SynEdit, SourceEdtior: Decouple UndoBlock from UpdateBlock

git-svn-id: trunk@28602 -
This commit is contained in:
martin 2010-12-03 02:10:35 +00:00
parent d1792391e0
commit ba8f8d4e90
4 changed files with 130 additions and 39 deletions

View File

@ -1592,6 +1592,7 @@ begin
if F.CurrentEditor is TCustomSynEdit then if F.CurrentEditor is TCustomSynEdit then
with TCustomSynEdit(F.CurrentEditor) do begin with TCustomSynEdit(F.CurrentEditor) do begin
BeginUndoBlock; BeginUndoBlock;
BeginUpdate;
LogCaret:=PhysicalToLogicalPos(CaretXY); LogCaret:=PhysicalToLogicalPos(CaretXY);
NewBlockBegin:=LogCaret; NewBlockBegin:=LogCaret;
CurLine:=Lines[NewBlockBegin.Y - 1]; CurLine:=Lines[NewBlockBegin.Y - 1];
@ -1627,6 +1628,7 @@ begin
TCustomSynEdit(F.CurrentEditor).SetFocus; TCustomSynEdit(F.CurrentEditor).SetFocus;
end; end;
end; end;
EndUpdate;
EndUndoBlock; EndUndoBlock;
end; end;
end; end;

View File

