SynEdit / IDE: Keep cursor at position, if codetools makes changes to toher location (like updating component names) issue #12344

git-svn-id: trunk@21829 -
This commit is contained in:
martin 2009-09-22 23:13:04 +00:00
parent 53a1e55eb8
commit d033ed3dfc
4 changed files with 125 additions and 20 deletions

View File

@ -1350,11 +1350,11 @@ begin
NewBlockBegin, NewBlockEnd, KeyChar, Shift);
if (CompareCarets(NewBlockBegin, NewBlockEnd) <> 0) or (Value <> '') then
begin
TextBetweenPoints[NewBlockBegin, NewBlockEnd] := Value;
TextBetweenPointsEx[NewBlockBegin, NewBlockEnd, scamEnd] := Value;
TCustomSynEdit(F.CurrentEditor).SetFocus;
end;
end else begin
TextBetweenPoints[NewBlockBegin, NewBlockEnd] := ItemList[Position];
TextBetweenPointsEx[NewBlockBegin, NewBlockEnd, scamEnd] := ItemList[Position];
TCustomSynEdit(F.CurrentEditor).SetFocus;
end;
end;

View File

@ -176,6 +176,12 @@ type
string; Line, Column: integer; var ReplaceAction: TSynReplaceAction) of object;
TSynEditCaretType = (ctVerticalLine, ctHorizontalLine, ctHalfBlock, ctBlock);
TSynCaretAdjustMode = ( // used in TextBetweenPointsEx
scamIgnore, // Caret stays at the same numeric values, if text is inserted before caret, the text moves, but the caret stays
scamAdjust, // Caret moves with text, if text is inserted
scamEnd,
scamBegin
);
TSynStateFlag = (sfCaretVisible, sfCaretChanged, sfHideCursor,
sfEnsureCursorPos, sfEnsureCursorPosAtResize,
@ -471,6 +477,8 @@ type
procedure SetMouseActions(const AValue: TSynEditMouseActions);
procedure SetMouseSelActions(const AValue: TSynEditMouseActions);
procedure SetTextBetweenPoints(aStartPoint, aEndPoint: TPoint; const AValue: String);
procedure SetTextBetweenPointsEx(aStartPoint, aEndPoint: TPoint;
aCaretMode: TSynCaretAdjustMode; const AValue: String);
procedure SurrenderPrimarySelection;
procedure BookMarkOptionsChanged(Sender: TObject);
procedure ComputeCaret(X, Y: Integer);
@ -850,7 +858,7 @@ type
{$ENDIF}
procedure WndProc(var Msg: TMessage); override;
public
procedure InsertTextAtCaret(aText: String);
procedure InsertTextAtCaret(aText: String; aCaretMode : TSynCaretAdjustMode = scamEnd);
property BlockBegin: TPoint read GetBlockBegin write SetBlockBegin; // Set Blockbegin. For none persistent also sets Blockend. Setting Caret may undo this and should be done before setting block
property BlockEnd: TPoint read GetBlockEnd write SetBlockEnd;
property FoldState: String read GetFoldState write SetFoldState;
@ -890,6 +898,8 @@ type
// Logical Points
property TextBetweenPoints[aStartPoint, aEndPoint: TPoint]: String
read GetTextBetweenPoints write SetTextBetweenPoints;
property TextBetweenPointsEx[aStartPoint, aEndPoint: TPoint; CaretMode: TSynCaretAdjustMode]: String
write SetTextBetweenPointsEx;
property TopLine: Integer read fTopLine write SetTopLine;
{$IFDEF SYN_LAZARUS}
property UseUTF8: boolean read FUseUTF8;
@ -1816,6 +1826,8 @@ begin
FreeAndNil(FHookedKeyTranslationList);
fHookedCommandHandlers:=nil;
fPlugins:=nil;
FCaret.Lines := nil;
FInternalCaret.Lines := nil;
FreeAndNil(fScrollTimer);
FreeAndNil(fTSearch);
FreeAndNil(fMarkupManager);
@ -1832,12 +1844,12 @@ begin
FreeAndNil(fTextDrawer);
FreeAndNil(fFontDummy);
FreeAndNil(FWordBreaker);
FreeAndNil(FFoldedLinesView);
FreeAndNil(FFoldedLinesView); // has reference to caret
FreeAndNil(FInternalBlockSelection);
FreeAndNil(FBlockSelection);
FreeAndNil(FStrings);
FreeAndNil(FTabbedLinesView);
FreeAndNil(FTrimmedLinesView);
FreeAndNil(FTrimmedLinesView); // has reference to caret
FreeAndNil(FDoubleWidthChrLinesView);
FreeAndNil(fLines);
FreeAndNil(fCaret);
@ -4977,12 +4989,33 @@ begin
FInternalBlockSelection.StartLineBytePos := aStartPoint;
FInternalBlockSelection.EndLineBytePos := aEndPoint;
FInternalBlockSelection.SelText := AValue;
FCaret.LineBytePos := FInternalBlockSelection.StartLineBytePos;
finally
EndUndoBlock;
end;
end;
procedure TCustomSynEdit.SetTextBetweenPointsEx(aStartPoint, aEndPoint: TPoint;
aCaretMode: TSynCaretAdjustMode; const AValue: String);
begin
BeginUndoBlock;
try
if aCaretMode = scamAdjust then
FCaret.AutoMoveOnEdit := True;
FInternalBlockSelection.SelectionMode := smNormal;
FInternalBlockSelection.StartLineBytePos := aStartPoint;
FInternalBlockSelection.EndLineBytePos := aEndPoint;
if aCaretMode = scamBegin then
FCaret.LineBytePos := FInternalBlockSelection.StartLineBytePos;
FInternalBlockSelection.SelText := AValue;
if aCaretMode = scamEnd then
FCaret.LineBytePos := FInternalBlockSelection.StartLineBytePos;
finally
if aCaretMode = scamAdjust then
FCaret.AutoMoveOnEdit := False;
EndUndoBlock;
end;
end;
function TCustomSynEdit.GetLineState(ALine: Integer): TSynLineState;
begin
with TSynEditStringList(fLines) do
@ -5089,9 +5122,9 @@ begin
inherited;
end;
procedure TCustomSynEdit.InsertTextAtCaret(aText: String);
procedure TCustomSynEdit.InsertTextAtCaret(aText: String; aCaretMode : TSynCaretAdjustMode = scamEnd);
begin
TextBetweenPoints[FCaret.LineBytePos, FCaret.LineBytePos] := aText;
TextBetweenPointsEx[FCaret.LineBytePos, FCaret.LineBytePos, aCaretMode] := aText;
end;
procedure TCustomSynEdit.DragOver(Source: TObject; X, Y: Integer;
@ -6063,7 +6096,7 @@ begin
ecBlockCopy:
begin
if SelAvail then
InsertTextAtCaret(FBlockSelection.SelText);
InsertTextAtCaret(FBlockSelection.SelText, scamEnd);
end;
ecBlockDelete:
begin

View File

@ -54,6 +54,7 @@ type
FLines: TSynEditStrings;
FOnChangeList: TMethodList;
FLockCount: Integer;
procedure SetLines(const AValue: TSynEditStrings); virtual;
procedure DoLock; virtual;
Procedure DoUnlock; virtual;
public
@ -64,7 +65,7 @@ type
procedure RemoveChangeHandler(AHandler: TNotifyEvent);
procedure Lock;
Procedure Unlock;
property Lines: TSynEditStrings read FLines write FLines;
property Lines: TSynEditStrings read FLines write SetLines;
property Locked: Boolean read GetLocked;
end;
@ -168,6 +169,7 @@ type
TSynEditCaret = class(TSynEditPointBase)
private
FAllowPastEOL: Boolean;
FAutoMoveOnEdit: Boolean;
FForcePastEOL: Integer;
FForceAdjustToNextChar: Integer;
FKeepCaretX: Boolean;
@ -200,10 +202,14 @@ type
procedure SetLineText(const AValue : string);
procedure SetSkipTabs(const AValue: Boolean);
protected
procedure SetLines(const AValue: TSynEditStrings); override;
procedure DoLock; override;
Procedure DoUnlock; override;
procedure DoLinesEdited(Sender: TSynEditStrings; aLinePos, aBytePos, aCount,
aLineBrkCnt: Integer; aText: String);
public
constructor Create;
destructor Destroy; override;
procedure AssignFrom(Src: TSynEditCaret);
procedure IncForcePastEOL;
procedure DecForcePastEOL;
@ -228,6 +234,7 @@ type
property AllowPastEOL: Boolean read FAllowPastEOL write SetAllowPastEOL;
property KeepCaretX: Boolean read FKeepCaretX write SetKeepCaretX;
property MaxLeftChar: PInteger write FMaxLeftChar;
property AutoMoveOnEdit: Boolean write FAutoMoveOnEdit;
end;
implementation
@ -239,6 +246,11 @@ begin
Result := FLockCount > 0;
end;
procedure TSynEditPointBase.SetLines(const AValue: TSynEditStrings);
begin
FLines := AValue;
end;
procedure TSynEditPointBase.DoLock;
begin
end;
@ -298,6 +310,15 @@ begin
fCharPos:= 1;
FAllowPastEOL := True;
FForcePastEOL := 0;
if FLines <> nil then
FLines.AddEditHandler(@DoLinesEdited);
end;
destructor TSynEditCaret.Destroy;
begin
if FLines <> nil then
FLines.RemoveEditHandler(@DoLinesEdited);
inherited Destroy;
end;
procedure TSynEditCaret.AssignFrom(Src: TSynEditCaret);
@ -519,6 +540,16 @@ begin
end;
end;
procedure TSynEditCaret.SetLines(const AValue: TSynEditStrings);
begin
if FLines = AValue then exit;
if FLines <> nil then
FLines.RemoveEditHandler(@DoLinesEdited);
inherited SetLines(AValue);
if FLines <> nil then
FLines.AddEditHandler(@DoLinesEdited);
end;
procedure TSynEditCaret.DoLock;
begin
FTouched := False;
@ -539,6 +570,47 @@ begin
FOldLinePos := FLinePos;
end;
procedure TSynEditCaret.DoLinesEdited(Sender: TSynEditStrings; aLinePos, aBytePos, aCount,
aLineBrkCnt: Integer; aText: String);
// Todo: refactor / this is a copy from selection
function AdjustPoint(aPoint: Tpoint): TPoint; inline;
begin
Result := aPoint;
if aLineBrkCnt < 0 then begin
(* Lines Deleted *)
if aPoint.y > aLinePos then begin
Result.y := Max(aLinePos, Result.y + aLineBrkCnt);
if Result.y = aLinePos then
Result.x := Result.x + aBytePos - 1;
end;
end
else
if aLineBrkCnt > 0 then begin
(* Lines Inserted *)
if (aPoint.y = aLinePos) and (aPoint.x >= aBytePos) then begin
Result.x := Result.x - aBytePos + 1;
Result.y := Result.y + aLineBrkCnt;
end;
if aPoint.y > aLinePos then begin
Result.y := Result.y + aLineBrkCnt;
end;
end
else
if aCount <> 0 then begin
(* Chars Insert/Deleted *)
if (aPoint.y = aLinePos) and (aPoint.x >= aBytePos) then
Result.x := Max(aBytePos, Result.x + aCount);
end;
end;
begin
if FAutoMoveOnEdit then begin
IncForcePastEOL;
LineBytePos := AdjustPoint(LineBytePos);
DecForcePastEOL;
end;
end;
{ TSynEditSelection }
constructor TSynEditSelection.Create(ALines : TSynEditStrings; aActOnLineChanges: Boolean);

View File

@ -2607,13 +2607,13 @@ procedure TSourceEditor.OnCodeBufferChanged(Sender: TSourceLog;
var Txt: string;
begin
if DirectionForward then begin
FEditor.TextBetweenPoints[MoveToPos, MoveToPos] :=
FEditor.TextBetweenPointsEx[MoveToPos, MoveToPos, scamAdjust] :=
FEditor.TextBetweenPoints[StartPos, EndPos];
FEditor.TextBetweenPoints[StartPos, EndPos] := '';
FEditor.TextBetweenPointsEx[StartPos, EndPos, scamAdjust] := '';
end else begin
Txt := FEditor.TextBetweenPoints[StartPos, EndPos];
FEditor.TextBetweenPoints[StartPos, EndPos] := '';
FEditor.TextBetweenPoints[MoveToPos, MoveToPos] := Txt;;
FEditor.TextBetweenPointsEx[StartPos, EndPos, scamAdjust] := '';
FEditor.TextBetweenPointsEx[MoveToPos, MoveToPos, scamAdjust] := Txt;;
end;
end;
@ -2634,7 +2634,7 @@ begin
begin
Sender.AbsoluteToLineCol(SrcLogEntry.Position,StartPos.Y,StartPos.X);
if StartPos.Y>=1 then
FEditor.TextBetweenPoints[StartPos, StartPos] := SrcLogEntry.Txt;
FEditor.TextBetweenPointsEx[StartPos, StartPos, scamAdjust] := SrcLogEntry.Txt;
end;
sleoDelete:
begin
@ -2642,7 +2642,7 @@ begin
Sender.AbsoluteToLineCol(SrcLogEntry.Position+SrcLogEntry.Len,
EndPos.Y,EndPos.X);
if (StartPos.Y>=1) and (EndPos.Y>=1) then
FEditor.TextBetweenPoints[StartPos, EndPos] := '';
FEditor.TextBetweenPointsEx[StartPos, EndPos, scamAdjust] := '';
end;
sleoMove:
begin
@ -2806,9 +2806,9 @@ procedure TSourceEditor.ReplaceLines(StartLine, EndLine: integer;
const NewText: string);
begin
if ReadOnly then Exit;
FEditor.TextBetweenPoints[Point(1,StartLine),
Point(length(FEditor.Lines[Endline-1])+1,EndLine)] :=
NewText;
FEditor.TextBetweenPointsEx[Point(1,StartLine),
Point(length(FEditor.Lines[Endline-1])+1,EndLine),
scamEnd] := NewText;
end;
procedure TSourceEditor.EncloseSelection;
@ -4020,7 +4020,7 @@ Begin
SrcEdit:=GetActiveSE;
Editor:=SrcEdit.EditorComponent;
if ValueType <> icvNone then
Editor.TextBetweenPoints[SourceStart, SourceEnd] := NewValue;
Editor.TextBetweenPointsEx[SourceStart, SourceEnd, scamEnd] := NewValue;
if CursorToLeft>0 then
begin
NewCaretXY:=Editor.CaretXY;