diff --git a/ide/main.pp b/ide/main.pp index 45ddacc3ea..5f8eec0c0b 100644 --- a/ide/main.pp +++ b/ide/main.pp @@ -12600,11 +12600,16 @@ begin SearchResultsView.ShowOnTop; SourceEditorManager.ShowActiveWindowOnTop(True); end; - SrcEdit.EditorComponent.LogicalCaretXY:=LogCaretXY; - if not SrcEdit.IsLocked then - SrcEdit.CenterCursor(True); - with SrcEdit.EditorComponent do begin - LeftChar:= Math.Max(LogCaretXY.X-CharsInWindow,1); + try + SrcEdit.BeginUpdate; + SrcEdit.EditorComponent.LogicalCaretXY:=LogCaretXY; + if not SrcEdit.IsLocked then + SrcEdit.CenterCursor(True); + with SrcEdit.EditorComponent do begin + LeftChar:= Math.Max(LogCaretXY.X-CharsInWindow,1); + end; + finally + SrcEdit.EndUpdate; end; SrcEdit.ErrorLine:=LogCaretXY.Y; end; @@ -13895,17 +13900,20 @@ begin if NewX<1 then NewX:=1; if NewY<1 then NewY:=1; //debugln(['[TMainIDE.DoJumpToCodePos] ',NewX,',',NewY,',',NewTopLine]); - with NewSrcEdit.EditorComponent do - begin - MoveLogicalCaretIgnoreEOL(Point(NewX,NewY)); + try + NewSrcEdit.BeginUpdate; + NewSrcEdit.EditorComponent.MoveLogicalCaretIgnoreEOL(Point(NewX,NewY)); if not NewSrcEdit.IsLocked then begin if NewTopLine < 1 then NewSrcEdit.CenterCursor(True) else - TopLine:=NewTopLine; + NewSrcEdit.TopLine:=NewTopLine; end; //DebugLn('TMainIDE.DoJumpToCodePos NewY=',dbgs(NewY),' ',dbgs(TopLine),' ',dbgs(NewTopLine)); - LeftChar:=Max(NewX-CharsInWindow,1); + with NewSrcEdit.EditorComponent do + LeftChar:=Max(NewX - CharsInWindow, 1); + finally + NewSrcEdit.EndUpdate; end; if MarkLine then NewSrcEdit.ErrorLine := NewY; @@ -14994,9 +15002,14 @@ begin SourceEditorManager.ActiveEditor := AnEditor; SourceEditorManager.ShowActiveWindowOnTop(True); - AnEditor.EditorComponent.GotoBookMark(ID); - if not AnEditor.IsLocked then - AnEditor.CenterCursor(True); + try + AnEditor.BeginUpdate; + AnEditor.EditorComponent.GotoBookMark(ID); + if not AnEditor.IsLocked then + AnEditor.CenterCursor(True); + finally + AnEditor.EndUpdate; + end; end; //this is fired when the editor is focused, changed, ?. Anything that causes the status change diff --git a/ide/sourceeditor.pp b/ide/sourceeditor.pp index e6dbce00c3..80f3b21c08 100644 --- a/ide/sourceeditor.pp +++ b/ide/sourceeditor.pp @@ -1198,6 +1198,16 @@ implementation {$R *.lfm} +const + (* SoftCenter are th visible Lines in the Editor where the caret can be locateted, + without CenterCursor adjusting the topline. + SoftCenter is defined by the amount of lines on the top/bottom of fthe editor, + which are *not* part of it. + *) + SoftCenterFactor = 5; // One fifth of the "LinesInWindow"on each side (top/bottom) + SoftCenterMinimum = 1; + SoftCenterMaximum = 8; + var SourceCompletionTimer: TIdleTimer = nil; SourceCompletionCaretXY: TPoint; @@ -4250,16 +4260,21 @@ end; -------------------------------------------------------------------------------} procedure TSourceEditor.CenterCursor(SoftCenter: Boolean = False); var - NewTopLine: integer; - Y, CurTopLine, LinesInWin, MinLines: Integer; + Y, CurTopLine, LinesInWin, MinLines, NewTopLine: Integer; begin + LinesInWin := EditorComponent.LinesInWindow; + CurTopLine := EditorComponent.TopView; + Y := EditorComponent.TextIndexToViewPos(EditorComponent.CaretY); + if SoftCenter then begin - CurTopLine := EditorComponent.TopLine; - LinesInWin := EditorComponent.LinesInWindow; - MinLines := Min(Max(LinesInWin div 5, 1), 5); - Y := EditorComponent.CaretY; - if (Y <= CurTopLine) or (Y >= CurTopLine + LinesInWin) - then + MinLines := Min( + Min( Max(LinesInWin div SoftCenterFactor, SoftCenterMinimum), + SoftCenterMaximum), + Max(LinesInWin div 2 - 1, 0) // make sure there is at least one line in the soft center + ); + + if (Y <= CurTopLine) or (Y >= CurTopLine + LinesInWin) then + // Caret not yet visible => hard-center NewTopLine := Max(1, Y - (LinesInWin div 2)) else if Y < CurTopLine + MinLines then @@ -4271,9 +4286,11 @@ begin NewTopLine := CurTopLine; end else - NewTopLine:=EditorComponent.CaretY-((EditorComponent.LinesInWindow-1) div 2); - if NewTopLine<1 then NewTopLine:=1; - EditorComponent.TopLine:=NewTopLine; + // not using SoftCenter + NewTopLine := Max(1, Y - (LinesInWin div 2)); + + if NewTopLine < 1 then NewTopLine := 1; + EditorComponent.TopView := NewTopLine; end; function TSourceEditor.TextToScreenPosition(const Position: TPoint): TPoint; @@ -4404,16 +4421,23 @@ end; function TSourceEditor.IsCaretOnScreen(ACaret: TPoint; UseSoftCenter: Boolean = False): Boolean; var - LinesInWin, MinLines: Integer; + LinesInWin, MinLines, CurTopLine, Y: Integer; begin + LinesInWin := EditorComponent.LinesInWindow; + CurTopLine := EditorComponent.TopView; + Y := EditorComponent.TextIndexToViewPos(EditorComponent.CaretY); if UsesoftCenter then begin - LinesInWin := EditorComponent.LinesInWindow; - MinLines := Min(Max(LinesInWin div 5, 1), 5); + MinLines := Min( + Min( Max(LinesInWin div SoftCenterFactor, SoftCenterMinimum), + SoftCenterMaximum), + Max(LinesInWin div 2 - 1, 0) // make sure there is at least one line in the soft center + ); end else MinLines := 0; - Result := (ACaret.y >= FEditor.TopLine + MinLines) and - (ACaret.Y <= FEditor.TopLine + FEditor.LinesInWindow - MinLines) and + + Result := (Y >= CurTopLine + MinLines) and + (Y <= CurTopLine + LinesInWin - MinLines) and (ACaret.X >= FEditor.LeftChar) and (ACaret.X <= FEditor.LeftChar + FEditor.CharsInWindow); end; diff --git a/ide/sourcesyneditor.pas b/ide/sourcesyneditor.pas index a43e5c6bc4..efe0d5c8a6 100644 --- a/ide/sourcesyneditor.pas +++ b/ide/sourcesyneditor.pas @@ -54,7 +54,9 @@ type function CreateGutter(AOwner : TSynEditBase; AFoldedLinesView: TSynEditFoldedView; ATextDrawer: TheTextDrawer): TSynGutter; override; public + function TextIndexToViewPos(aTextIndex : Integer) : Integer; property IDEGutterMarks: TIDESynGutterMarks read GetIDEGutterMarks; + property TopView; property TextBuffer; end; @@ -118,6 +120,11 @@ begin Result := TIDESynGutter.Create(AOwner, AFoldedLinesView, ATextDrawer); end; +function TIDESynEditor.TextIndexToViewPos(aTextIndex: Integer): Integer; +begin + Result := TextView.TextIndexToViewPos(aTextIndex - 1); +end; + { TIDESynGutter } procedure TIDESynGutter.CreateDefaultGutterParts;