SynEdit: fixed incorrect line-invalidation / repaint when scrolling (with folded text)

This commit is contained in:
Martin 2022-04-01 15:00:14 +02:00
parent 013e6a61a5
commit 5b23421c5d
5 changed files with 49 additions and 36 deletions

View File

@ -154,7 +154,7 @@ type
constructor Create(AOwner: TWinControl; ATextDrawer: TheTextDrawer);
destructor Destroy; override;
procedure Assign(Src: TLazSynSurface); override;
procedure InvalidateLines(FirstTextLine, LastTextLine: TLineIdx); override;
procedure InvalidateLines(FirstTextLine, LastTextLine: TLineIdx; AScreenLineOffset: Integer = 0); override;
function ScreenColumnToXValue(Col: integer): integer; // map screen column to screen pixel
function RowColumnToPixels(const RowCol: TPoint): TPoint;
@ -239,9 +239,9 @@ type
procedure BoundsChanged; override;
public
constructor Create(AOwner: TWinControl);
procedure InvalidateLines(FirstTextLine, LastTextLine: TLineIdx); override;
procedure InvalidateTextLines(FirstTextLine, LastTextLine: TLineIdx); virtual;
procedure InvalidateGutterLines(FirstTextLine, LastTextLine: TLineIdx); virtual;
procedure InvalidateLines(FirstTextLine, LastTextLine: TLineIdx; AScreenLineOffset: Integer = 0); override;
procedure InvalidateTextLines(FirstTextLine, LastTextLine: TLineIdx; AScreenLineOffset: Integer = 0); virtual;
procedure InvalidateGutterLines(FirstTextLine, LastTextLine: TLineIdx; AScreenLineOffset: Integer = 0); virtual;
property LeftGutterArea: TLazSynSurfaceWithText read GetLeftGutterArea write SetLeftGutterArea;
property RightGutterArea: TLazSynSurfaceWithText read GetRightGutterArea write SetRightGutterArea;
@ -1160,7 +1160,8 @@ begin
FRightGutterWidth := 0;
end;
procedure TLazSynSurfaceManager.InvalidateLines(FirstTextLine, LastTextLine: TLineIdx);
procedure TLazSynSurfaceManager.InvalidateLines(FirstTextLine,
LastTextLine: TLineIdx; AScreenLineOffset: Integer);
var
rcInval: TRect;
ViewedRange: TLineRange;
@ -1169,14 +1170,14 @@ begin
if (FirstTextLine >= 0) then begin
ViewedRange := DisplayView.TextToViewIndex(FirstTextLine);
rcInval.Top := Max(TextArea.TextBounds.Top,
TextArea.TextBounds.Top + (ViewedRange.Top
TextArea.TextBounds.Top + (ViewedRange.Top + AScreenLineOffset
- TextArea.TopLine + 1) * TextArea.LineHeight);
end;
if (LastTextLine >= 0) then begin
if LastTextLine <> FirstTextLine then
ViewedRange := DisplayView.TextToViewIndex(LastTextLine);
rcInval.Bottom := Min(TextArea.TextBounds.Bottom,
TextArea.TextBounds.Top + (ViewedRange.Bottom
TextArea.TextBounds.Top + (ViewedRange.Bottom + AScreenLineOffset
- TextArea.TopLine + 2) * TextArea.LineHeight);
end;
@ -1187,15 +1188,17 @@ begin
InvalidateRect(Handle, @rcInval, FALSE);
end;
procedure TLazSynSurfaceManager.InvalidateTextLines(FirstTextLine, LastTextLine: TLineIdx);
procedure TLazSynSurfaceManager.InvalidateTextLines(FirstTextLine,
LastTextLine: TLineIdx; AScreenLineOffset: Integer);
begin
FTextArea.InvalidateLines(FirstTextLine, LastTextLine);
FTextArea.InvalidateLines(FirstTextLine, LastTextLine, AScreenLineOffset);
end;
procedure TLazSynSurfaceManager.InvalidateGutterLines(FirstTextLine, LastTextLine: TLineIdx);
procedure TLazSynSurfaceManager.InvalidateGutterLines(FirstTextLine,
LastTextLine: TLineIdx; AScreenLineOffset: Integer);
begin
FLeftGutterArea.InvalidateLines(FirstTextLine, LastTextLine);
FRightGutterArea.InvalidateLines(FirstTextLine, LastTextLine);
FLeftGutterArea.InvalidateLines(FirstTextLine, LastTextLine, AScreenLineOffset);
FRightGutterArea.InvalidateLines(FirstTextLine, LastTextLine, AScreenLineOffset);
end;
{ TLazSynTextArea }
@ -1361,7 +1364,8 @@ begin
BoundsChanged;
end;
procedure TLazSynTextArea.InvalidateLines(FirstTextLine, LastTextLine: TLineIdx);
procedure TLazSynTextArea.InvalidateLines(FirstTextLine,
LastTextLine: TLineIdx; AScreenLineOffset: Integer);
var
rcInval: TRect;
ViewedRange: TLineRange;
@ -1370,13 +1374,13 @@ begin
if (FirstTextLine >= 0) then begin
ViewedRange := DisplayView.TextToViewIndex(FirstTextLine);
rcInval.Top := Max(TextBounds.Top,
TextBounds.Top + (ViewedRange.Top - TopLine + 1) * LineHeight);
TextBounds.Top + (ViewedRange.Top + AScreenLineOffset - TopLine + 1) * LineHeight);
end;
if (LastTextLine >= 0) then begin
if LastTextLine <> FirstTextLine then
ViewedRange := DisplayView.TextToViewIndex(LastTextLine);
rcInval.Bottom := Min(TextBounds.Bottom,
TextBounds.Top + (ViewedRange.Bottom - TopLine + 2) * LineHeight);
TextBounds.Top + (ViewedRange.Bottom + AScreenLineOffset - TopLine + 2) * LineHeight);
end;
{$IFDEF VerboseSynEditInvalidate}

