Adjusting paragraph border, background and indents
Posted: Wed Jan 11, 2017 12:07 pm
For paragraphs in TRichView, offsets of borders, background, and indents are defined independently. All offsets are counted from contents.
On one hand, this approach allows making interesting effects, like
On the other hand, if SpaceBefore, SpaceAfter, LeftIndent, RightIndent are not large enough, border and background may overlap adjacent paragraphs (if you use RichViewActions, they always assign spacing and indents large enough, but if you do it manually, this overlapping may happen).
Also, not all combinations are possible in HTML or Microsoft Word. In HTML, border is always drawn exactly inside background. In MS Word, border is drawn exactly outside background.
So, if your application is primarily designed for HTML/RTF/DocX export, you may wish to make the same border/background relation in TRichView.
The procedure below adjusts border, background, and intents of all paragraphs in existing documents. It always makes indents (SpaceBefore, SpaceAfter, LeftIndent, RightIndent) large enough to cover border and background.
Additionally, it adjusts borders and background; there are some options, see below.
Test:
Options for BorderMode parameter:
* bmFree - border and background are not changed
* bmAroundBackground - border is changed so it is outside background (spacing between them is possible)
* bmBackgroundInBorder - background is changed to external side of border (this option corresponds to HTML)
* bmAroundBackgroundNoSpacing - border is changed so it is outside background (without spacing between them) (this option corresponds to Microsoft Word formats)
Update: MoveInside() corrected
On one hand, this approach allows making interesting effects, like
On the other hand, if SpaceBefore, SpaceAfter, LeftIndent, RightIndent are not large enough, border and background may overlap adjacent paragraphs (if you use RichViewActions, they always assign spacing and indents large enough, but if you do it manually, this overlapping may happen).
Also, not all combinations are possible in HTML or Microsoft Word. In HTML, border is always drawn exactly inside background. In MS Word, border is drawn exactly outside background.
So, if your application is primarily designed for HTML/RTF/DocX export, you may wish to make the same border/background relation in TRichView.
The procedure below adjusts border, background, and intents of all paragraphs in existing documents. It always makes indents (SpaceBefore, SpaceAfter, LeftIndent, RightIndent) large enough to cover border and background.
Additionally, it adjusts borders and background; there are some options, see below.
Code: Select all
type
TBorderMode = (bmFree, bmAroundBackground, bmBackgroundInBorder, bmAroundBackgroundNoSpacing);
procedure NormalizePara(ParaInfo: TParaInfo; BorderMode: TBorderMode);
procedure NormalizeIndents(Offsets: TRVRect; w: Integer);
begin
if ParaInfo.LeftIndent < Offsets.Left + w then
ParaInfo.LeftIndent := Offsets.Left + w;
if ParaInfo.SpaceBefore < Offsets.Top + w then
ParaInfo.SpaceBefore := Offsets.Top + w;
if ParaInfo.RightIndent < Offsets.Right + w then
ParaInfo.RightIndent := Offsets.Right + w;
if ParaInfo.SpaceAfter < Offsets.Bottom + w then
ParaInfo.SpaceAfter := Offsets.Bottom + w;
end;
procedure MakeNonNegative(Offsets: TRVRect);
begin
Offsets.Left := Max(Offsets.Left, 0);
Offsets.Right := Max(Offsets.Right, 0);
Offsets.Top := Max(Offsets.Top, 0);
Offsets.Bottom := Max(Offsets.Bottom, 0);
end;
procedure MakeOffsetsAtLeast(Offsets, SampleOffsets: TRVRect);
begin
Offsets.Left := Max(Offsets.Left, SampleOffsets.Left);
Offsets.Right := Max(Offsets.Right, SampleOffsets.Right);
Offsets.Top := Max(Offsets.Top, SampleOffsets.Top);
Offsets.Bottom := Max(Offsets.Bottom, SampleOffsets.Bottom);
end;
procedure MoveInside(Offsets, SampleOffsets: TRVRect; w: Integer);
begin
Offsets.Left := SampleOffsets.Left + w;
Offsets.Right := SampleOffsets.Right + w;
Offsets.Top := SampleOffsets.Top + w;
Offsets.Bottom := SampleOffsets.Bottom + w;
end;
begin
MakeNonNegative(ParaInfo.Border.BorderOffsets);
MakeNonNegative(ParaInfo.Background.BorderOffsets);
if ParaInfo.Border.Style <> rvbNone then
begin
case BorderMode of
bmAroundBackground:
MakeOffsetsAtLeast(ParaInfo.Border.BorderOffsets,
ParaInfo.Background.BorderOffsets);
bmBackgroundInBorder:
if ParaInfo.Background.Color <> clNone then
MoveInside(ParaInfo.Background.BorderOffsets,
ParaInfo.Border.BorderOffsets,
ParaInfo.Border.GetTotalWidth);
bmAroundBackgroundNoSpacing:
ParaInfo.Border.BorderOffsets.Assign(ParaInfo.Background.BorderOffsets);
end;
NormalizeIndents(ParaInfo.Border.BorderOffsets,
ParaInfo.Border.GetTotalWidth);
end;
if ParaInfo.Background.Color <> clNone then
NormalizeIndents(ParaInfo.Background.BorderOffsets, 0);
end;
procedure NormalizeParagraphs(RVStyle: TRVStyle; BorderMode: TBorderMode);
var
i: Integer;
begin
for i := 0 to RVStyle.ParaStyles.Count - 1 do
NormalizePara(RVStyle.ParaStyles[i], BorderMode);
end;
Code: Select all
procedure TForm3.ToolButton63Click(Sender: TObject);
begin
NormalizeParagraphs(RichViewEdit1.Style, bmBackgroundInBorder);
RichViewEdit1.Format;
end;
* bmFree - border and background are not changed
* bmAroundBackground - border is changed so it is outside background (spacing between them is possible)
* bmBackgroundInBorder - background is changed to external side of border (this option corresponds to HTML)
* bmAroundBackgroundNoSpacing - border is changed so it is outside background (without spacing between them) (this option corresponds to Microsoft Word formats)
Update: MoveInside() corrected