SynEdit: refactor painting

git-svn-id: trunk@34863 -
This commit is contained in:
martin 2012-01-22 13:17:30 +00:00
parent 4065155e57
commit d90f4b44fe
8 changed files with 178 additions and 86 deletions

View File

@ -5,7 +5,7 @@ unit LazSynTextArea;
interface interface
uses uses
Classes, SysUtils, Graphics, LCLType, LCLIntf, LCLProc, Classes, SysUtils, Graphics, Controls, LCLType, LCLIntf, LCLProc,
SynEditTypes, SynEditMiscProcs, SynEditMiscClasses, LazSynEditText, SynEditTypes, SynEditMiscProcs, SynEditMiscClasses, LazSynEditText,
SynEditMarkup, SynEditHighlighter, SynTextDrawer; SynEditMarkup, SynEditHighlighter, SynTextDrawer;
@ -57,9 +57,10 @@ type
FirstCol, LastCol: integer); virtual; FirstCol, LastCol: integer); virtual;
property Canvas: TCanvas read FCanvas; property Canvas: TCanvas read FCanvas;
public public
constructor Create(ATextDrawer: TheTextDrawer); constructor Create(AOwner: TWinControl; ATextDrawer: TheTextDrawer);
//constructor Create(AOwner : TSynEditBase; ATextDrawer: TheTextDrawer);
destructor Destroy; override; destructor Destroy; override;
procedure Assign(Src: TLazSynSurface); override;
procedure InvalidateLines(FirstLine, LastLine: TLineIdx); override;
function ScreenColumnToXValue(Col: integer): integer; // map screen column to screen pixel function ScreenColumnToXValue(Col: integer): integer; // map screen column to screen pixel
function RowColumnToPixels(const RowCol: TPoint): TPoint; function RowColumnToPixels(const RowCol: TPoint): TPoint;
@ -85,6 +86,7 @@ type
property DisplayView: TLazSynDisplayView read FDisplayView write FDisplayView; property DisplayView: TLazSynDisplayView read FDisplayView write FDisplayView;
property Highlighter: TSynCustomHighlighter read FHighlighter write FHighlighter; property Highlighter: TSynCustomHighlighter read FHighlighter write FHighlighter;
property MarkupManager: TSynEditMarkupManager read FMarkupManager write FMarkupManager; property MarkupManager: TSynEditMarkupManager read FMarkupManager write FMarkupManager;
property TextDrawer: TheTextDrawer read FTextDrawer;
public public
property TextBounds: TRect read FTextBounds; property TextBounds: TRect read FTextBounds;
@ -109,7 +111,8 @@ type
procedure DoPaint(ACanvas: TCanvas; AClip: TRect); override; procedure DoPaint(ACanvas: TCanvas; AClip: TRect); override;
procedure BoundsChanged; override; procedure BoundsChanged; override;
public public
constructor Create; constructor Create(AOwner: TWinControl);
procedure InvalidateLines(FirstLine, LastLine: TLineIdx); override;
property TextArea: TLazSynTextArea read FTextArea write FTextArea; property TextArea: TLazSynTextArea read FTextArea write FTextArea;
property LeftGutterArea: TLazSynSurface read FLeftGutterArea write FLeftGutterArea; property LeftGutterArea: TLazSynSurface read FLeftGutterArea write FLeftGutterArea;
property RightGutterArea: TLazSynSurface read FRightGutterArea write FRightGutterArea; property RightGutterArea: TLazSynSurface read FRightGutterArea write FRightGutterArea;
@ -154,12 +157,30 @@ begin
FRightGutterArea.SetBounds(Top, r, Bottom, Right); FRightGutterArea.SetBounds(Top, r, Bottom, Right);
end; end;
constructor TLazSynSurfaceManager.Create; constructor TLazSynSurfaceManager.Create(AOwner: TWinControl);
begin begin
inherited Create(AOwner);
FLeftGutterWidth := 0; FLeftGutterWidth := 0;
FRightGutterWidth := 0; FRightGutterWidth := 0;
end; end;
procedure TLazSynSurfaceManager.InvalidateLines(FirstLine, LastLine: TLineIdx);
var
rcInval: TRect;
begin
rcInval := Bounds;
if (FirstLine >= 0) then
rcInval.Top := TextArea.TextBounds.Top + FirstLine * TextArea.LineHeight;
if (LastLine >= 0) then
rcInval.Bottom := TextArea.TextBounds.Top + LastLine * TextArea.LineHeight;
{$IFDEF VerboseSynEditInvalidate}
DebugLn(['TCustomSynEdit.InvalidateGutterLines ',DbgSName(self), ' FirstLine=',FirstLine, ' LastLine=',LastLine, ' rect=',dbgs(rcInval)]);
{$ENDIF}
if (rcInval.Top < rcInval.Bottom) and (rcInval.Left < rcInval.Right) then
InvalidateRect(Handle, @rcInval, FALSE);
end;
{ TLazSynTextArea } { TLazSynTextArea }
function TLazSynTextArea.GetPadding(Side: TLazSynBorderSide): integer; function TLazSynTextArea.GetPadding(Side: TLazSynBorderSide): integer;
@ -252,10 +273,11 @@ begin
if Result.Y < 0 then Result.Y := 0; if Result.Y < 0 then Result.Y := 0;
end; end;
constructor TLazSynTextArea.Create(ATextDrawer: TheTextDrawer); constructor TLazSynTextArea.Create(AOwner: TWinControl; ATextDrawer: TheTextDrawer);
var var
i: TLazSynBorderSide; i: TLazSynBorderSide;
begin begin
inherited Create(AOwner);
FTextDrawer := ATextDrawer; FTextDrawer := ATextDrawer;
FTextDrawer.RegisterOnFontChangeHandler(@DoDrawerFontChanged); FTextDrawer.RegisterOnFontChangeHandler(@DoDrawerFontChanged);
FPaintLineColor := TSynSelectedColor.Create; FPaintLineColor := TSynSelectedColor.Create;
@ -278,6 +300,53 @@ begin
inherited Destroy; inherited Destroy;
end; end;
procedure TLazSynTextArea.Assign(Src: TLazSynSurface);
var
i: TLazSynBorderSide;
begin
inherited Assign(Src);
FTextDrawer := TLazSynTextArea(Src).FTextDrawer;
FTheLinesView := TLazSynTextArea(Src).FTheLinesView;
FDisplayView := TLazSynTextArea(Src).FDisplayView;
FHighlighter := TLazSynTextArea(Src).FHighlighter;
FMarkupManager := TLazSynTextArea(Src).FMarkupManager;
FForegroundColor := TLazSynTextArea(Src).FForegroundColor;
FBackgroundColor := TLazSynTextArea(Src).FBackgroundColor;
FRightEdgeColor := TLazSynTextArea(Src).FRightEdgeColor;
FExtraCharSpacing := TLazSynTextArea(Src).FExtraCharSpacing;
FExtraLineSpacing := TLazSynTextArea(Src).FExtraLineSpacing;
FVisibleSpecialChars := TLazSynTextArea(Src).FVisibleSpecialChars;
FRightEdgeColumn := TLazSynTextArea(Src).FRightEdgeColumn;
FRightEdgeVisible := TLazSynTextArea(Src).FRightEdgeVisible;
for i := low(TLazSynBorderSide) to high(TLazSynBorderSide) do
FPadding[i] := TLazSynTextArea(Src).FPadding[i];
FTopLine := TLazSynTextArea(Src).FTopLine;
FLeftChar := TLazSynTextArea(Src).FLeftChar;
BoundsChanged;
end;
procedure TLazSynTextArea.InvalidateLines(FirstLine, LastLine: TLineIdx);
var
rcInval: TRect;
begin
rcInval := Bounds;
if (FirstLine >= 0) then
rcInval.Top := TextBounds.Top + FirstLine * LineHeight;
if (LastLine >= 0) then
rcInval.Bottom := TextBounds.Top + LastLine * LineHeight;
{$IFDEF VerboseSynEditInvalidate}
DebugLn(['TCustomSynEdit.InvalidateGutterLines ',DbgSName(self), ' FirstLine=',FirstLine, ' LastLine=',LastLine, ' rect=',dbgs(rcInval)]);
{$ENDIF}
if (rcInval.Top < rcInval.Bottom) and (rcInval.Left < rcInval.Right) then
InvalidateRect(Handle, @rcInval, FALSE);
end;
procedure TLazSynTextArea.FontChanged; procedure TLazSynTextArea.FontChanged;
begin begin
// ToDo: wait for handle creation // ToDo: wait for handle creation
@ -947,7 +1016,7 @@ var
// Initialize rcLine for drawing. Note that Top and Bottom are updated // Initialize rcLine for drawing. Note that Top and Bottom are updated
// inside the loop. Get only the starting point for this. // inside the loop. Get only the starting point for this.
rcLine := AClip; rcLine := AClip;
rcLine.Bottom := FirstLine * fTextHeight; rcLine.Bottom := TextBounds.Top + FirstLine * fTextHeight;
TV := TopLine - 1; TV := TopLine - 1;

