mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-13 12:39:15 +02:00
SynEdit: Improve order of event in DecPaintLock. Make sure ScrollAfterTopLineChanged is only called once, and as late as possible (after all InvalidateLines calls should be done)
This commit is contained in:
parent
b4ccfdb8b6
commit
c33eb7418e
@ -447,6 +447,8 @@ type
|
||||
|
||||
TCustomSynEdit = class(TSynEditBase)
|
||||
procedure SelAvailChange(Sender: TObject);
|
||||
private type
|
||||
TSynDecPaintLockState = (iplFalse, iplIgnore, iplSubLock);
|
||||
private
|
||||
FImeHandler: LazSynIme;
|
||||
{$IFDEF Gtk2IME}
|
||||
@ -540,7 +542,7 @@ type
|
||||
FRecalcCharsAndLinesLock: Integer;
|
||||
FDoingResizeLock: Integer;
|
||||
FInvalidateRect: TRect;
|
||||
FIsInDecPaintLock: Boolean;
|
||||
FIsInDecPaintLock: TSynDecPaintLockState;
|
||||
FScrollBars: TScrollStyle;
|
||||
FOldTopView: Integer;
|
||||
FCachedTopLine: Integer;
|
||||
@ -1370,6 +1372,11 @@ var
|
||||
const
|
||||
GutterTextDist = 2; //Pixel
|
||||
|
||||
function DbgS(const s: TSynEdit.TSynDecPaintLockState): string; overload;
|
||||
begin
|
||||
WriteStr(Result, s);
|
||||
end;
|
||||
|
||||
type
|
||||
|
||||
TSynTextViewsManagerInternal = class(TSynTextViewsManager)
|
||||
@ -2539,7 +2546,11 @@ end;
|
||||
|
||||
procedure TCustomSynEdit.IncPaintLock;
|
||||
begin
|
||||
if FIsInDecPaintLock then exit;
|
||||
if FIsInDecPaintLock <> iplFalse then begin
|
||||
if FIsInDecPaintLock = iplSubLock then
|
||||
inc(FPaintLock);
|
||||
exit;
|
||||
end;
|
||||
if (PaintLockOwner = nil) then begin
|
||||
PaintLockOwner := Self;
|
||||
FLines.SendNotification(senrIncOwnedPaintLock, Self); // DoIncForeignPaintLock
|
||||
@ -2551,7 +2562,11 @@ end;
|
||||
|
||||
procedure TCustomSynEdit.DecPaintLock;
|
||||
begin
|
||||
if FIsInDecPaintLock then exit;
|
||||
if FIsInDecPaintLock <> iplFalse then begin
|
||||
if FIsInDecPaintLock = iplSubLock then
|
||||
dec(FPaintLock);
|
||||
exit;
|
||||
end;
|
||||
if FPaintLockOwnerCnt = 1 then
|
||||
FLines.EndUpdate(Self);
|
||||
dec(FPaintLockOwnerCnt);
|
||||
@ -2595,7 +2610,11 @@ end;
|
||||
|
||||
procedure TCustomSynEdit.DoIncPaintLock(Sender: TObject);
|
||||
begin
|
||||
if FIsInDecPaintLock then exit;
|
||||
if FIsInDecPaintLock <> iplFalse then begin
|
||||
if FIsInDecPaintLock = iplSubLock then
|
||||
inc(FPaintLock);
|
||||
exit;
|
||||
end;
|
||||
if FPaintLock = 0 then begin
|
||||
SetUpdateState(True, Self);
|
||||
FInvalidateRect := Rect(-1, -1, -2, -2);
|
||||
@ -2613,8 +2632,12 @@ end;
|
||||
|
||||
procedure TCustomSynEdit.DoDecPaintLock(Sender: TObject);
|
||||
begin
|
||||
if FIsInDecPaintLock then exit;
|
||||
FIsInDecPaintLock := True;
|
||||
if FIsInDecPaintLock <> iplFalse then begin
|
||||
if FIsInDecPaintLock = iplSubLock then
|
||||
dec(FPaintLock);
|
||||
exit;
|
||||
end;
|
||||
FIsInDecPaintLock := iplIgnore;
|
||||
try
|
||||
if (FUndoBlockAtPaintLock >= FPaintLock) then begin
|
||||
if (FUndoBlockAtPaintLock > FPaintLock) then
|
||||
@ -2655,31 +2678,47 @@ begin
|
||||
*)
|
||||
|
||||
Dec(FPaintLock);
|
||||
if (FPaintLock = 0) and (not WaitingForInitialSize) then begin
|
||||
ScrollAfterTopLineChanged;
|
||||
if sfScrollbarChanged in fStateFlags then
|
||||
UpdateScrollbars;
|
||||
// must be past UpdateScrollbars; but before UpdateCaret (for ScrollBar-Auto-show)
|
||||
if sfEnsureCursorPos in fStateFlags then
|
||||
EnsureCursorPosVisible; // TODO: This may call SetTopLine, change order
|
||||
// This does Paintlock, should be before final decrease
|
||||
// Must be after EnsureCursorPosVisible (as it does MoveCaretToVisibleArea)
|
||||
if FCaret.LinePos > Max(FLines.Count, 1) then
|
||||
FCaret.LinePos := Max(FLines.Count, 1);
|
||||
if sfCaretChanged in fStateFlags then
|
||||
UpdateCaret;
|
||||
//if sfScrollbarChanged in fStateFlags then
|
||||
// UpdateScrollbars;
|
||||
end;
|
||||
if (FPaintLock = 0) then begin
|
||||
FMarkupManager.DecPaintLock; // Todo: Markup can do invalidation, should be before ScrollAfterTopLineChanged;
|
||||
if (not WaitingForInitialSize) then begin
|
||||
if sfScrollbarChanged in fStateFlags then
|
||||
UpdateScrollbars;
|
||||
|
||||
(* EnsureCursorPosVisible must be past UpdateScrollbars; but before UpdateCaret (for ScrollBar-Auto-show)
|
||||
- May Change TopView and LeftChar
|
||||
- Needs iplSubLock: This prevents calls to UpdateScrollBars and ScrollAfterTopLineChanged
|
||||
*)
|
||||
FIsInDecPaintLock := iplSubLock;
|
||||
if sfEnsureCursorPos in fStateFlags then
|
||||
EnsureCursorPosVisible; // TODO: This may call SetTopLine, change order
|
||||
// This does Paintlock, should be before final decrease
|
||||
FIsInDecPaintLock := iplIgnore;
|
||||
|
||||
(* EnsureCursorPosVisible; may have scrolled
|
||||
This should not change the visibility of eithre scrollbar.
|
||||
So no further update of the Caret needed.
|
||||
- If needed this could move down, until right before ScrollAfterTopLineChanged
|
||||
*)
|
||||
if sfScrollbarChanged in fStateFlags then
|
||||
UpdateScrollbars;
|
||||
|
||||
// Must be after EnsureCursorPosVisible (as it does MoveCaretToVisibleArea)
|
||||
if FCaret.LinePos > Max(FLines.Count, 1) then
|
||||
FCaret.LinePos := Max(FLines.Count, 1);
|
||||
if sfCaretChanged in fStateFlags then
|
||||
UpdateCaret; // MoveCaretToVisibleArea and ScreenCaret.DisplayPos / ScreenCaret is still locked
|
||||
end;
|
||||
|
||||
FMarkupManager.DecPaintLock;
|
||||
FBlockSelection.AutoExtend := False;
|
||||
if fStatusChanges <> [] then
|
||||
DoOnStatusChange(fStatusChanges);
|
||||
|
||||
if (not WaitingForInitialSize) then
|
||||
ScrollAfterTopLineChanged;
|
||||
end;
|
||||
finally
|
||||
FScreenCaret.UnLock;
|
||||
FIsInDecPaintLock := False;
|
||||
FIsInDecPaintLock := iplFalse;
|
||||
if FPaintLock = 0 then begin
|
||||
SetUpdateState(False, Self);
|
||||
if FInvalidateRect.Bottom >= FInvalidateRect.Top then begin
|
||||
@ -5151,6 +5190,7 @@ var
|
||||
begin
|
||||
if (sfPainting in fStateFlags) or (fPaintLock <> 0) or WaitingForInitialSize then
|
||||
exit;
|
||||
assert(FIsInDecPaintLock <> iplSubLock, 'TCustomSynEdit.ScrollAfterTopLineChanged: FIsInDecPaintLock <> iplSubLock');
|
||||
Delta := FOldTopView - TopView;
|
||||
{$IFDEF SYNSCROLLDEBUG}
|
||||
if (sfHasScrolled in fStateFlags) then debugln(['ScrollAfterTopLineChanged with sfHasScrolled Delta=',Delta,' topline=',TopLine, ' FOldTopView=',FOldTopView ]);
|
||||
@ -5265,6 +5305,7 @@ begin
|
||||
if WaitingForInitialSize or (PaintLock <> 0) or (FDoingResizeLock <> 0) then
|
||||
Include(fStateFlags, sfScrollbarChanged)
|
||||
else begin
|
||||
assert(FIsInDecPaintLock <> iplSubLock, 'TCustomSynEdit.UpdateScrollBars: FIsInDecPaintLock <> iplSubLock');
|
||||
Exclude(fStateFlags, sfScrollbarChanged);
|
||||
ScrollInfo.cbSize := SizeOf(ScrollInfo);
|
||||
ScrollInfo.fMask := SIF_ALL or SIF_DISABLENOSCROLL and not SIF_TRACKPOS;
|
||||
@ -5797,7 +5838,7 @@ begin
|
||||
// don't use MinMax here, it will fail in design mode (Lines.Count is zero,
|
||||
// but the painting code relies on TopLine >= 1)
|
||||
{$IFDEF SYNSCROLLDEBUG}
|
||||
if (fPaintLock = 0) and (not FIsInDecPaintLock) then debugln(['SetTopView outside Paintlock New=',AValue, ' Old=', FFoldedLinesView.TopLine]);
|
||||
if (fPaintLock = 0) and (FIsInDecPaintLock = iplFalse) then debugln(['SetTopView outside Paintlock New=',AValue, ' Old=', FFoldedLinesView.TopLine]);
|
||||
if (sfHasScrolled in fStateFlags) then debugln(['SetTopView with sfHasScrolled Value=',AValue, ' FOldTopView=',FOldTopView ]);
|
||||
{$ENDIF}
|
||||
FCachedTopLine := -1;
|
||||
@ -5830,7 +5871,7 @@ begin
|
||||
fMarkupManager.TopLine := TopLine;
|
||||
|
||||
{$IFDEF SYNSCROLLDEBUG}
|
||||
if (fPaintLock = 0) and (not FIsInDecPaintLock) then debugln('SetTopline outside Paintlock EXIT');
|
||||
if (fPaintLock = 0) and (FIsInDecPaintLock = iplFalse) then debugln('SetTopline outside Paintlock EXIT');
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
@ -7963,7 +8004,7 @@ end;
|
||||
procedure TCustomSynEdit.AfterLoadFromFile;
|
||||
begin
|
||||
if WaitingForInitialSize or
|
||||
( (FPaintLock > 0) and not((FPaintLock = 1) and FIsInDecPaintLock) )
|
||||
( (FPaintLock > 0) and not((FPaintLock = 1) and (FIsInDecPaintLock <> iplFalse)) )
|
||||
then begin
|
||||
Include(fStateFlags, sfAfterLoadFromFileNeeded);
|
||||
exit;
|
||||
|
Loading…
Reference in New Issue
Block a user