View File

@ -2953,6 +2953,8 @@ begin
end;
procedure TCustomSynEdit.InvalidateGutterLines(FirstLine, LastLine: integer); // Todo: move to gutter
var
offs: Integer;
begin
if sfPainting in fStateFlags then exit;
if Visible and HandleAllocated then begin
@ -2969,12 +2971,12 @@ begin
if (LastLine <> -1) and (LastLine < FirstLine) then
SwapInt(FirstLine, LastLine);
offs := 0;
if FPaintLock > 0 then begin
// pretend we haven't scrolled
FirstLine := FirstLine - (FOldTopView - TopView);
LastLine := LastLine - (FOldTopView - TopView);
offs := - (FOldTopView - TopView);
end;
FPaintArea.InvalidateGutterLines(FirstLine-1, LastLine-1);
FPaintArea.InvalidateGutterLines(FirstLine-1, LastLine-1, offs);
end;
{$IFDEF VerboseSynEditInvalidate}
DebugLnExit(['TCustomSynEdit.InvalidateGutterLines ',DbgSName(self)]);
@ -2984,6 +2986,8 @@ begin
end;
procedure TCustomSynEdit.InvalidateLines(FirstLine, LastLine: integer);
var
offs: Integer;
begin
if sfPainting in fStateFlags then exit;
if Visible and HandleAllocated then begin
@ -2996,12 +3000,12 @@ begin
if (LastLine <> -1) and (LastLine < FirstLine) then
SwapInt(FirstLine, LastLine);
offs := 0;
if FPaintLock > 0 then begin
// pretend we haven't scrolled
FirstLine := FirstLine - (FOldTopView - TopView);
LastLine := LastLine - (FOldTopView - TopView);
offs := - (FOldTopView - TopView);
end;
FPaintArea.InvalidateTextLines(FirstLine-1, LastLine-1);
FPaintArea.InvalidateTextLines(FirstLine-1, LastLine-1, offs);
end;
{$IFDEF VerboseSynEditInvalidate}
DebugLnExit(['TCustomSynEdit.InvalidateTextLines ',DbgSName(self)]);

View File

@ -593,7 +593,7 @@ type
procedure RemoveBoundsChangeHandler(AHandler: TNotifyEvent);
procedure Paint(ACanvas: TCanvas; AClip: TRect);
procedure InvalidateLines(FirstTextLine, LastTextLine: TLineIdx); virtual;
procedure InvalidateLines(FirstTextLine, LastTextLine: TLineIdx; AScreenLineOffset: Integer = 0); virtual;
procedure SetBounds(ATop, ALeft, ABottom, ARight: Integer);
property Left: Integer read FBounds.Left;
@ -1634,7 +1634,8 @@ begin
DoPaint(ACanvas, AClip);
end;
procedure TLazSynSurface.InvalidateLines(FirstTextLine, LastTextLine: TLineIdx);
procedure TLazSynSurface.InvalidateLines(FirstTextLine, LastTextLine: TLineIdx;
AScreenLineOffset: Integer);
begin
//
end;

View File