View File

@ -432,9 +432,6 @@ type
FStrings: TStrings; // External TStrings based interface to the Textbuffer FStrings: TStrings; // External TStrings based interface to the Textbuffer
FTopLinesView: TSynEditStrings; // The linesview that holds the real line-buffer/FLines FTopLinesView: TSynEditStrings; // The linesview that holds the real line-buffer/FLines
FDisplayView: TLazSynDisplayView; FDisplayView: TLazSynDisplayView;
FTextArea: TLazSynTextArea;
FLeftGutterArea, FRightGutterArea: TLazSynGutterArea;
FPaintArea: TLazSynSurfaceManager;
fExtraCharSpacing: integer; fExtraCharSpacing: integer;
fMaxLeftChar: Integer; // 1024 fMaxLeftChar: Integer; // 1024
@ -666,8 +663,11 @@ type
protected protected
{$IFDEF EnableDoubleBuf} {$IFDEF EnableDoubleBuf}
BufferBitmap: TBitmap; // the double buffer BufferBitmap: TBitmap; // the double buffer
{$ENDIF}
SavedCanvas: TCanvas; // the normal TCustomControl canvas during paint SavedCanvas: TCanvas; // the normal TCustomControl canvas during paint
{$ENDIF}
FTextArea: TLazSynTextArea;
FLeftGutterArea, FRightGutterArea: TLazSynGutterArea;
FPaintArea: TLazSynSurfaceManager;
procedure Paint; override; procedure Paint; override;
procedure StartPaintBuffer(const ClipRect: TRect); procedure StartPaintBuffer(const ClipRect: TRect);
@ -1903,7 +1903,7 @@ begin
FLastMousePoint := Point(-1,-1); FLastMousePoint := Point(-1,-1);
fBlockIndent := 2; fBlockIndent := 2;
FTextArea := TLazSynTextArea.Create(FTextDrawer); FTextArea := TLazSynTextArea.Create(Self, FTextDrawer);
FTextArea.RightEdgeVisible := not(eoHideRightMargin in SYNEDIT_DEFAULT_OPTIONS); FTextArea.RightEdgeVisible := not(eoHideRightMargin in SYNEDIT_DEFAULT_OPTIONS);
FTextArea.ExtraCharSpacing := 0; FTextArea.ExtraCharSpacing := 0;
FTextArea.ExtraLineSpacing := 0; FTextArea.ExtraLineSpacing := 0;
@ -1912,14 +1912,15 @@ begin
FTextArea.DisplayView := FDisplayView; FTextArea.DisplayView := FDisplayView;
FTextArea.Highlighter := nil; FTextArea.Highlighter := nil;
FLeftGutterArea := TLazSynGutterArea.Create; FLeftGutterArea := TLazSynGutterArea.Create(Self);
FLeftGutterArea.TextArea := FTextArea; FLeftGutterArea.TextArea := FTextArea;
FLeftGutterArea.Gutter := FLeftGutter; FLeftGutterArea.Gutter := FLeftGutter;
FRightGutterArea := TLazSynGutterArea.Create;
FRightGutterArea := TLazSynGutterArea.Create(Self);
FRightGutterArea.TextArea := FTextArea; FRightGutterArea.TextArea := FTextArea;
FRightGutterArea.Gutter := FRightGutter; FRightGutterArea.Gutter := FRightGutter;
FPaintArea := TLazSynSurfaceManager.Create; FPaintArea := TLazSynSurfaceManager.Create(Self);
FPaintArea.TextArea := FTextArea; FPaintArea.TextArea := FTextArea;
FPaintArea.LeftGutterArea := FLeftGutterArea; FPaintArea.LeftGutterArea := FLeftGutterArea;
FPaintArea.RightGutterArea := FRightGutterArea; FPaintArea.RightGutterArea := FRightGutterArea;
@ -2146,7 +2147,7 @@ end;
destructor TCustomSynEdit.Destroy; destructor TCustomSynEdit.Destroy;
var var
i: integer; q,i: integer;
begin begin
Application.RemoveOnIdleHandler(@IdleScanRanges); Application.RemoveOnIdleHandler(@IdleScanRanges);
SurrenderPrimarySelection; SurrenderPrimarySelection;
@ -2466,22 +2467,8 @@ begin
if sfPainting in fStateFlags then exit; if sfPainting in fStateFlags then exit;
if Visible and HandleAllocated then if Visible and HandleAllocated then
if (FirstLine = -1) and (LastLine = -1) then begin if (FirstLine = -1) and (LastLine = -1) then begin
if FLeftGutter.Visible then begin; FLeftGutterArea.InvalidateLines(-1, -1);
rcInval := Rect(0, 0, FLeftGutter.Width, ClientHeight - ScrollBarWidth); FRightGutterArea.InvalidateLines(-1, -1);
{$IFDEF VerboseSynEditInvalidate}
DebugLn(['TCustomSynEdit.InvalidateGutterLines ',DbgSName(self),' ALL ',dbgs(rcInval)]);
{$ENDIF}
InvalidateRect(Handle, @rcInval, FALSE);
end;
// right gutter
if FRightGutter.Visible then begin
rcInval := Rect(ClientWidth - FRightGutter.Width - ScrollBarWidth, 0,
ClientWidth - ScrollBarWidth, ClientHeight - ScrollBarWidth);
{$IFDEF VerboseSynEditInvalidate}
DebugLn(['TCustomSynEdit.InvalidateGutterLines ',DbgSName(self),' ALL ',dbgs(rcInval)]);
{$ENDIF}
InvalidateRect(Handle, @rcInval, FALSE);
end;
end else begin end else begin
// pretend we haven't scrolled // pretend we haven't scrolled
TopFoldLine := FFoldedLinesView.TopLine; TopFoldLine := FFoldedLinesView.TopLine;
@ -2498,26 +2485,9 @@ begin
LastLine := LinesInWindow + 1; LastLine := LinesInWindow + 1;
FirstLine := RowToScreenRow(FirstLine); FirstLine := RowToScreenRow(FirstLine);
FirstLine := Max(0, FirstLine); FirstLine := Max(0, FirstLine);
{ any line visible? }
if (LastLine >= FirstLine) then begin FLeftGutterArea.InvalidateLines(FirstLine, LastLine);
if FLeftGutter.Visible then begin; FRightGutterArea.InvalidateLines(FirstLine, LastLine);
rcInval := Rect(0, LineHeight * FirstLine,
FLeftGutter.Width, LineHeight * LastLine);
{$IFDEF VerboseSynEditInvalidate}
DebugLn(['TCustomSynEdit.InvalidateGutterLines ',DbgSName(self),' PART ',dbgs(rcInval)]);
{$ENDIF}
InvalidateRect(Handle, @rcInval, FALSE);
end;
// right gutter
if FRightGutter.Visible then begin
rcInval.Left := ClientWidth - FRightGutter.Width - ScrollBarWidth;
rcInval.Right := ClientWidth - ScrollBarWidth;
{$IFDEF VerboseSynEditInvalidate}
DebugLn(['TCustomSynEdit.InvalidateGutterLines ',DbgSName(self),' PART ',dbgs(rcInval)]);
{$ENDIF}
InvalidateRect(Handle, @rcInval, FALSE);
end;
end;
FFoldedLinesView.TopLine := TopFoldLine; FFoldedLinesView.TopLine := TopFoldLine;
end; end;
@ -2532,13 +2502,7 @@ begin
if sfPainting in fStateFlags then exit; if sfPainting in fStateFlags then exit;
if Visible and HandleAllocated then if Visible and HandleAllocated then
if (FirstLine = -1) and (LastLine = -1) then begin if (FirstLine = -1) and (LastLine = -1) then begin
rcInval := ClientRect; FTextArea.InvalidateLines(-1, -1);
rcInval.Left := FTextArea.Bounds.Left;
rcInval.Right := FTextArea.Bounds.Right;
{$IFDEF VerboseSynEditInvalidate}
DebugLn(['TCustomSynEdit.InvalidateLines ',DbgSName(self),' ALL ',dbgs(rcInval)]);
{$ENDIF}
InvalidateRect(Handle, @rcInval, FALSE);
end else begin end else begin
// pretend we haven't scrolled // pretend we haven't scrolled
TopFoldLine := FFoldedLinesView.TopLine; TopFoldLine := FFoldedLinesView.TopLine;
@ -2555,15 +2519,8 @@ begin
l := LinesInWindow + 1; l := LinesInWindow + 1;
f := RowToScreenRow(FirstLine); f := RowToScreenRow(FirstLine);
f := Max(0, f); f := Max(0, f);
{ any line visible? }
if (l >= f) then begin FTextArea.InvalidateLines(F, L);
rcInval := Rect(FTextArea.Bounds.Left, LineHeight * f,
FTextArea.Bounds.Right, LineHeight * l);
{$IFDEF VerboseSynEditInvalidate}
DebugLn(['TCustomSynEdit.InvalidateLines ',DbgSName(self),' PART ',dbgs(rcInval)]);
{$ENDIF}
InvalidateRect(Handle, @rcInval, FALSE);
end;
FFoldedLinesView.TopLine := TopFoldLine; FFoldedLinesView.TopLine := TopFoldLine;
end; end;
@ -3431,8 +3388,8 @@ var
NewBufferHeight: Integer; NewBufferHeight: Integer;
{$ENDIF} {$ENDIF}
begin begin
if (SavedCanvas<>nil) then RaiseGDBException('');
{$IFDEF EnableDoubleBuf} {$IFDEF EnableDoubleBuf}
if (SavedCanvas<>nil) then RaiseGDBException('');
if BufferBitmap=nil then if BufferBitmap=nil then
BufferBitmap:=TBitmap.Create; BufferBitmap:=TBitmap.Create;
NewBufferWidth:=BufferBitmap.Width; NewBufferWidth:=BufferBitmap.Width;
@ -7057,7 +7014,7 @@ end;
procedure TCustomSynEdit.MoveCaretHorz(DX: integer); procedure TCustomSynEdit.MoveCaretHorz(DX: integer);
var var
NewCaret: TPoint; NewCaret: TPoint;
s: String; s, a: String;
PhysicalLineLen: Integer; PhysicalLineLen: Integer;
begin begin
NewCaret:=Point(CaretX+DX,CaretY); NewCaret:=Point(CaretX+DX,CaretY);