@ -597,6 +597,8 @@ type
procedure DestroyMarkList; procedure DestroyMarkList;
procedure RemoveHandlers(ALines: TSynEditStrings = nil); procedure RemoveHandlers(ALines: TSynEditStrings = nil);
procedure ExtraLineCharsChanged(Sender: TObject); procedure ExtraLineCharsChanged(Sender: TObject);
procedure InternalBeginUndoBlock(aList: TSynEditUndoList = nil); // includes paintlock
procedure InternalEndUndoBlock(aList: TSynEditUndoList = nil);
protected protected
procedure CreateHandle; override; procedure CreateHandle; override;
procedure CreateParams(var Params: TCreateParams); override; procedure CreateParams(var Params: TCreateParams); override;
@ -738,7 +740,7 @@ type
procedure AddKey(Command: TSynEditorCommand; Key1: word; SS1: TShiftState; procedure AddKey(Command: TSynEditorCommand; Key1: word; SS1: TShiftState;
Key2: word; SS2: TShiftState); Key2: word; SS2: TShiftState);
procedure AfterLoadFromFile; procedure AfterLoadFromFile;
procedure BeginUndoBlock(aList: TSynEditUndoList = nil); procedure BeginUndoBlock;
procedure BeginUpdate; procedure BeginUpdate;
function CaretXPix: Integer; function CaretXPix: Integer;
function CaretYPix: Integer; function CaretYPix: Integer;
@ -755,7 +757,7 @@ type
destructor Destroy; override; destructor Destroy; override;
procedure DoCopyToClipboard(SText: string; FoldInfo: String = ''); procedure DoCopyToClipboard(SText: string; FoldInfo: String = '');
procedure DragDrop(Source: TObject; X, Y: Integer); override; procedure DragDrop(Source: TObject; X, Y: Integer); override;
procedure EndUndoBlock(aList: TSynEditUndoList = nil); procedure EndUndoBlock;
procedure EndUpdate; procedure EndUpdate;
procedure EnsureCursorPosVisible; procedure EnsureCursorPosVisible;
{$IFDEF SYN_COMPILER_4_UP} {$IFDEF SYN_COMPILER_4_UP}
@ -4009,7 +4011,7 @@ var
PasteAction: TSynCopyPasteAction; PasteAction: TSynCopyPasteAction;
begin begin
Result := False; Result := False;
BeginUndoBlock; InternalBeginUndoBlock;
try try
PTxt := ClipHelper.TextP; PTxt := ClipHelper.TextP;
PMode := ClipHelper.SelectionMode; PMode := ClipHelper.SelectionMode;
@ -4050,7 +4052,7 @@ begin
end; end;
end; end;
finally finally
EndUndoBlock; InternalEndUndoBlock;
end; end;
end; end;
@ -4296,11 +4298,11 @@ end;
procedure TCustomSynEdit.SetSelTextExternal(const Value: string); procedure TCustomSynEdit.SetSelTextExternal(const Value: string);
begin begin
// undo entry added // undo entry added
BeginUndoBlock; InternalBeginUndoBlock;
try try
FBlockSelection.SelText := Value; FBlockSelection.SelText := Value;
finally finally
EndUndoBlock; InternalEndUndoBlock;
end; end;
end; end;
@ -5016,7 +5018,7 @@ begin
FTheLinesView.IsRedoing := True; FTheLinesView.IsRedoing := True;
Item := Group.Pop; Item := Group.Pop;
if Item <> nil then begin if Item <> nil then begin
BeginUndoBlock; InternalBeginUndoBlock;
fUndoList.CurrentGroup.Reason := Group.Reason; fUndoList.CurrentGroup.Reason := Group.Reason;
fUndoList.IsInsideRedo := True; fUndoList.IsInsideRedo := True;
try try
@ -5025,7 +5027,7 @@ begin
Item := Group.Pop; Item := Group.Pop;
until (Item = nil); until (Item = nil);
finally finally
EndUndoBlock; InternalEndUndoBlock;
end; end;
end; end;
FTheLinesView.IsRedoing := False; FTheLinesView.IsRedoing := False;
@ -5125,7 +5127,7 @@ begin
FTheLinesView.IsUndoing := True; FTheLinesView.IsUndoing := True;
Item := Group.Pop; Item := Group.Pop;
if Item <> nil then begin if Item <> nil then begin
BeginUndoBlock(fRedoList); InternalBeginUndoBlock(fRedoList);
fRedoList.CurrentGroup.Reason := Group.Reason; fRedoList.CurrentGroup.Reason := Group.Reason;
fUndoList.Lock; fUndoList.Lock;
try try
@ -5137,7 +5139,7 @@ begin
// Todo: Decide what do to, If there are any trimable spaces. // Todo: Decide what do to, If there are any trimable spaces.
FTrimmedLinesView.ForceTrim; FTrimmedLinesView.ForceTrim;
fUndoList.UnLock; fUndoList.UnLock;
EndUndoBlock(fRedoList); InternalEndUndoBlock(fRedoList);
end; end;
end; end;
FTheLinesView.IsUndoing := False; FTheLinesView.IsUndoing := False;
@ -5490,21 +5492,21 @@ end;
procedure TCustomSynEdit.SetTextBetweenPoints(aStartPoint, aEndPoint: TPoint; procedure TCustomSynEdit.SetTextBetweenPoints(aStartPoint, aEndPoint: TPoint;
const AValue: String); const AValue: String);
begin begin
BeginUndoBlock; InternalBeginUndoBlock;
try try
FInternalBlockSelection.SelectionMode := smNormal; FInternalBlockSelection.SelectionMode := smNormal;
FInternalBlockSelection.StartLineBytePos := aStartPoint; FInternalBlockSelection.StartLineBytePos := aStartPoint;
FInternalBlockSelection.EndLineBytePos := aEndPoint; FInternalBlockSelection.EndLineBytePos := aEndPoint;
FInternalBlockSelection.SelText := AValue; FInternalBlockSelection.SelText := AValue;
finally finally
EndUndoBlock; InternalEndUndoBlock;
end; end;
end; end;
procedure TCustomSynEdit.SetTextBetweenPointsEx(aStartPoint, aEndPoint: TPoint; procedure TCustomSynEdit.SetTextBetweenPointsEx(aStartPoint, aEndPoint: TPoint;
aCaretMode: TSynCaretAdjustMode; const AValue: String); aCaretMode: TSynCaretAdjustMode; const AValue: String);
begin begin
BeginUndoBlock; InternalBeginUndoBlock;
try try
if aCaretMode = scamAdjust then if aCaretMode = scamAdjust then
FCaret.IncAutoMoveOnEdit; FCaret.IncAutoMoveOnEdit;
@ -5519,7 +5521,7 @@ begin
finally finally
if aCaretMode = scamAdjust then if aCaretMode = scamAdjust then
FCaret.DecAutoMoveOnEdit; FCaret.DecAutoMoveOnEdit;
EndUndoBlock; InternalEndUndoBlock;
end; end;
end; end;
@ -5666,7 +5668,7 @@ begin
or ((NewCaret.Y = BB.Y) and (NewCaret.X < BB.X)); or ((NewCaret.Y = BB.Y) and (NewCaret.X < BB.X));
end; end;
if DoDrop then begin if DoDrop then begin
BeginUndoBlock; //mh 2000-11-20 InternalBeginUndoBlock; //mh 2000-11-20
try try
DragDropText := TCustomSynEdit(Source).SelText; DragDropText := TCustomSynEdit(Source).SelText;
BlockSel := TCustomSynEdit(Source).FBlockSelection; BlockSel := TCustomSynEdit(Source).FBlockSelection;
@ -5714,7 +5716,7 @@ begin
BlockEnd := {$IFDEF SYN_LAZARUS}PhysicalToLogicalPos(CaretXY) BlockEnd := {$IFDEF SYN_LAZARUS}PhysicalToLogicalPos(CaretXY)
{$ELSE}CaretXY{$ENDIF}; {$ELSE}CaretXY{$ENDIF};
finally finally
EndUndoBlock; InternalEndUndoBlock;
end; end;
end; end;
finally finally
@ -5996,7 +5998,7 @@ begin
DoOnProcessCommand(Command, AChar, Data); DoOnProcessCommand(Command, AChar, Data);
if Command <> ecNone then begin if Command <> ecNone then begin
try try
BeginUndoBlock; InternalBeginUndoBlock;
FBeautifyStartLineIdx := -1; FBeautifyStartLineIdx := -1;
FBeautifyEndLineIdx := -1; FBeautifyEndLineIdx := -1;
if assigned(FBeautifier) then begin if assigned(FBeautifier) then begin
@ -6024,7 +6026,7 @@ begin
FBeautifyStartLineIdx+1, FBeautifyEndLineIdx+1); FBeautifyStartLineIdx+1, FBeautifyEndLineIdx+1);
end; end;
finally finally
EndUndoBlock; InternalEndUndoBlock;
end; end;
end; end;
end; end;
@ -6629,10 +6631,10 @@ end;
procedure TCustomSynEdit.ClearAll; procedure TCustomSynEdit.ClearAll;
begin begin
{$IFDEF SYN_LAZARUS} {$IFDEF SYN_LAZARUS}
BeginUndoBlock; InternalBeginUndoBlock;
SelectAll; SelectAll;
SelText:=''; SelText:='';
EndUndoBlock; InternalEndUndoBlock;
{$ELSE} {$ELSE}
Lines.Clear; Lines.Clear;
{$ENDIF} {$ENDIF}
@ -6654,8 +6656,7 @@ begin
fBlockSelection.ActiveSelectionMode := Value; fBlockSelection.ActiveSelectionMode := Value;
end; end;
{begin} //sbs 2000-11-19 procedure TCustomSynEdit.InternalBeginUndoBlock(aList: TSynEditUndoList);
procedure TCustomSynEdit.BeginUndoBlock(aList: TSynEditUndoList = nil);
begin begin
if aList = nil then aList := fUndoList; if aList = nil then aList := fUndoList;
aList.OnNeedCaretUndo := {$IFDEF FPC}@{$ENDIF}GetCaretUndo; aList.OnNeedCaretUndo := {$IFDEF FPC}@{$ENDIF}GetCaretUndo;
@ -6663,15 +6664,8 @@ begin
IncPaintLock; IncPaintLock;
FFoldedLinesView.Lock; FFoldedLinesView.Lock;
end; end;
{end} //sbs 2000-11-19
procedure TCustomSynEdit.BeginUpdate; procedure TCustomSynEdit.InternalEndUndoBlock(aList: TSynEditUndoList);
begin
IncPaintLock;
end;
{begin} //sbs 2000-11-19
procedure TCustomSynEdit.EndUndoBlock(aList: TSynEditUndoList = nil);
begin begin
if aList = nil then aList := fUndoList; if aList = nil then aList := fUndoList;
// Write all trimming info to the end of the undo block, // Write all trimming info to the end of the undo block,
@ -6682,7 +6676,28 @@ begin
DecPaintLock; DecPaintLock;
aList.EndBlock; // Todo: Doing this after DecPaintLock, can cause duplicate calls to StatusChanged(scModified) aList.EndBlock; // Todo: Doing this after DecPaintLock, can cause duplicate calls to StatusChanged(scModified)
end; end;
{end} //sbs 2000-11-19
procedure TCustomSynEdit.BeginUndoBlock;
begin
fUndoList.OnNeedCaretUndo := {$IFDEF FPC}@{$ENDIF}GetCaretUndo;
fUndoList.BeginBlock;
////FFoldedLinesView.Lock;
//FTrimmedLinesView.Lock;
end;
procedure TCustomSynEdit.BeginUpdate;
begin
IncPaintLock;
end;
procedure TCustomSynEdit.EndUndoBlock;
begin
// Write all trimming info to the end of the undo block,
// so it will be undone first, and other UndoItems do see the expected spaces
//FTrimmedLinesView.UnLock;
////FFoldedLinesView.UnLock;
fUndoList.EndBlock;
end;
procedure TCustomSynEdit.EndUpdate; procedure TCustomSynEdit.EndUpdate;
begin begin
@ -7565,7 +7580,7 @@ begin
exit; exit;
end; end;
BeginUndoBlock; InternalBeginUndoBlock;
try try
i := 0; i := 0;
OldCaretX := CaretX; OldCaretX := CaretX;
@ -7609,7 +7624,7 @@ begin
CaretX := OldCaretX + i; CaretX := OldCaretX + i;
//debugln('TCustomSynEdit.DoTabKey StartOfBlock=',dbgs(StartOfBlock),' fBlockEnd=',dbgs(fBlockEnd),' Spaces="',Spaces,'"'); //debugln('TCustomSynEdit.DoTabKey StartOfBlock=',dbgs(StartOfBlock),' fBlockEnd=',dbgs(fBlockEnd),' Spaces="',Spaces,'"');
finally finally
EndUndoBlock; InternalEndUndoBlock;
end; end;
EnsureCursorPosVisible; EnsureCursorPosVisible;
end; end;