@ -108,7 +108,7 @@ type
protected
procedure DoPaint(ACanvas: TCanvas; AClip: TRect); override;
public
procedure InvalidateLines(FirstTextLine, LastTextLine: TLineIdx); override;
procedure InvalidateLines(FirstTextLine, LastTextLine: TLineIdx; AScreenLineOffset: Integer = 0); override;
procedure Assign(Src: TLazSynSurface); override;
property Gutter: TSynGutter read FGutter write SetGutter;
property TextBounds: TRect read GetTextBounds;
@ -144,7 +144,8 @@ begin
FGutter.Paint(ACanvas, Self, AClip, ScreenRow1, ScreenRow2);
end;
procedure TLazSynGutterArea.InvalidateLines(FirstTextLine, LastTextLine: TLineIdx);
procedure TLazSynGutterArea.InvalidateLines(FirstTextLine,
LastTextLine: TLineIdx; AScreenLineOffset: Integer);
var
rcInval: TRect;
begin
@ -152,12 +153,12 @@ begin
if (FirstTextLine >= 0) then
rcInval.Top := Max(TextArea.TextBounds.Top,
TextArea.TextBounds.Top
+ (DisplayView.TextToViewIndex(FirstTextLine).Top
+ (DisplayView.TextToViewIndex(FirstTextLine).Top + AScreenLineOffset
- TextArea.TopLine + 1) * TextArea.LineHeight);
if (LastTextLine >= 0) then
rcInval.Bottom := Min(TextArea.TextBounds.Bottom,
TextArea.TextBounds.Top
+ (DisplayView.TextToViewIndex(LastTextLine).Bottom
+ (DisplayView.TextToViewIndex(LastTextLine).Bottom + AScreenLineOffset
- TextArea.TopLine + 2) * TextArea.LineHeight);
{$IFDEF VerboseSynEditInvalidate}

View File

@ -131,9 +131,9 @@ type
public
constructor Create(AOwner: TWinControl; AnOriginalManager: TLazSynSurfaceManager);
destructor Destroy; override;
procedure InvalidateLines(FirstTextLine, LastTextLine: TLineIdx); override;
procedure InvalidateTextLines(FirstTextLine, LastTextLine: TLineIdx); override;
procedure InvalidateGutterLines(FirstTextLine, LastTextLine: TLineIdx); override;
procedure InvalidateLines(FirstTextLine, LastTextLine: TLineIdx; AScreenLineOffset: Integer = 0); override;
procedure InvalidateTextLines(FirstTextLine, LastTextLine: TLineIdx; AScreenLineOffset: Integer = 0); override;
procedure InvalidateGutterLines(FirstTextLine, LastTextLine: TLineIdx; AScreenLineOffset: Integer = 0); override;
property ExtraManager: TLazSynSurfaceManager read FExtraManager write FExtraManager;
property OriginalManager: TLazSynSurfaceManager read FOriginalManager write FOriginalManager;
property TopLineCount: Integer read FTopLineCount write SetTopLineCount;
@ -1418,21 +1418,24 @@ begin
FOriginalManager.Free;
end;
procedure TSourceLazSynSurfaceManager.InvalidateLines(FirstTextLine, LastTextLine: TLineIdx);
procedure TSourceLazSynSurfaceManager.InvalidateLines(FirstTextLine,
LastTextLine: TLineIdx; AScreenLineOffset: Integer);
begin
FOriginalManager.InvalidateLines(FirstTextLine, LastTextLine);
FOriginalManager.InvalidateLines(FirstTextLine, LastTextLine, AScreenLineOffset);
FExtraManager.InvalidateLines(FirstTextLine, LastTextLine);
end;
procedure TSourceLazSynSurfaceManager.InvalidateTextLines(FirstTextLine, LastTextLine: TLineIdx);
procedure TSourceLazSynSurfaceManager.InvalidateTextLines(FirstTextLine,
LastTextLine: TLineIdx; AScreenLineOffset: Integer);
begin
FOriginalManager.InvalidateTextLines(FirstTextLine, LastTextLine);
FOriginalManager.InvalidateTextLines(FirstTextLine, LastTextLine, AScreenLineOffset);
FExtraManager.InvalidateTextLines(FirstTextLine, LastTextLine);
end;
procedure TSourceLazSynSurfaceManager.InvalidateGutterLines(FirstTextLine, LastTextLine: TLineIdx);
procedure TSourceLazSynSurfaceManager.InvalidateGutterLines(FirstTextLine,
LastTextLine: TLineIdx; AScreenLineOffset: Integer);
begin
FOriginalManager.InvalidateGutterLines(FirstTextLine, LastTextLine);
FOriginalManager.InvalidateGutterLines(FirstTextLine, LastTextLine, AScreenLineOffset);
FExtraManager.InvalidateGutterLines(FirstTextLine, LastTextLine);
end;