View File

@ -269,11 +269,17 @@ type
TLazSynSurface = class TLazSynSurface = class
private private
FBounds: TRect; FBounds: TRect;
FOwner: TWinControl;
function GetHandle: HWND;
protected protected
procedure BoundsChanged; virtual; procedure BoundsChanged; virtual;
procedure DoPaint(ACanvas: TCanvas; AClip: TRect); virtual; abstract; procedure DoPaint(ACanvas: TCanvas; AClip: TRect); virtual; abstract;
property Handle: HWND read GetHandle;
public public
constructor Create(AOwner: TWinControl);
procedure Assign(Src: TLazSynSurface); virtual;
procedure Paint(ACanvas: TCanvas; AClip: TRect); procedure Paint(ACanvas: TCanvas; AClip: TRect);
procedure InvalidateLines(FirstLine, LastLine: TLineIdx); virtual;
procedure SetBounds(ATop, ALeft, ABottom, ARight: Integer); procedure SetBounds(ATop, ALeft, ABottom, ARight: Integer);
property Left: Integer read FBounds.Left; property Left: Integer read FBounds.Left;
@ -825,11 +831,26 @@ end;
{ TLazSynSurface } { TLazSynSurface }
function TLazSynSurface.GetHandle: HWND;
begin
Result := FOwner.Handle;
end;
procedure TLazSynSurface.BoundsChanged; procedure TLazSynSurface.BoundsChanged;
begin begin
// //
end; end;
constructor TLazSynSurface.Create(AOwner: TWinControl);
begin
FOwner := AOwner;
end;
procedure TLazSynSurface.Assign(Src: TLazSynSurface);
begin
// do not assign the bounds
end;
procedure TLazSynSurface.Paint(ACanvas: TCanvas; AClip: TRect); procedure TLazSynSurface.Paint(ACanvas: TCanvas; AClip: TRect);
begin begin
if (AClip.Left >= Bounds.Right) or if (AClip.Left >= Bounds.Right) or
@ -842,11 +863,16 @@ begin
if (AClip.Left < Bounds.Left) then AClip.Left := Bounds.Left; if (AClip.Left < Bounds.Left) then AClip.Left := Bounds.Left;
if (AClip.Right > Bounds.Right) then AClip.Right := Bounds.Right; if (AClip.Right > Bounds.Right) then AClip.Right := Bounds.Right;
if (AClip.Top < Bounds.Top) then AClip.Top := Bounds.Top; if (AClip.Top < Bounds.Top) then AClip.Top := Bounds.Top;
if (AClip.Bottom < Bounds.Bottom) then AClip.Bottom := Bounds.Bottom; if (AClip.Bottom > Bounds.Bottom) then AClip.Bottom := Bounds.Bottom;
DoPaint(ACanvas, AClip); DoPaint(ACanvas, AClip);
end; end;
procedure TLazSynSurface.InvalidateLines(FirstLine, LastLine: TLineIdx);
begin
//
end;
procedure TLazSynSurface.SetBounds(ATop, ALeft, ABottom, ARight: Integer); procedure TLazSynSurface.SetBounds(ATop, ALeft, ABottom, ARight: Integer);
begin begin
if (FBounds.Left = ALeft) and (FBounds.Top = ATop) and if (FBounds.Left = ALeft) and (FBounds.Top = ATop) and

