diff options
author | Graeme Geldenhuys <graeme@mastermaths.co.za> | 2011-07-23 22:40:34 +0200 |
---|---|---|
committer | Graeme Geldenhuys <graeme@mastermaths.co.za> | 2011-07-23 22:40:34 +0200 |
commit | d2d9660e01e653f62f15d73e52f5b92470863acd (patch) | |
tree | 9afbe5710021192a42081f195a0c9da2286f6656 /docview | |
parent | 26b9f1e9a89abbf0678812b4c421ee8e5399b6b8 (diff) | |
download | fpGUI-d2d9660e01e653f62f15d73e52f5b92470863acd.tar.xz |
TRichTextLayout & TLayoutLine code reworked to classes instead of arrays
- TLayoutLine changed from a record type to a data class
- Implemented TLayoutLineList class instead of using a dynamic array
for TLayoutLine storage.
- Changed all related code to reference the object list correctly.
Diffstat (limited to 'docview')
-rw-r--r-- | docview/components/richtext/RichTextDisplayUnit.pas | 2 | ||||
-rw-r--r-- | docview/components/richtext/RichTextLayoutUnit.pas | 135 | ||||
-rw-r--r-- | docview/components/richtext/RichTextView.pas | 53 |
3 files changed, 115 insertions, 75 deletions
diff --git a/docview/components/richtext/RichTextDisplayUnit.pas b/docview/components/richtext/RichTextDisplayUnit.pas index 5f5f8ac1..67914de8 100644 --- a/docview/components/richtext/RichTextDisplayUnit.pas +++ b/docview/components/richtext/RichTextDisplayUnit.pas @@ -306,7 +306,7 @@ ProfileEvent('DEBUG: DrawRichTextLayout >>>'); //FontManager.Canvas.DrawLine(0, y, 300, y); repeat - Line := Layout.FLines^[ LineIndex ]; + Line := Layout.FLines[LineIndex]; BottomOfLine := Y; if // the line is in the range to be drawn diff --git a/docview/components/richtext/RichTextLayoutUnit.pas b/docview/components/richtext/RichTextLayoutUnit.pas index b5a324b5..004c2ef1 100644 --- a/docview/components/richtext/RichTextLayoutUnit.pas +++ b/docview/components/richtext/RichTextLayoutUnit.pas @@ -12,10 +12,13 @@ Uses CanvasFontManager, RichTextDocumentUnit, RichTextStyleUnit, - fpg_imagelist; + fpg_imagelist, + contnrs; Type - TLayoutLine = record + + TLayoutLine = class(TObject) + public Text: PChar; Length: longint; Height: longint; @@ -28,7 +31,18 @@ Type end; - TLinesArray = array[ 0..0 ] of TLayoutLine; + TLayoutLineList = class(TObjectList) + protected + function GetItem(Index: Integer): TLayoutLine; reintroduce; + procedure SetItem(Index: Integer; const AValue: TLayoutLine); reintroduce; + public + function Add(AObject: TLayoutLine): Integer; reintroduce; + function Remove(AObject: TLayoutLine): Integer; reintroduce; + function IndexOf(AObject: TLayoutLine): Integer; reintroduce; + function First: TLayoutLine; reintroduce; + Function Last: TLayoutLine; reintroduce; + property Items[Index: Integer]: TLayoutLine read GetItem write SetItem; default; + end; TTextPosition = @@ -53,7 +67,6 @@ Type FFontManager: TCanvasFontManager; FText: PChar; FImages: TfpgImageList; - FAllocatedNumLines: Longint; FLayoutWidth: longint; // The target width for the layout. Used for centreing/right align FWidth: longint; // The actual width of the text. May be wider due to unaligned // parts or bitmaps or width so small individual characters don't fit. @@ -62,8 +75,7 @@ Type FHorizontalImageScale: double; FVerticalImageScale: double; public - // Internal layout data - FLines: ^TLinesArray; + FLines: TLayoutLineList; FNumLines: longint; FRichTextSettings: TRichTextSettings; // Drawing functions @@ -116,6 +128,46 @@ Type Implementation + +{ TLayoutLineList } + +function TLayoutLineList.GetItem(Index: Integer): TLayoutLine; +begin + inherited GetItem(Index); +end; + +procedure TLayoutLineList.SetItem(Index: Integer; const AValue: TLayoutLine); +begin + inherited SetItem(Index, AValue); +end; + +function TLayoutLineList.Add(AObject: TLayoutLine): Integer; +begin + Result := inherited Add(AObject); +end; + +function TLayoutLineList.Remove(AObject: TLayoutLine): Integer; +begin + Result := inherited Remove(AObject); +end; + +function TLayoutLineList.IndexOf(AObject: TLayoutLine): Integer; +begin + Result := inherited IndexOf(AObject); +end; + +function TLayoutLineList.First: TLayoutLine; +begin + Result := TLayoutLine(inherited First); +end; + +function TLayoutLineList.Last: TLayoutLine; +begin + Result := TLayoutLine(inherited Last); +end; + + +{ TRichTextLayout } Uses SysUtils ,ACLStringUtility @@ -138,9 +190,8 @@ ProfileEvent('DEBUG: TRichTextLayout.Create >>>>'); FRichTextSettings := RichTextSettings; FImages := Images; FText := Text; - FAllocatedNumLines := 10; ProfileEvent('DEBUG: TRichTextLayout.Create 1 of 4'); - GetMem( FLines, FAllocatedNumLines * sizeof( TLayoutLine ) ); + FLines := TLayoutLineList.Create; FNumLines := 0; FLinks := TStringList.Create; FLinks.Duplicates := dupIgnore; @@ -161,41 +212,30 @@ end; Destructor TRichTextLayout.Destroy; Begin - FreeMem( Flines, FAllocatedNumLines * sizeof( TLayoutLine ) ); - FLines := nil; + ProfileEvent('TRichTextLayout.Destroy ******* '); + FreeAndNil(FLines); FLinks.Free; - Inherited Destroy; + inherited Destroy; End; Procedure TRichTextLayout.AddLineStart(var Line: TLayoutLine); -var - NewAllocation: longint; begin - if FNumLines >= FAllocatedNumLines then - begin - // reallocate the array twice the size - NewAllocation := FAllocatedNumLines * 2; - FLines := ReAllocMem( FLines, -// FAllocatedNumLines * sizeof( TLayoutLine ), - NewAllocation * sizeof( TLayoutLine ) ); - FAllocatedNumLines := NewAllocation; - end; - FLines^[ FNumLines ] := Line; + FLines.Add(Line); inc( FNumLines ); - ProfileEvent(' DEBUG: TRichTextLayout.AddLineStart: FNumLines =' + intToStr(FNumLines)); + ProfileEvent('TRichTextLayout.AddLineStart: FNumLines =' + intToStr(FNumLines)); end; Procedure TRichTextLayout.PerformStyleTag( Const Tag: TTag; Var Style: TTextDrawStyle; const X: longint ); begin -ProfileEvent('DEBUG: TRichTextLayout.PerformStyleTag >>>'); +ProfileEvent('TRichTextLayout.PerformStyleTag >>>'); ApplyStyleTag( Tag, Style, FFontManager, FRichTextSettings, X ); -ProfileEvent('DEBUG: TRichTextLayout.PerformStyleTag <<<'); +ProfileEvent('TRichTextLayout.PerformStyleTag <<<'); end; // Check the current font specifications and see if the @@ -230,7 +270,7 @@ end; // Main procedure: reads through the whole text currently stored // and breaks up into lines - each represented as a TLayoutLine in -// the array FLines[ 0.. FNumLines ] +// the LayoutLineList class Procedure TRichTextLayout.Layout; Var CurrentLine: TLayoutLine; @@ -266,8 +306,10 @@ Var CurrentLine.Width := EndX; if CurrentLine.Width > FWidth then FWidth := CurrentLine.Width; - assert( CurrentLine.Height > 0 ); // we must have set the line height! + Assert( CurrentLine.Height > 0 ); // we must have set the line height! AddLineStart( CurrentLine ); + + CurrentLine := TLayoutLine.Create; CurrentLine.Text := NextLine; CurrentLine.Style := Style; CurrentLine.Height := 0; @@ -276,6 +318,7 @@ Var CurrentLine.Width := 0; CurrentLine.LinkIndex := CurrentLinkIndex; CurrentLine.Wrapped := false; + assert( CurrentLinkIndex >= -1 ); assert( CurrentLinkIndex < FLinks.Count ); WordStartX := Style.LeftMargin; @@ -294,6 +337,8 @@ ProfileEvent('DEBUG: TRichTextLayout.Layout >>>>'); ApplyStyle( Style, FFontManager ); CurrentLinkIndex := -1; P := FText; // P is the current search position + + CurrentLine := TLayoutLine.Create; CurrentLine.Text := P; CurrentLine.Style := Style; CurrentLine.Height := 0; @@ -302,6 +347,7 @@ ProfileEvent('DEBUG: TRichTextLayout.Layout >>>>'); CurrentLine.Width := 0; CurrentLine.LinkIndex := -1; CurrentLine.Wrapped := false; + WordStartX := Style.LeftMargin; WordX := 0; WrapX := FLayoutWidth - FRichTextSettings.Margins.Right; @@ -631,7 +677,7 @@ Var StartedDrawing: boolean; fstyle: string; begin - Line := TLayoutLine(FLines[ LineIndex ]); + Line := FLines[LineIndex]; P := Line.Text; EndP := Line.Text + Line.Length; Style := Line.Style; @@ -731,7 +777,7 @@ Var NewMarginX: longint; fStyle: string; begin - Line := TLayoutLine(FLines[ LineIndex ]); + Line := FLines[LineIndex]; P := Line.Text; EndP := Line.Text + Line.Length; @@ -811,12 +857,13 @@ begin if YToFind < Y then begin Result := tpAboveText; - exit; + Exit; //==> end; + // TODO: Replace FNumLines with FLines.Count-1 while LineIndex < FNumLines do begin - LineHeight := TLayoutLine(FLines[ LineIndex ]).Height; + LineHeight := FLines[LineIndex].Height; if ( YToFind >= Y ) and ( YToFind < (Y + LineHeight)) then begin @@ -831,7 +878,7 @@ begin end; LineIndex := FNumLines - 1; - Remainder := TLayoutLine(FLines[ LineIndex ]).Height; + Remainder := FLines[LineIndex].Height; Result := tpBelowText; end; @@ -856,7 +903,7 @@ begin tpBelowText: begin - Offset := TLayoutLine(FLines[ LineIndex ]).Length; + Offset := FLines[LineIndex].Length; exit; end; end; @@ -875,17 +922,16 @@ var begin Result := 0; if Index <= 0 then - exit; + Exit; //==> while Result < FNumLines do begin - LineCharIndex := GetCharIndex( TLayoutLine(FLines[ Result ]).Text ); - LineLength := TLayoutLine(FLines[ Result ]).Length; - if LineCharIndex + LineLength - > Index then + LineCharIndex := GetCharIndex(FLines[Result].Text ); + LineLength := FLines[Result].Length; + if (LineCharIndex + LineLength) > Index then begin // found - exit; + Exit; //==> end; inc( Result ); end; @@ -895,7 +941,7 @@ end; function TRichTextLayout.GetOffsetFromCharIndex( Index: longint; Line: longint ): longint; begin - Result := Index - GetCharIndex( TLayoutLine( FLines[ Line ] ).Text ); + Result := Index - GetCharIndex(FLines[Line].Text); end; function TRichTextLayout.GetElementWidth( Element: TTextElement ): longint; @@ -939,8 +985,7 @@ begin dec( line ); while line >= 0 do begin - inc( Result, - TLayoutLine(Flines[ Line ]).Height ); + inc( Result, Flines[Line].Height ); dec( line ); end; end; @@ -957,12 +1002,12 @@ begin if FNumLines = 0 then begin Result := ''; - exit; + Exit; //==> end; LineIndex := GetLineFromCharIndex( CharIndexToFind ); - Line := TLayoutLine(FLines[ LineIndex ]); + Line := FLines[LineIndex]; P := Line.Text; EndP := Line.Text + Line.Length; diff --git a/docview/components/richtext/RichTextView.pas b/docview/components/richtext/RichTextView.pas index a0234468..0b183ff8 100644 --- a/docview/components/richtext/RichTextView.pas +++ b/docview/components/richtext/RichTextView.pas @@ -1121,7 +1121,7 @@ begin // below the bottom Result := tpBelowTextArea; LineIndex := FLayout.FNumLines; - Offset := FLayout.FLines^[ FLayout.FNumLines - 1 ].Length - 1; + Offset := FLayout.FLines[FLayout.FNumLines-1].Length - 1; exit; end; @@ -1319,7 +1319,7 @@ begin DrawHeight := TextRect.Top - TextRect.Bottom; DrawWidth := TextRect.Right - TextRect.Left; - Line := FLayout.FLines^[ CursorRow ]; + Line := FLayout.FLines[CursorRow]; LineHeight := Line.Height; Y := DrawHeight @@ -1347,7 +1347,7 @@ begin TextHeight := FFontManager.CharHeight; Descender := FFontManager.CharDescender; - MaxDescender := FLayout.FLines^[ CursorRow ].MaxDescender; + MaxDescender := FLayout.FLines[CursorRow].MaxDescender; CursorHeight := TextHeight; dec( Y, LineHeight - 1 ); @@ -1397,7 +1397,7 @@ begin if LastLine = -1 then exit; - LineHeight := FLayout.FLines^[ LastLine ].Height; + LineHeight := FLayout.FLines[LastLine].Height; if LastLine = FLayout.FNumLines - 1 then begin @@ -1418,7 +1418,7 @@ begin // more than half line already displayed so if LastLine < FLayout.FNumLines - 1 then // AND to make next line fully visible - inc( Result, FLayout.FLines^[ LastLine + 1 ].Height ); + inc( Result, FLayout.FLines[LastLine+1].Height ); end; Function TRichTextView.GetSmallDownScrollPosition: longint; @@ -1436,7 +1436,7 @@ begin // Now limit the scrolling to max text height for the bottom line Diff := Result - FVScrollBar.Position; - LineTextHeight := FLayout.FLines^[ LastLine ].MaxTextHeight; + LineTextHeight := FLayout.FLines[LastLine].MaxTextHeight; if Diff > LineTextHeight then Diff := LineTextHeight; Result := FVScrollBar.Position + Diff; @@ -1456,7 +1456,7 @@ begin // Now limit the scrolling to max text height for the bottom line Diff := FVScrollBar.Position - Result; - LineTextHeight := FLayout.FLines^[ FirstVisibleLine ].MaxTextHeight; + LineTextHeight := FLayout.FLines[FirstVisibleLine].MaxTextHeight; if Diff > LineTextHeight then Diff := LineTextHeight; Result := FVScrollBar.Position - Diff; @@ -1504,11 +1504,11 @@ begin // scroll so that top line is fully visible... Result := FVScrollBar.Position - Offset; - if Offset < (FLayout.FLines^[ FirstVisibleLine ].Height div 2) then + if Offset < (FLayout.FLines[FirstVisibleLine].Height div 2) then // more than half the line was already displayed so if FirstVisibleLine > 0 then // AND to make next line up visible - dec( Result, FLayout.FLines^[ FirstVisibleLine - 1 ].Height ); + dec( Result, FLayout.FLines[FirstVisibleLine-1].Height ); end; Function Sign( arg: longint ): longint; @@ -2033,7 +2033,7 @@ begin Result := -1; exit; end; - Result := FLayout.GetCharIndex( FLayout.FLines^[ FCursorRow ].Text ) + FCursorOffset; + Result := FLayout.GetCharIndex( FLayout.FLines[FCursorRow].Text ) + FCursorOffset; end; procedure TRichTextView.RefreshCursorPosition; @@ -2059,20 +2059,15 @@ begin end; Row := FLayout.GetLineFromCharIndex( Index ); - SetCursorPosition( Index - FLayout.GetCharIndex( FLayout.FLines^[ Row ].Text ), - Row, - true ); + SetCursorPosition( Index - FLayout.GetCharIndex( FLayout.FLines[Row].Text ), Row, true ); end; -procedure TRichTextView.SetCursorIndex( Index: longint; - PreserveSelection: boolean ); +procedure TRichTextView.SetCursorIndex( Index: longint; PreserveSelection: boolean ); var Row: longint; begin Row := FLayout.GetLineFromCharIndex( Index ); - SetCursorPosition( Index - FLayout.GetCharIndex( FLayout.FLines^[ Row ].Text ), - Row, - PreserveSelection ); + SetCursorPosition( Index - FLayout.GetCharIndex( FLayout.FLines[Row].Text ), Row, PreserveSelection ); SetupCursor; end; @@ -2085,7 +2080,7 @@ begin RemoveCursor; FCursorOffset := Offset; FCursorRow := Row; - Index := FLayout.GetCharIndex( FLayout.FLines^[ Row ].Text ) + Offset; + Index := FLayout.GetCharIndex( FLayout.FLines[Row].Text ) + Offset; //writeln(' SetCursorPosition: offset=', FCursorOffset, ' row=', FCursorRow, ' index=', Index); exit; { TODO: Complete this selection of text code - currently gives AV's } @@ -2123,7 +2118,7 @@ begin // exit; // SetCursorIndex( GetCharIndex( P ), PreserveSelection ); - Line := FLayout.FLines^[ CursorRow ]; + Line := FLayout.FLines[CursorRow]; NewOffset := PCharDiff( P, Line.Text ); if NewOffset < Line.Length then begin @@ -2163,7 +2158,7 @@ begin // if Element.ElementType = teTextEnd then // exit; - Line := FLayout.FLines^[ CursorRow ]; + Line := FLayout.FLines[CursorRow]; NewOffset := PCharDiff( P, Line.Text ); if NewOffset >= 0 then begin @@ -2173,7 +2168,7 @@ begin begin if FCursorRow <= 0 then exit; - Line := FLayout.FLines^[ CursorRow - 1 ]; + Line := FLayout.FLines[CursorRow-1]; if Line.Wrapped then SetCursorPosition( Line.Length - 1, FCursorRow - 1, PreserveSelection ) else @@ -2211,7 +2206,7 @@ Procedure TRichTextView.CursorToLineStart( PreserveSelection: boolean ); Var Line: TLayoutLine; begin - Line := FLayout.FLines^[ FCursorRow ]; + Line := FLayout.FLines[FCursorRow]; SetCursorPosition( 0, FCursorRow, PreserveSelection ); SetupCursor; end; @@ -2220,7 +2215,7 @@ Procedure TRichTextView.CursorToLineEnd( PreserveSelection: boolean ); Var Line: TLayoutLine; begin - Line := FLayout.FLines^[ FCursorRow ]; + Line := FLayout.FLines[FCursorRow]; SetCursorPosition( Line.Length, FCursorRow, PreserveSelection ); SetupCursor; end; @@ -2281,7 +2276,7 @@ begin if NewRow >= FLayout.FNumLines - 1 then break; - Distance := Distance + FLayout.FLines^[ NewRow ].Height; + Distance := Distance + FLayout.FLines[NewRow].Height; inc( NewRow ); end; @@ -2306,7 +2301,7 @@ begin if NewRow <= 0 then break; dec( NewRow ); - Distance := Distance + FLayout.FLines^[ NewRow ].Height; + Distance := Distance + FLayout.FLines[NewRow].Height; end; FLayout.GetXFromOffset( FCursorOffset, FCursorRow, X ); @@ -2676,7 +2671,7 @@ begin GetFirstVisibleLine( LineIndex, Y ); if LineIndex >= 0 then - Result := FLayout.GetCharIndex( FLayout.FLines^[ LineIndex ].Text ) + Result := FLayout.GetCharIndex( FLayout.FLines[LineIndex].Text ) else Result := 0; end; @@ -2750,7 +2745,7 @@ begin exit; if ( Row = BottomLine ) - and ( Offset >= FLayout.FLines^[ BottomLine ].Height - 1 ) then + and ( Offset >= FLayout.FLines[BottomLine].Height - 1 ) then // bottom row already entirely visible exit; @@ -2778,7 +2773,7 @@ begin if ( BottomLine <> -1 ) and ( Row >= BottomLine ) then SetVerticalPosition( FLayout.GetLinePosition( Row ) - + FLayout.FLines^[ Row ].Height + + FLayout.FLines[Row].Height - GetTextAreaHeight ); end; end; |