界面库

editable 优化undo
This commit is contained in:
JianjunLiu 2022-08-22 17:10:59 +08:00
parent a06ee66a81
commit 76fa95bd22
2 changed files with 191 additions and 16 deletions

View File

@ -202,8 +202,7 @@ type TTslMenoUndoList=class() //undolist
fItems:TList; fItems:TList;
fLockCount:integer; fLockCount:integer;
fMaxUndoActions; fMaxUndoActions;
function GetCanUndo: function GetCanUndo():boolean;
boolean;
begin begin
return fItems.length()>0; return fItems.length()>0;
end end
@ -218,8 +217,7 @@ type TTslMenoUndoList=class() //undolist
end; end;
end; end;
end end
function GetItemCount: function GetItemCount():integer;
integer;
begin begin
return fItems.length(); return fItems.length();
end end
@ -270,15 +268,13 @@ type TTslMenoUndoList=class() //undolist
if fLockCount>0 then fLockCount--; if fLockCount>0 then fLockCount--;
return fLockCount; return fLockCount;
end end
function PeekItem: function PeekItem():TSynEditUndoItem;
TSynEditUndoItem;
begin begin
iLast := fItems.length()-1; iLast := fItems.length()-1;
if iLast >= 0 then return fItems[iLast]; if iLast >= 0 then return fItems[iLast];
return nil; return nil;
end end
function PopItem: function PopItem():TSynEditUndoItem;
TSynEditUndoItem;
begin begin
if fLockCount>0 then return nil; if fLockCount>0 then return nil;
if fItems.length()then return fItems.Pop(); if fItems.length()then return fItems.Pop();

View File

