tslediter/funcext/tvclib/utslvclcoolbar.tsf

677 lines
19 KiB
Plaintext

unit utslvclcoolbar;
interface
uses utslvclauxiliary,utslvclgdi;
type tcustomcoolbar=class(tcustomcontrol)
function Create(AOwner);
begin
fcoolbands := new tcoolbarlines();
frowheight := 30;
fbtnwidth := 20;
fautosize := true;
inherited;
FWill_Drag := true;
cimgst();
fsizebtncolor := _wapi.GetSysColor(COLOR_MENUBAR);
fdragbtncolor := fsizebtncolor;
end
function ControlAppended(AControl);override;
begin
{**
@explan(说明) 子控件添加 %%
**}
it := new tcoolband(AControl);
fcoolbands.appendrow(it);
end
function ControlDeleted(AControl);override;
begin
{**
@explan(说明) 子控件删除 %%
**}
fcoolbands.deleteitem(AControl);
end
function Notification(o,op);override;
begin
return inherited;
if ifarray(op) then
begin
ctls := controls;
if (ctls.IndexOf(o)>=0) then
begin
//echo tostn(op);
flg := op["flag"];
if flag>0 and ((flag .& 4 ) or (flg .& 8)) then
begin
echo "\r\n",tostn(op);
end
end
end
inherited;
end
function MouseUp(o,e);override;
begin
if csDesigning in ComponentState then exit;
if e.button=mbLeft then
begin
if FIs_Draging then
begin
_wapi.ImageList_DragLeave(self.Handle);
_wapi.ImageList_EndDrag();
if fdragenode then
begin
r := fcoolbands.getnodebyxy(e.xpos,e.ypos);
if fcoolbands.moveitemto(fdragenode,r[0],r[1]) then
begin
doControlALign();
InvalidateRect(nil,false);
r := getarrange();
echo tostn(r);
end
end else
if fsizenode then
begin
ctl := fsizenode.fctl;
clr := ctl.BoundsRect;
y := e.ypos;
if y> clr[1] and (y<clr[1]+clr[3]) then
begin
nwid := e.xpos-ctl.left;
if nwid>10 then
begin
ctl.Width := nwid;
doControlALign();
InvalidateRect(nil,false);
end
end
end
r := ClientRect;
EnabledChild(true);
FWill_Drag := true;
FIs_Draging := false;
_wapi.clipcursor(0);
end
end
inherited;
end
function MouseDown(o,e);override;
begin
if csDesigning in ComponentState then exit;
if e.button=mbLeft then
begin
xy := e.pos;
trk := -1;
for i,v in fcoolbands.data do
begin
if pointinrect(xy,v.fdragrect) then
begin
trk := 0;
fdragenode := v;
fsizenode := nil;
break;
end
if pointinrect(xy,v.fsizerect) then
begin
trk := 1;
fdragenode := nil;
fsizenode := v;
break;
end
end
if trk<0 then return ;
nxy := clienttowindow(e.xpos,e.ypos);
if FWill_Drag then
begin
FWill_Drag := false;
FIs_Draging := true;
_wapi.ImageList_BeginDrag(FDRageimglist.Handle,trk,12,12);
_wapi.ImageList_DragEnter(self.Handle,nxy[0],nxy[1]);
crect := clientrect;
ps := array(clienttoscreen(crect[0],crect[1]),clienttoscreen(crect[2],crect[3]));
_wapi.clipcursor(ps);
EnabledChild(false);
end
end
inherited;
end
function MouseMove(o,e);override;
begin
if FIs_Draging then
begin
nxy := clienttowindow(e.xpos,e.ypos);
_wapi.ImageList_DragMove(nxy[0],nxy[1]);
end
inherited;
end
function doControlALign();override;
begin
mwid := 10;
swid := 12;
y := 0;
rhs := fcoolbands.getrowheights();
if autosize then
begin
rc := ClientRect;
nh := sum(rhs);
h := rc[3]-rc[1];
dh := h-nh;
if abs(dh)>4 then
begin
Align := alNone;
Height := (border*2)+nh;
Align := alTop;
return ;
end
end
for i,v in fcoolbands.data2 do
begin
x := 0;
for j,bsi in v do
begin
ctl := bsi.fctl;
if ctl.Visible then
begin
bsi.fdragrect := array(x,y,x+mwid,y+rhs[i]);
h := ctl.Height;
w := ctl.Width;
x += mwid;
bsi.fctlrect := array(x,y,w,h);
dy := 0;
if (rhs[i]-h)>2 then
begin
dy := integer((rhs[i]-h)/2);
end
ctl.SetBounds(x,y+dy,w,h);
x+=w;
bsi.fsizerect := array(x,y,x+swid,y+rhs[i]);
x+=swid;
end else
begin
bsi.fdragrect := array(0,0,0,0);
bsi.fctlrect := array(0,0,0,0);
bsi.fsizerect := array(0,0,0,0);
end
end
bsi.fsizerect := array(0,0,0,0);
y+=rhs[i];
end
end
function paint();override;
begin
dc := canvas;
cl := dc.brush.color;
bcl := dc.pen.color;
dc.pen.color := 0xDCDCDC;
rhs := fcoolbands.getrowheights();
y := 0;
for i:= 0 to length(rhs)-2 do
begin
y +=rhs[i];
dc.moveto(array(0,y));
dc.lineto(array(width,y));
end
for i,v in fcoolbands.data do
begin
//dc.brush.color := 0x87CEEB;
dc.brush.color := fdragbtncolor;
rc1 := v.fdragrect;
rc1[0]+=1;
rc1[1]+=1;
rc1[2]-=1;
rc1[3]-=1;
dc.fillrect(rc1);
ply := array( rc1[array(0,1)],
rc1[array(2,1)],
rc1[array(2,3)],
rc1[array(0,3)],
rc1[array(0,1)]
);
dc.draw("polyline",ply) ;
//dc.brush.color := 0xEEE8AA;
dc.brush.color := fsizebtncolor;
rc1 := v.fsizerect;
rc1[0]+=1;
rc1[1]+=1;
rc1[2]-=1;
rc1[3]-=1;
dc.fillrect(rc1);
ply := array( rc1[array(0,1)],
rc1[array(2,1)],
rc1[array(2,3)],
rc1[array(0,3)],
rc1[array(0,1)]
);
dc.draw("polyline",ply) ;
end
dc.brush.color := cl;
dc.pen.color := bcl;
end
function Recycling();override;
begin
inherited;
//if FDRageimglist then _wapi.ImageList_Destroy(FDRageimglist);
end
property autosize read fautosize write setautosize;
property arrange read getarrange write setarrange;
property dragbtncolor:color read fdragbtncolor write fdragbtncolor;
property sizebtncolor:color read fsizebtncolor write fsizebtncolor;
private
fautosize ;
fdragbtncolor;
fsizebtncolor;
function arange2a(s);
begin
ss := str2array(s,";");
rs := array();
for i,v in ss do
begin
if trim(v) then
begin
str2array(v,",");
end
end
end
function getarrange();
begin
ar := "";
ctls := controls;
for i,vi in fcoolbands.data2 do
begin
for j,v in vi do
begin
ar+= inttostr(ctls.indexof(v.fctl));
ar+=",";
end
ar[length(ar)] := ";";
end
if ar then ar[length(ar):] := "";
return ar;
end
function setarrange(ar);
begin
ctls := controls;
ct := ctls.count-1;
if ct<0 then return ;
idxs := 0->(ct);
fcoolbands_ := new tnumindexarray();
for i,v in str2array(ar,";") do
begin
if v then
begin
line := new tnumindexarray();
for j,vj in str2array(v,",") do
begin
idx := strtointdef(vj,-1);
if idx>=0 then
begin
vidx := idxs[idx];
if vidx>=0 then
begin
reindex(idxs,array(idx:nil));
line.Push(new tcoolband(ctls[vidx]));
end
end
end
if line.length() then
begin
fcoolbands_.Push(line);
end
end
end
for i,v in idxs do
begin
line := new tnumindexarray();
line.Push(new tcoolband(ctls[vidx]));
fcoolbands_.Push(line);
end
fcoolbands := fcoolbands_;
if HandleAllocated() then
begin
doControlALign();
end
end
function setautosize(v);
begin
nv := v?true:false;
if nv<>fautosize then
begin
fautosize := v;
if nv then
begin
doControlALign();
end
end
end
function EnabledChild(f);
begin
fcoolbands.EnabledChild(f);
end
function cimgst();
begin
FDRageimglist := new TCustomImageList(self);
FDRageimglist.Width := 24;
FDRageimglist.Height := 24;
bmp := new TcustomBitmap();
bmp.readvcon(HexFormatStrToTsl(getmovebmp()));
FDRageimglist.addbmp(bmp);
bmp.readvcon(HexFormatStrToTsl(getsizebmp()));
FDRageimglist.addbmp(bmp);
end
fdragenode;
fsizenode;
fcoolbands;
frowheight;
fbtnwidth;
FIs_Draging;//
FWill_Drag;//
FDRageimglist;//
end
implementation
type tcoolband = class
function create(ctl);
begin
fctl := ctl;
end
function destroy();
begin
end
function enabled(f);
begin
if not f then
begin
if fenable<>nil then return ;
fenable := fctl.Enabled;
fctl.Enabled := false;
end else
begin
fctl.Enabled := fenable;
fenable := nil;
end
end
function operator[](idx);
begin
try
return invoke(fctl,idx);
except
return 0;
end
end
fctl;
fdragrect;
fsizerect;
fctlrect;
private
fenable;
end
type tcoolbarlines = class
function create();
begin
flines := new tnumindexarray();
end
function appendrow(cb); //追加一行
begin
line := new tnumindexarray();
line.Push(cb);
flines.Push(line);
end
function unshiftrow(cb); //在前面
begin
line := new tnumindexarray();
flines.unshift(line);
end
function deleteitem(it,f); //删除一项
begin
for i,v in flines.data do
begin
for j ,vj in v.data do
begin
if vj = it then
begin
v.splice(j,1);
if v.length()<1 then
begin
flines.splice(i,1);//删除
end
end
end
end
end
function moveitemto(it,nit,f);//移动到坐标
begin
if it=nit then return 0;
{id1 := -1;
id2 := -1;
for i ,v in data do
begin
if v= it then
begin
id1 := i;
if id2>-1 then break;
end
if v=nit then
begin
id2 := i;
if id1>-1 then break;
end
end
//it 为移动的
//nid 为锚点
case f of
0,1: //前
begin
if (id2-id1)=1 then return 0;
end
2: //前一行
begin
end
3: //后
begin
if (id1-id2)=1 then return 0;
end
4: //后一行
begin
end
end }
deleteitem(it);//删掉
case f of
0,1: //前
begin
ifg := 0;
end
2: //前一行
begin
line := new tnumindexarray();
line.push(it);
flines.unshift(line);
return 1;
end
3: //后
begin
ifg :=2;
end
4: //后一行
begin
line := new tnumindexarray();
line.push(it);
flines.Push(line);
return 1;
end
end
for i,v in flines.data do
begin
for j ,vj in v.data do
begin
if vj = nit then
begin
if ifg then //后面
begin
v.splice(j+1,0,it);
end else
begin
v.splice(j,0,it);
end
end
end
end
return true;
end
function getrowheights(); //总高度
begin
r := array(25);
for i,v in flines.data do
begin
h := 0;
for j,vj in v.data do
begin
h := max(h,vj["height"]);
end
r[i] := h;
end
return r;
end
function EnabledChild(f);
begin
for i,v in flines.data do
begin
for j,vj in v.data do
begin
vj.enabled(f);
end
end
end
function getnodebyxy(x,y);
begin
rs := getrowheights();
b := 0;
bdr := 3;
rl := length(rs)-1;
for i,v in rs do
begin
if v<1 then continue;
if y>=b and y<=b+v then //确定行
begin
for j,bsi in flines[i].data do
begin
rc := bsi.fctlrect;
rt := -1;
if (x>=(rc[0])) and ( x<=(rc[0]+rc[2])) and
(y>=(rc[1]+bdr)) and ( y<=(rc[1]+rc[3]-bdr)) then
begin
rt := 0;
end
if x<(rc[0]+bdr) then
begin
rt := 1;
end
if i=0 then
begin
if y<(rc[1]+bdr) then
begin
rt := 2;
end
end
if i=rl then
begin
if y>(rc[1]+rc[3]-bdr) then
begin
rt := 4;
end
end
if rt>-1 then return array(bsi,rt,i,j);
end
return array(bsi,3,i,j);
end
b+=v;
end
ri := length(rs)-1;
return array((flines[ri])[0],4,ri,0);
end
property data2 read getdata2;
property data read getdata;
property lines read flines;
private
function getdata();
begin
r := array();
k := 0;
for i,v in flines.data do
begin
for j,vj in v.data do
begin
r[k] := vj;
k++;
end
end
return r;
end
function getdata2();
begin
r := array();
k := 0;
for i,v in flines.data do
begin
for j,vj in v.data do
begin
r[i,j] := vj;
end
end
return r;
end
flines;
end
function getmovebmp();
begin
return "0502000000060400000074797065000203000000696D670006040000006461746
10002E801000089504E470D0A1A0A0000000D4948445200000018000000180806
000000E0773DF8000000017352474200AECE1CE90000000467414D410000B18F0
BFC6105000000097048597300000EC300000EC301C76FA8640000017D49444154
484BB594BF2F044114C7FD1DFE06FF8446F41285CE3FA0D048682FA1500912AD6
8509C50A1D128885CA1398DECE5E2E2ECB27B2EB72C479E7C9F9D313BB3676692
BB4FF2B29BF9F13EB3F366678C468C97E0F4F68DC30767C1D6D92B4D2CB538F0E
E8A93404DEE2BB10AB6CFBB4672112E12AB6061F785932DEEC585C478A2CF8655
9066DFB2B042707D9FD1453DE33E1BCE4506AAC01543803DAF54138A7BE6EA663
7421694B17290F057E91404EA69F159A53A4FFF4FA4403D2D28A8CE65FA4ED38D
36CD349F683DEAE4AD7F88AFD3252CA8DEA4B2538FF99D671E88C4E3774D8EC9E
0911A519FE636A3D239885AF0C1F358707835588095015DF0107F958E1771524B
799EDCA2E5FD4476624F5103442F3F8A83B6488C53B758FD010B455E3DEEC841F
5D667DE6A47DD62353928088038A661D7EF984EADB58DE4C010FC87586510F6F3
163B5641D95501D03694ABA2ECB2AB1CFD1E88A15C7623BFAE0112E9C92176C1B
9C8AAC465E50267014061F5CBCC8697C01FA21F97353FCB2FCC13D10000000049
454E44AE42608200";
end
function getsizebmp();
begin
return "0502000000060400000074797065000203000000696D670006040000006461746
100020E01000089504E470D0A1A0A0000000D4948445200000018000000180806
000000E0773DF8000000017352474200AECE1CE90000000467414D410000B18F0
BFC6105000000097048597300000EC300000EC301C76FA864000000A349444154
484BED93BB0E84300C04F3E7499B3675DA7C674E8B6CB45C1E46C09D0462240A6
CD603065CFD31AFC0E4E1821042F5DECB598BD5074301C2CEB9E5E80DB1FA4A57
808086638C526D41CF9234021E9E5292EA185C33936C04FCD83967A9DAE0DA916
415F0F0528A54F7834C4FB20A78356705B85965B322961C5D110F07FF7DC90A4B
2EFF4C15EB47E2FEF75A98A10020380B5B7D30155CC12B30B9BBA0D60F44173C9
EBDFC87F10000000049454E44AE42608200";
end
initialization
end.