tslediter/funcext/tvclib/t_children_sizer.tsf

284 lines
8.4 KiB
Plaintext

type t_children_sizer = class()
{**
@explan(说明) 子控件布局器 %%
@param(layout)(bool) 是否布局 %%
@param(controlsperline)(integer) 每行控件数 %%
@param(horizontalspacing)(integer) 水平间距 %%
@param(verticalspacing)(integer) 垂直间距 %%
@param(leftrightspacing)(integer) 左右间距 %%
@param(topbottomspacing)(integer) 上下间距 %%
**}
//TControlChildrenLayout
//static const cclNone =0;
//static const cclLeftToRightThenTopToBottom = 1; // if BiDiMode <> bdLeftToRight then it becomes RightToLeft
//static const cclTopToBottomThenLeftToRight = 2;
function create(aowner);
begin
fowner := aowner;
fcontrolsperline := 1;
flayout := 0;
fhorizontalspacing := 10;
fverticalspacing := 10;
ftopbottomspacing := 5;
fleftrightspacing := 20;
fautosizing := 0;
end
function AdjustSize(); //调整
begin
if flayout=0 then return ;
if fautosizing then return ;
fautosizing := true;
if not fowner then return ;
faownercls := fowner.ClientRect;
dolayoutctls(w,h);
if fowner.autosize then
begin
bds := fowner.BoundsRect;
cls := faownercls;
dw := (bds[2]-bds[0])-(cls[2]-cls[0]);
dh := (bds[3]-bds[1])-(cls[3]-cls[1]);
bds[2] := bds[0]+w+dw;
bds[3] := bds[1]+h+dh;
fowner.BoundsRect := bds;
end
fautosizing := false;
end
function getsizerinfo();
begin
r := array();
r["layout"] := flayout;
r["controlsperline"] := fcontrolsperline;
r["horizontalspacing"] := fhorizontalspacing;
r["verticalspacing"] := fverticalspacing;
r["topbottomspacing"] := ftopbottomspacing;
r["leftrightspacing"] := fleftrightspacing;
return r;
end
function setsizerinfo(v);
begin
if not(ifarray(v) and v) then return ;
flg := false;
for i,vi in v do
begin
case i of
"layout" :
begin
if vi<>flayout and(vi=0 or vi=1 or vi=2) then
begin
flayout := vi;
if vi then flg := true;
end
end
"controlsperline":
begin
if vi<>fcontrolsperline and vi>0 then
begin
fcontrolsperline := vi;
flg := true;
end
end
"horizontalspacing":
begin
if vi<>fhorizontalspacing and vi>0 then
begin
fhorizontalspacing := vi;
flg := true;
end
end
"verticalspacing":
begin
if vi<>fverticalspacing and vi>0 then
begin
fverticalspacing := vi;
flg := true;
end
end
"topbottomspacing":
begin
if vi<>ftopbottomspacing and vi>0 then
begin
ftopbottomspacing := vi;
flg := true;
end
end
"leftrightspacing":
begin
if vi<>fleftrightspacing and vi>0 then
begin
fleftrightspacing := vi;
flg := true;
end
end
end;
end
if flg then
begin
AdjustSize();
end
end
property layout read flayout write setlayout;
property controlsperline read fcontrolsperline write setcontrolsperline;
property horizontalspacing read fhorizontalspacing write sethorizontalspacing;
property verticalspacing read fverticalspacing write setverticalspacing;
property leftrightspacing read fleftrightspacing write setleftrightspacing;
property topbottomspacing read ftopbottomspacing write settopbottomspacing;
property autosizing read fautosizing;
private
function getwndclass();
begin
return class(TWinControl);
end
function dolayoutctls(w,h);
begin
if not fowner then return ;
ctls := fowner.Controls;
r := array();
ridx := 0;
cidx := 0;
ccount := 0;
for i :=0 to fowner.ControlCount-1 do
begin
ctl := ctls[i];
if not ctl then continue;
if not ctl.Visible then continue;
if (ctl is getwndclass()) and ctl.WsPopUp then continue;
if cidx>=fcontrolsperline then
begin
ccount := fcontrolsperline;
cidx := 0;
ridx++;
end
ctl.GetPreferredSize(wi,hi);
if flayout=1 then
r[ridx,cidx] := array(ctl,0,0,wi,hi);
else r[cidx,ridx] := array(ctl,0,0,wi,hi);
cidx++;
end
ccount := mcols(r);
ridx := mrows(r);
//ccount := max(ccount,cidx);
wsz := zeros(ccount);
//hsz := zeros(ridx+1);
hsz := zeros(ridx);
for i := 0 to length(r)-1 do
begin
for j := 0 to length(r[i])-1 do
//for j := 0 to ccount-1 do
begin
hsz[i] := max(hsz[i],r[i,j,4]);
wsz[j] := max(wsz[j],r[i,j,3]);
end
end
py := ftopbottomspacing+faownercls[1];
lr := length(r)-1;
for i := 0 to lr do
begin
px := fleftrightspacing+faownercls[0];
for j := 0 to ccount-1 do
begin
vij := r[i,j];
if not vij then continue;
vij[1] := px;
vij[2] := py;
vij[3] := px+wsz[j];
vij[4] := py+hsz[i];
r[i,j] := vij;
px+=wsz[j];
if j<ccount-1 then
px+=fverticalspacing;
end
py+=hsz[i];
if i<lr then py+=horizontalspacing;
w := max(w,px);
end
w +=fleftrightspacing;
py += ftopbottomspacing;
h := py;
for i := 0 to length(r)-1 do
begin
for j := 0 to ccount-1 do
begin
vi := r[i,j];
if not vi then continue;
vi[0].BoundsRect := vi[1:4];
end
end
w-=faownercls[0];
h-=faownercls[1];
return ;
end
function setleftrightspacing(v);
begin
nv := integer(v);
if nv<>fleftrightspacing then
begin
fleftrightspacing := nv;
dolayout();
end
end
function settopbottomspacing(v);
begin
nv := integer(v);
if nv<>ftopbottomspacing then
begin
ftopbottomspacing := nv;
dolayout();
end
end
function sethorizontalspacing(v);
begin
nv := integer(v);
if nv<>fhorizontalspacing then
begin
fhorizontalspacing := nv;
dolayout();
end
end
function setverticalspacing(v);
begin
nv := integer(v);
if nv<>fverticalspacing then
begin
fverticalspacing := nv;
dolayout();
end
end
function setlayout(v);
begin
if v<>flayout and v in array(0,1,2) then
begin
flayout := v;
if v>0 then
begin
dolayout();
end
end
end
function setcontrolsperline(v);
begin
nv := integer(v);
if nv>0 and fcontrolsperline<>nv then
begin
fcontrolsperline := nv;
dolayout();
end
end
function dolayout();
begin
AdjustSize();
end
private
[weakref] fowner;
fautosizing;
flayout;
fcontrolsperline;
fhorizontalspacing;
fverticalspacing;
fleftrightspacing;
ftopbottomspacing;
faownercls;
end