View File

@ -6,13 +6,14 @@ interface
uses uses
SysUtils, Classes, Controls, Graphics, LCLType, LCLIntf, Menus, SysUtils, Classes, Controls, Graphics, LCLType, LCLIntf, Menus,
SynEditMarks, SynEditMiscClasses, SynEditMiscProcs, LazSynTextArea, SynEditMarks, SynEditTypes, SynEditMiscClasses, SynEditMiscProcs, LazSynTextArea,
SynTextDrawer, SynGutterBase, SynGutterLineNumber, SynGutterCodeFolding, SynTextDrawer, SynGutterBase, SynGutterLineNumber, SynGutterCodeFolding,
SynGutterMarks, SynGutterChanges, SynEditMouseCmds; SynGutterMarks, SynGutterChanges, SynEditMouseCmds;
type type
TSynGutterSeparator = class; TSynGutterSeparator = class;
TLazSynGutterArea = class;
{ TSynGutter } { TSynGutter }
@ -32,7 +33,7 @@ type
constructor Create(AOwner : TSynEditBase; ASide: TSynGutterSide; constructor Create(AOwner : TSynEditBase; ASide: TSynGutterSide;
ATextDrawer: TheTextDrawer); ATextDrawer: TheTextDrawer);
destructor Destroy; override; destructor Destroy; override;
procedure Paint(Canvas: TCanvas; AClip: TRect; FirstLine, LastLine: integer); procedure Paint(Canvas: TCanvas; Surface:TLazSynGutterArea; AClip: TRect; FirstLine, LastLine: integer);
function HasCustomPopupMenu(out PopMenu: TPopupMenu): Boolean; function HasCustomPopupMenu(out PopMenu: TPopupMenu): Boolean;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure MouseMove(Shift: TShiftState; X, Y: Integer); procedure MouseMove(Shift: TShiftState; X, Y: Integer);
@ -98,11 +99,15 @@ type
private private
FGutter: TSynGutter; FGutter: TSynGutter;
FTextArea: TLazSynTextArea; FTextArea: TLazSynTextArea;
function GetTextBounds: TRect;
protected protected
procedure DoPaint(ACanvas: TCanvas; AClip: TRect); override; procedure DoPaint(ACanvas: TCanvas; AClip: TRect); override;
public public
procedure InvalidateLines(FirstLine, LastLine: TLineIdx); override;
procedure Assign(Src: TLazSynSurface); override;
property TextArea: TLazSynTextArea read FTextArea write FTextArea; property TextArea: TLazSynTextArea read FTextArea write FTextArea;
property Gutter: TSynGutter read FGutter write FGutter; property Gutter: TSynGutter read FGutter write FGutter;
property TextBounds: TRect read GetTextBounds;
end; end;
implementation implementation
@ -111,6 +116,11 @@ uses
{ TLazSynGutterArea } { TLazSynGutterArea }
function TLazSynGutterArea.GetTextBounds: TRect;
begin
Result := TextArea.TextBounds;
end;
procedure TLazSynGutterArea.DoPaint(ACanvas: TCanvas; AClip: TRect); procedure TLazSynGutterArea.DoPaint(ACanvas: TCanvas; AClip: TRect);
var var
ScreenRow1, ScreenRow2: integer; ScreenRow1, ScreenRow2: integer;
@ -119,7 +129,31 @@ begin
ScreenRow1 := Max((AClip.Top - Bounds.Top) div TextArea.LineHeight, 0); ScreenRow1 := Max((AClip.Top - Bounds.Top) div TextArea.LineHeight, 0);
ScreenRow2 := Min((AClip.Bottom-1 - Bounds.Top) div TextArea.LineHeight, TextArea.LinesInWindow + 1); ScreenRow2 := Min((AClip.Bottom-1 - Bounds.Top) div TextArea.LineHeight, TextArea.LinesInWindow + 1);
FGutter.Paint(ACanvas, AClip, ScreenRow1, ScreenRow2); FGutter.Paint(ACanvas, Self, AClip, ScreenRow1, ScreenRow2);
end;
procedure TLazSynGutterArea.InvalidateLines(FirstLine, LastLine: TLineIdx);
var
rcInval: TRect;
begin
rcInval := Bounds;
if (FirstLine >= 0) then
rcInval.Top := TextArea.TextBounds.Top + FirstLine * TextArea.LineHeight;
if (LastLine >= 0) then
rcInval.Bottom := TextArea.TextBounds.Top + LastLine * TextArea.LineHeight;
{$IFDEF VerboseSynEditInvalidate}
DebugLn(['TCustomSynEdit.InvalidateGutterLines ',DbgSName(self), ' FirstLine=',FirstLine, ' LastLine=',LastLine, ' rect=',dbgs(rcInval)]);
{$ENDIF}
if (rcInval.Top < rcInval.Bottom) and (rcInval.Left < rcInval.Right) then
InvalidateRect(Handle, @rcInval, FALSE);
end;
procedure TLazSynGutterArea.Assign(Src: TLazSynSurface);
begin
inherited Assign(Src);
FTextArea := TLazSynGutterArea(Src).FTextArea;
FGutter := TLazSynGutterArea(Src).FGutter;
end; end;
{ TSynGutter } { TSynGutter }
@ -203,7 +237,7 @@ begin
Parts[PixelToPartIndex(X)].DoOnGutterClick(X, Y); Parts[PixelToPartIndex(X)].DoOnGutterClick(X, Y);
end; end;
procedure TSynGutter.Paint(Canvas: TCanvas; AClip: TRect; FirstLine, LastLine: integer); procedure TSynGutter.Paint(Canvas: TCanvas; Surface:TLazSynGutterArea; AClip: TRect; FirstLine, LastLine: integer);
var var
i: integer; i: integer;
rcLine: TRect; rcLine: TRect;
@ -224,10 +258,8 @@ begin
TextDrawer.ExtTextOut(Left, Top, ETO_OPAQUE, AClip, nil, 0); TextDrawer.ExtTextOut(Left, Top, ETO_OPAQUE, AClip, nil, 0);
TextDrawer.EndDrawing; TextDrawer.EndDrawing;
if Side = gsLeft then AClip.Left := Surface.Left;
AClip.Left := LeftOffset AClip.Top := Surface.TextBounds.Top + FirstLine * TCustomSynEdit(SynEdit).LineHeight;
else
AClip.Left := SynEdit.ClientWidth - Width - ScrollBarWidth + LeftOffset;
rcLine := AClip; rcLine := AClip;
rcLine.Right := rcLine.Left; rcLine.Right := rcLine.Left;

