SynEdit: Fixed an invalidation issue when scrolling (current line highlight could get lost), also improves issue #11715

git-svn-id: trunk@20975 -
This commit is contained in:
martin 2009-07-27 15:12:13 +00:00
parent e480675e27
commit ee46b0680f

View File

@ -386,7 +386,7 @@ type
fTextHeight: Integer; fTextHeight: Integer;
fTextOffset: Integer; fTextOffset: Integer;
fTopLine: Integer; fTopLine: Integer;
FOldTopView, FTopDelta: Integer; // TopView before IncPaintLock FNewTopLine: Integer;
fHighlighter: TSynCustomHighlighter; fHighlighter: TSynCustomHighlighter;
{$IFNDEF SYN_LAZARUS} {$IFNDEF SYN_LAZARUS}
fSelectedColor: TSynSelectedColor; fSelectedColor: TSynSelectedColor;
@ -567,7 +567,6 @@ type
procedure SetTabWidth(Value: integer); procedure SetTabWidth(Value: integer);
procedure SynSetText(const Value: string); procedure SynSetText(const Value: string);
procedure SetTopLine(Value: Integer); procedure SetTopLine(Value: Integer);
procedure ScrollAfterTopLineChanged;
procedure SetWantTabs(const Value: boolean); procedure SetWantTabs(const Value: boolean);
procedure SetWordBlock(Value: TPoint); procedure SetWordBlock(Value: TPoint);
{$IFDEF SYN_LAZARUS} {$IFDEF SYN_LAZARUS}
@ -1669,7 +1668,7 @@ begin
fTabWidth := 8; fTabWidth := 8;
fLeftChar := 1; fLeftChar := 1;
fTopLine := 1; fTopLine := 1;
FTopDelta := 0; FNewTopLine := -1;
{$IFDEF SYN_LAZARUS} {$IFDEF SYN_LAZARUS}
FFoldedLinesView.TopLine := 1; FFoldedLinesView.TopLine := 1;
{$ELSE} {$ELSE}
@ -1757,7 +1756,8 @@ begin
FFoldedLinesView.UnLock; // after ScanFrom, but before UpdateCaret FFoldedLinesView.UnLock; // after ScanFrom, but before UpdateCaret
Dec(fPaintLock); Dec(fPaintLock);
if (fPaintLock = 0) and HandleAllocated then begin if (fPaintLock = 0) and HandleAllocated then begin
ScrollAfterTopLineChanged; if FNewTopLine > 0 then
TopLine := FNewTopLine;
if sfScrollbarChanged in fStateFlags then if sfScrollbarChanged in fStateFlags then
UpdateScrollbars; UpdateScrollbars;
// must be past UpdateScrollbars; but before UpdateCaret // must be past UpdateScrollbars; but before UpdateCaret
@ -2077,10 +2077,8 @@ end;
procedure TCustomSynEdit.IncPaintLock; procedure TCustomSynEdit.IncPaintLock;
begin begin
if fPaintLock = 0 then begin if fPaintLock = 0 then
FOldTopView := TopView; FNewTopLine := -1;
FTopDelta := 0;
end;
inc(fPaintLock); inc(fPaintLock);
FFoldedLinesView.Lock; //DecPaintLock triggers ScanFrom, and folds must wait FFoldedLinesView.Lock; //DecPaintLock triggers ScanFrom, and folds must wait
FTrimmedLinesView.Lock; // Lock before caret FTrimmedLinesView.Lock; // Lock before caret
@ -2113,12 +2111,12 @@ begin
if LastLine >= 0 then begin if LastLine >= 0 then begin
if (LastLine < FirstLine) then SwapInt(LastLine, FirstLine); if (LastLine < FirstLine) then SwapInt(LastLine, FirstLine);
LastLine := RowToScreenRow(Min(LastLine, ScreenRowToRow(LinesInWindow)))+1; LastLine := RowToScreenRow(Min(LastLine, ScreenRowToRow(LinesInWindow)))+1;
LastLine := LastLine + FTopDelta; LastLine := LastLine;
end end
else else
LastLine := LinesInWindow + 1; LastLine := LinesInWindow + 1;
FirstLine := RowToScreenRow(Max(FirstLine, TopLine)); FirstLine := RowToScreenRow(Max(FirstLine, TopLine));
FirstLine := Max(0, FirstLine + FTopDelta); FirstLine := Max(0, FirstLine);
{ any line visible? } { any line visible? }
if (LastLine >= FirstLine) then begin if (LastLine >= FirstLine) then begin
rcInval := Rect(0, fTextHeight * FirstLine, rcInval := Rect(0, fTextHeight * FirstLine,
@ -2158,12 +2156,12 @@ begin
if LastLine >= 0 then begin if LastLine >= 0 then begin
if (LastLine < FirstLine) then SwapInt(LastLine, FirstLine); if (LastLine < FirstLine) then SwapInt(LastLine, FirstLine);
l := RowToScreenRow(Min(LastLine, ScreenRowToRow(LinesInWindow)))+1; l := RowToScreenRow(Min(LastLine, ScreenRowToRow(LinesInWindow)))+1;
l := l + FTopDelta; l := l;
end end
else else
l := LinesInWindow + 1; l := LinesInWindow + 1;
f := RowToScreenRow(Max(FirstLine, TopLine)); f := RowToScreenRow(Max(FirstLine, TopLine));
f := Max(0, f + FTopDelta); f := Max(0, f);
{ any line visible? } { any line visible? }
if (l >= f) then begin if (l >= f) then begin
rcInval := Rect(fGutterWidth, fTextHeight * f, rcInval := Rect(fGutterWidth, fTextHeight * f,
@ -3979,7 +3977,15 @@ end;
{$ENDIF} {$ENDIF}
procedure TCustomSynEdit.SetTopLine(Value: Integer); procedure TCustomSynEdit.SetTopLine(Value: Integer);
var
Delta: Integer;
OldTopView: LongInt;
begin begin
if fPaintLock > 0 then begin
// defer scrolling, to minimize any possible flicker
FNewTopLine := Value;
exit;
end;
// don't use MinMax here, it will fail in design mode (Lines.Count is zero, // don't use MinMax here, it will fail in design mode (Lines.Count is zero,
// but the painting code relies on TopLine >= 1) // but the painting code relies on TopLine >= 1)
if (eoScrollPastEof in Options) then if (eoScrollPastEof in Options) then
@ -3991,25 +3997,13 @@ begin
Value := FindNextUnfoldedLine(Value, False); Value := FindNextUnfoldedLine(Value, False);
FFoldedLinesView.TopTextIndex := fTopLine - 1; FFoldedLinesView.TopTextIndex := fTopLine - 1;
if Value <> fTopLine then begin if Value <> fTopLine then begin
if fPaintLock = 0 then OldTopView := TopView;
FOldTopView := TopView;
fTopLine := Value; fTopLine := Value;
FFoldedLinesView.TopTextIndex := Value-1; FFoldedLinesView.TopTextIndex := Value-1;
FTopDelta := TopView - FOldTopView;
UpdateScrollBars; UpdateScrollBars;
ScrollAfterTopLineChanged; if (sfPainting in fStateFlags) then debugln('SetTopline inside paint');
StatusChanged([scTopLine]); Delta := OldTopView - TopView;
end; if Delta <> 0 then begin
fMarkupManager.TopLine:= fTopLine;
end;
procedure TCustomSynEdit.ScrollAfterTopLineChanged;
var
Delta: Integer;
begin
if (sfPainting in fStateFlags) or (fPaintLock <> 0) then exit;
Delta := FOldTopView - TopView;
if Delta = 0 then exit;
// TODO: SW_SMOOTHSCROLL --> can't get it work // TODO: SW_SMOOTHSCROLL --> can't get it work
if (Abs(Delta) >= fLinesInWindow) or if (Abs(Delta) >= fLinesInWindow) or
not ScrollWindowEx(Handle, 0, fTextHeight * Delta, nil, nil, 0, nil, SW_INVALIDATE) not ScrollWindowEx(Handle, 0, fTextHeight * Delta, nil, nil, 0, nil, SW_INVALIDATE)
@ -4018,7 +4012,11 @@ begin
else else
if eoAlwaysVisibleCaret in fOptions2 then if eoAlwaysVisibleCaret in fOptions2 then
MoveCaretToVisibleArea; // Invalidate caret line, if necessary MoveCaretToVisibleArea; // Invalidate caret line, if necessary
FTopDelta := 0; end;
StatusChanged([scTopLine]);
end;
fMarkupManager.TopLine:= fTopLine;
end; end;
procedure TCustomSynEdit.ShowCaret; procedure TCustomSynEdit.ShowCaret;