View File

@ -17,7 +17,7 @@ or between two empty lines
uses uses
Classes, SysUtils, Forms, testregistry, TestBase, LCLProc, LCLType, Classes, SysUtils, Forms, testregistry, TestBase, LCLProc, LCLType,
SynEdit, SynEditKeyCmds; SynEdit, SynEditKeyCmds, SynEditTextTrimmer;
type type
@ -43,6 +43,7 @@ type
procedure TrimUndoRedo; procedure TrimUndoRedo;
procedure TrimUndoRedoEc; procedure TrimUndoRedoEc;
procedure NoTrimUndoRedo; procedure NoTrimUndoRedo;
procedure TestInUndoBlock;
end; end;
implementation implementation
@ -63,14 +64,14 @@ begin
AssertEquals(FTName+' ('+ASubName+') Caret X', AExpX, SynEdit.CaretX); AssertEquals(FTName+' ('+ASubName+') Caret X', AExpX, SynEdit.CaretX);
AssertEquals(FTName+' ('+ASubName+') Caret Y', AExpY, SynEdit.CaretY); AssertEquals(FTName+' ('+ASubName+') Caret Y', AExpY, SynEdit.CaretY);
end; end;
debugln(['done ',ASubName]); //debugln(['done ',ASubName]);
end; end;
procedure TTestTrimSpace.test_start(AName, Txt: String); procedure TTestTrimSpace.test_start(AName, Txt: String);
begin begin
FTName := AName; FTName := AName;
SynEdit.Text := Txt; SynEdit.Text := Txt;
debugln(['----- START ',AName]); //debugln(['----- START ',AName]);
end; end;
@ -525,6 +526,74 @@ begin
end; end;
procedure TTestTrimSpace.TestInUndoBlock;
type TUpdateMode = (umNone, umOuter, umInner);
var UpdateMode: TUpdateMode;
procedure BeginUndoBlock;
begin
if UpdateMode = umOuter then SynEdit.BeginUpdate;
SynEdit.BeginUndoBlock;
if UpdateMode = umInner then SynEdit.BeginUpdate;
end;
procedure EndUndoBlock;
begin
if UpdateMode = umInner then SynEdit.EndUpdate;
SynEdit.EndUndoBlock;
if UpdateMode = umOuter then SynEdit.EndUpdate;
end;
procedure DoTestInUndoBlock;
begin
ReCreateEdit;
SynEdit.Options := [eoTrimTrailingSpaces, eoAutoIndent, eoScrollPastEol]; // eoGroupUndo
SynEdit.TrimSpaceType := settLeaveLine;
SetLines(['abc d', 'mno', 'xyz', '']);
SetCaret(1,1);
// need to add space later, so it is regocnized as trailing
BeginUndoBlock;
SynEdit.TextBetweenPointsEx[point(5,1), point(6,1), scamEnd] := ''; // delete d
SynEdit.TextBetweenPointsEx[point(4,2), point(4,2), scamEnd] := ' '; // add space
EndUndoBlock;
TestIsFullText ('modified after block', ['abc', 'mno ', 'xyz', '']);
TestIsCaret('modified after block', 5,2);
SynEdit.Undo;
TestIsFullText ('Undone', ['abc d', 'mno', 'xyz', '']);
TestIsCaret('UnDone', 1,1);
SynEdit.Redo;
TestIsFullText ('Redone', ['abc', 'mno ', 'xyz', '']);
TestIsCaret('Redone', 5,2);
SynEdit.Undo;
TestIsFullText ('Undone 2', ['abc d', 'mno', 'xyz', '']);
TestIsCaret('UnDone 2', 1,1);
SynEdit.Redo;
TestIsFullText ('Redone 2', ['abc', 'mno ', 'xyz', '']);
TestIsCaret('Redone 2', 5,2);
end;
begin
UpdateMode := umNone;
PushBaseName('Without BeginUpdate');
DoTestInUndoBlock;
UpdateMode := umInner;
PushBaseName('With BeginUpdate inside');
DoTestInUndoBlock;
UpdateMode := umOuter;
PushBaseName('With BeginUpdate outside');
DoTestInUndoBlock;
PopBaseName;
end;
initialization initialization