@ -898,6 +898,11 @@ type teditable=class(TSLUIBASE)
begin begin
s1 := filterstring(s); s1 := filterstring(s);
if s1=fstring then return; if s1=fstring then return;
if fcanundo and (fundolist.locked<1) then
begin
fundolist.AddChange("del",1,-1,FString);
fundolist.AddChange("ins",1,-1,s1);
end
FString := s1; FString := s1;
if FCaretX=1 then if FCaretX=1 then
begin begin
@ -972,7 +977,8 @@ type teditable=class(TSLUIBASE)
X2 := FSelBegin+FSelLength-(FSelLength>0); X2 := FSelBegin+FSelLength-(FSelLength>0);
b := min(x1,x2); b := min(x1,x2);
e := min(max(x1,x2),length(FString)); e := min(max(x1,x2),length(FString));
FString[b:e]:= ""; if fcanundo and (fundolist.locked<1) then fundolist.AddChange("del",b,e,FString[b:e]);
FString[b:e]:= "";
cx := max(1,min(x1,x2)); cx := max(1,min(x1,x2));
InitSel(); InitSel();
BeginUpDate(); BeginUpDate();
@ -1005,13 +1011,18 @@ type teditable=class(TSLUIBASE)
len := length(FString); len := length(FString);
if FCaretX <= length(FString)then if FCaretX <= length(FString)then
begin begin
b := FCaretX;
if bytetype(FString,FCaretX)=1 then if bytetype(FString,FCaretX)=1 then
begin begin
FString[(FCaretX):(FCaretX+1)]:= ""; e := FCaretX+1;
//FString[(FCaretX):(FCaretX+1)]:= "";
end else end else
begin begin
FString[(FCaretX):(FCaretX)]:= ""; e := b;
//FString[(FCaretX):(FCaretX)]:= "";
end end
if fcanundo and (fundolist.locked<1) then fundolist.AddChange("del",b,e,FString[b:e]);
FString[b:e] := "";
BeginUpDate(); BeginUpDate();
InvalidateRect(nil,false); InvalidateRect(nil,false);
DeletePerfect(); DeletePerfect();
@ -1041,15 +1052,18 @@ type teditable=class(TSLUIBASE)
if FCaretX>1 then if FCaretX>1 then
begin begin
cx := FCaretX; cx := FCaretX;
e := FCaretX-1;
if bytetype(FString,FCaretX-1)=2 then if bytetype(FString,FCaretX-1)=2 then
begin begin
FString[(FCaretX-2):(FCaretX-1)]:= ""; b := FCaretX-2;//FString[(FCaretX-2):(FCaretX-1)]:= "";
cx -= 2; cx -= 2;
end else end else
begin begin
FString[(FCaretX-1):(FCaretX-1)]:= ""; b := FCaretX-1;//FString[(FCaretX-1):(FCaretX-1)]:= "";
cx--; cx--;
end end
if fcanundo and (fundolist.locked<1) then fundolist.AddChange("del",b,e,FString[b:e]);
FString[b:e]:= "";
BeginUpDate(); BeginUpDate();
MoveCaretTo(cx,0); MoveCaretTo(cx,0);
DeletePerfect(); DeletePerfect();
@ -1169,6 +1183,9 @@ type teditable=class(TSLUIBASE)
FCaretX := 1; FCaretX := 1;
FLeftCharCount := 0; //1; FLeftCharCount := 0; //1;
FFont := new Tcustomfont(); FFont := new Tcustomfont();
fundolist := new tedolist();
fredolist := new tedolist();
fcanundo := true;
end end
function InsertChar(c_); //²åÈë function InsertChar(c_); //²åÈë
begin begin
@ -1205,6 +1222,7 @@ type teditable=class(TSLUIBASE)
begin begin
if(FFontWidth * (len+1))>(rc[2]-rc[0])then return; if(FFontWidth * (len+1))>(rc[2]-rc[0])then return;
end end
if fcanundo and (fundolist.locked<1) then fundolist.AddChange("ins",FCaretX,-1,c);
if FCaretX=1 then if FCaretX=1 then
begin begin
FString := c+FString; FString := c+FString;
@ -1222,6 +1240,18 @@ type teditable=class(TSLUIBASE)
function ExecuteCommand(cmd,pm);virtual; function ExecuteCommand(cmd,pm);virtual;
begin begin
case cmd of case cmd of
"canundo":
begin
fcanundo := pm;
end
"ecundo":
begin
undo();
end
"ecredo":
begin
redo();
end
"echome": "echome":
begin begin
MoveCaretTo(1,pm); MoveCaretTo(1,pm);
@ -1332,6 +1362,15 @@ type teditable=class(TSLUIBASE)
begin begin
return FCaretX; return FCaretX;
end end
"ecclear":
begin
fundolist.lock();
selectall();
dodelete();
fundolist.clear();
fredolist.clear();
fundolist.lock();
end
end; end;
end end
function GetEntryRect();virtual; function GetEntryRect();virtual;
@ -1373,6 +1412,13 @@ type teditable=class(TSLUIBASE)
begin begin
ExecuteCommand("ecend",fsft); ExecuteCommand("ecend",fsft);
end end
ord("Z"):
begin
if fctl then
begin
ExecuteCommand("ecundo",0);
end
end
ord("C"): ord("C"):
begin begin
if fctl then if fctl then
@ -1593,6 +1639,9 @@ type teditable=class(TSLUIBASE)
property HasFocus read FSetFocused; property HasFocus read FSetFocused;
property Focusedborder read FFocusBorder write FFocusBorder; property Focusedborder read FFocusBorder write FFocusBorder;
private private
fcanundo;
fredolist;
fundolist;
FIsCaretShow; FIsCaretShow;
FKillFocus; FKillFocus;
FOnSetFocus; FOnSetFocus;
@ -1608,6 +1657,56 @@ type teditable=class(TSLUIBASE)
fselbkcolor; fselbkcolor;
freadonlyColor; freadonlyColor;
static FCopyer; static FCopyer;
private
function undo();
begin
if not fcanundo then return ;
it := fundolist.pop();
if not it then return ;
fundolist.lock();
try
doitem(it);
except
end;
case it.freason of
"del":it.freason := "ins";
"ins":it.freason := "del";
end ;
fredolist.AddChange(it);
fundolist.unlock();
//if not canundo then return ;
end
function redo();
begin
if not fcanundo then return ;
it := fredolist.pop();
if not it then return ;
doitem(it);
//if not canundo then return ;
end
function doitem(it);
begin
case it.freason of
"del":
begin
s := it.ftext;
b := it.FStart;
FCaretX := b;
InitSel();
InsertChar(s);
end
"ins":
begin
s := it.ftext;
b := it.FStart;
FSelBegin := b;
FSelLength := length(s);
FCaretX := b+FSelLength;
dodelete();
end
end ;
end
end end
type tVirtualCalender=class(TSLUIBASE) type tVirtualCalender=class(TSLUIBASE)
{** {**
@ -2435,7 +2534,7 @@ type tthreeEntry=class(TCustomControl)
if not ifarray(r)then return array(0,0,0,0); if not ifarray(r)then return array(0,0,0,0);
return r; return r;
end end
function WMCHAR(o,e);override; function WMCHAR(o,e):WM_CHAR;override;
begin begin
case e.char of case e.char of
"0" to "9":return inherited; "0" to "9":return inherited;
@ -5496,7 +5595,7 @@ type tcustomipaddr = class(TCustomControl)
FPrev.ExecuteCommand("ecsel",array(10,1)); FPrev.ExecuteCommand("ecsel",array(10,1));
end end
end end
function WMCHAR(o,e);override; function WMCHAR(o,e):WM_CHAR;override;
begin begin
case e.char of case e.char of
"0" to "9" : "0" to "9" :
@ -5944,6 +6043,86 @@ type TTipWnd=class(TCustomControl) //tip
private private
FSize; FSize;
end end
type tedoitem = class
function create(r,s,e,t);
begin
freason := r;
fstart := s;
fend := e;
ftext := t;
end
function clone();
begin
return new tedoitem(freason,FStart,fend,ftext);
end
freason; //操作
fstart; //开始位置
fend; //截止位置
ftext; //文本
end
type tedolist = class()
public
function create();
begin
flist := new tnumindexarray();
flockct := 0;
end
function citem(r,s,e,t);
begin
return new tedoitem(r,s,e,t);
end
function lock();
begin
flockct++;
end
function unlock();
begin
if flockct>0 then
begin
flockct--;
end
return flockct;
end
function push(it); //弹出
begin
if flockct then return 0;
if ifobj(it) then
begin
flist.push(it);
return 1;
end
end
function peak(); //获取
begin
len := flist.length();
if len>0 then
begin
return flist[len-1];
end
return nil;
end
function pop();
begin
if flockct=0 then
return flist.pop();
return 0;
end
function clear();
begin
if flockct then return ;
flist.splice(nil,nil,array());
flockct := 0;
end
function AddChange(r,s,e,t);
begin
if ifobj(r) then push(r.clone());
push(citem(r,s,e,t));
end
property locked read flockct;
private
flockct; //计数
flist; //链表
end
initialization initialization
{$ifdef linux} {$ifdef linux}