View File

@ -96,8 +96,8 @@ begin
Canvas.AntialiasingMode:=amOff; Canvas.AntialiasingMode:=amOff;
rcLine := AClip; rcLine := AClip;
rcLine.Bottom := AClip.Top;
rcLine.Left := rcLine.Left + Width div 2; rcLine.Left := rcLine.Left + Width div 2;
rcLine.Bottom := FirstLine * LineHeight;
for i := FirstLine to LastLine do for i := FirstLine to LastLine do
begin begin
iLine := FoldView.TextIndex[i]; iLine := FoldView.TextIndex[i];

View File

@ -679,7 +679,7 @@ begin
Pen.Color := MarkupInfo.Foreground; Pen.Color := MarkupInfo.Foreground;
Pen.Width := 1; Pen.Width := 1;
rcLine.Bottom := FirstLine * LineHeight; rcLine.Bottom := AClip.Top;
for iLine := FirstLine to LastLine do for iLine := FirstLine to LastLine do
begin begin
// next line rect // next line rect

View File

@ -253,7 +253,7 @@ begin
fTextDrawer.Style := MarkupInfo.Style; fTextDrawer.Style := MarkupInfo.Style;
// prepare the rect initially // prepare the rect initially
rcLine := AClip; rcLine := AClip;
rcLine.Bottom := FirstLine * LineHeight; rcLine.Bottom := AClip.Top;
for i := FirstLine to LastLine do for i := FirstLine to LastLine do
begin begin
iLine := FoldView.DisplayNumber[i]; iLine := FoldView.DisplayNumber[i];