View File

@ -2170,6 +2170,7 @@ begin
CodeToolsInSync:=not NeedsUpdateCodeBuffer; CodeToolsInSync:=not NeedsUpdateCodeBuffer;
if SrcLogEntry<>nil then begin if SrcLogEntry<>nil then begin
SynEditor.BeginUndoBlock; SynEditor.BeginUndoBlock;
SynEditor.BeginUpdate;
SynEditor.TemplateEdit.IncExternalEditLock; SynEditor.TemplateEdit.IncExternalEditLock;
SynEditor.SyncroEdit.IncExternalEditLock; SynEditor.SyncroEdit.IncExternalEditLock;
try try
@ -2202,6 +2203,7 @@ begin
finally finally
SynEditor.SyncroEdit.DecExternalEditLock; SynEditor.SyncroEdit.DecExternalEditLock;
SynEditor.TemplateEdit.DecExternalEditLock; SynEditor.TemplateEdit.DecExternalEditLock;
SynEditor.EndUpdate;
SynEditor.EndUndoBlock; SynEditor.EndUndoBlock;
end; end;
end else begin end else begin
@ -3384,7 +3386,6 @@ var
P: TPoint; P: TPoint;
begin begin
if ReadOnly then exit; if ReadOnly then exit;
FEditor.BeginUpdate;
FEditor.BeginUndoBlock; FEditor.BeginUndoBlock;
if not EditorComponent.SelAvail then begin if not EditorComponent.SelAvail then begin
P.Y := FEditor.CaretY; P.Y := FEditor.CaretY;
@ -3398,9 +3399,9 @@ begin
i:=EditorOpts.HighlighterList.FindByHighlighter(FEditor.Highlighter); i:=EditorOpts.HighlighterList.FindByHighlighter(FEditor.Highlighter);
if i>=0 then if i>=0 then
IsPascal := EditorOpts.HighlighterList[i].DefaultCommentType <> comtCPP; IsPascal := EditorOpts.HighlighterList[i].DefaultCommentType <> comtCPP;
// will show modal dialog - must not be in Editor.BeginUpdate block, or painting will not work
FEditor.SelText:=AddConditional(EditorComponent.SelText,IsPascal); FEditor.SelText:=AddConditional(EditorComponent.SelText,IsPascal);
FEditor.EndUndoBlock; FEditor.EndUndoBlock;
FEditor.EndUpdate;
end; end;
procedure TSourceEditor.SortSelection; procedure TSourceEditor.SortSelection;
@ -3884,9 +3885,11 @@ begin
// user typed 'begin' // user typed 'begin'
if not LazarusIDE.SaveSourceEditorChangesToCodeCache(self) then exit; if not LazarusIDE.SaveSourceEditorChangesToCodeCache(self) then exit;
FEditor.BeginUndoBlock; FEditor.BeginUndoBlock;
FEditor.BeginUpdate;
try try
if not CodeToolBoss.CompleteBlock(CodeBuffer,p.X,p.Y,true) then exit; if not CodeToolBoss.CompleteBlock(CodeBuffer,p.X,p.Y,true) then exit;
finally finally
FEditor.EndUpdate;
FEditor.EndUndoBlock; FEditor.EndUndoBlock;
end; end;
end; end;
@ -3901,6 +3904,7 @@ begin
if not LazarusIDE.SaveSourceEditorChangesToCodeCache(self) then exit; if not LazarusIDE.SaveSourceEditorChangesToCodeCache(self) then exit;
XY:=FEditor.LogicalCaretXY; XY:=FEditor.LogicalCaretXY;
FEditor.BeginUndoBlock; FEditor.BeginUndoBlock;
FEditor.BeginUpdate;
try try
if not CodeToolBoss.CompleteBlock(CodeBuffer,XY.X,XY.Y,false, if not CodeToolBoss.CompleteBlock(CodeBuffer,XY.X,XY.Y,false,
NewCode,NewX,NewY,NewTopLine) then exit; NewCode,NewX,NewY,NewTopLine) then exit;
@ -3913,6 +3917,7 @@ begin
FEditor.LogicalCaretXY:=XY; FEditor.LogicalCaretXY:=XY;
end; end;
finally finally
FEditor.EndUpdate;
FEditor.EndUndoBlock; FEditor.EndUndoBlock;
end; end;
end; end;