View File

@ -138,9 +138,9 @@ begin
LineHeight := TCustomSynEdit(SynEdit).LineHeight; LineHeight := TCustomSynEdit(SynEdit).LineHeight;
//Gutter.Paint always supplies AClip.Left = GutterPart.Left //Gutter.Paint always supplies AClip.Left = GutterPart.Left
MarkRect := Rect(AClip.Left + FBookMarkOpt.LeftMargin, MarkRect := Rect(AClip.Left + FBookMarkOpt.LeftMargin,
aScreenLine * LineHeight, AClip.Top,
AClip.Left + FColumnWidth, AClip.Left + FColumnWidth,
(aScreenLine+1) * LineHeight); AClip.Top + LineHeight);
LastMarkIsBookmark := FBookMarkOpt.DrawBookmarksFirst; LastMarkIsBookmark := FBookMarkOpt.DrawBookmarksFirst;
@ -184,6 +184,8 @@ end;
procedure TSynGutterMarks.Paint(Canvas : TCanvas; AClip : TRect; FirstLine, LastLine : integer); procedure TSynGutterMarks.Paint(Canvas : TCanvas; AClip : TRect; FirstLine, LastLine : integer);
var var
i: integer; i: integer;
LineHeight: Integer;
rcLine: TRect;
begin begin
if not Visible then exit; if not Visible then exit;
if MarkupInfo.Background <> clNone then if MarkupInfo.Background <> clNone then
@ -198,10 +200,16 @@ begin
FColumnWidth := Width; FColumnWidth := Width;
FColumnCount := Max((Width+1) div FColumnWidth, 1); // full columns FColumnCount := Max((Width+1) div FColumnWidth, 1); // full columns
rcLine := AClip;
rcLine.Bottom := rcLine.Top;
if FBookMarkOpt.GlyphsVisible and (LastLine >= FirstLine) then if FBookMarkOpt.GlyphsVisible and (LastLine >= FirstLine) then
begin begin
for i := FirstLine to LastLine do LineHeight := TCustomSynEdit(SynEdit).LineHeight;
PaintLine(i, Canvas, AClip); for i := FirstLine to LastLine do begin
rcLine.Top := rcLine.Bottom;
rcLine.Bottom := Min(AClip.Bottom, rcLine.Top + LineHeight);
PaintLine(i, Canvas, rcLine);
end;
end; end;
end; end;