diff --git a/src/gx/gh_flexlay.pas b/src/gx/gh_flexlay.pas
index 3eed2e410e14dd7b1f8c94026aabc540518be32c..9692f0d1353f0319fb407204f7feb37dcf8338de 100644 (file)
--- a/src/gx/gh_flexlay.pas
+++ b/src/gx/gh_flexlay.pas
function lineStart (): Boolean; inline;
function canWrap (): Boolean; inline;
function inGroup (): Boolean; inline;
- function expand (): Boolean; inline;
function firstInLine (): Boolean; inline;
+ function getExpand (): Boolean; inline;
+ procedure setExpand (v: Boolean); inline;
+
+ function alignLeft (): Boolean; inline;
+ function alignTop (): Boolean; inline;
+ function alignRight (): Boolean; inline;
+ function alignBottom (): Boolean; inline;
+ function alignCenter (): Boolean; inline;
+
public
property didWrap: Boolean read getDidWrap write setDidWrap;
+ property expand: Boolean read getExpand write setExpand;
end;
PLayGroup = ^TLayGroup;
// this also sets `tempFlex`
procedure calcMaxSizeInternal (cidx: LayControlIdx);
- procedure fixLine (me: PLayControl; i0, i1: LayControlIdx; cury: Integer; var spaceLeft: Single; var flexTotal: Integer; var flexBoxCount: Integer);
+ procedure fixLine (me: PLayControl; i0, i1: LayControlIdx; var cury: Integer; var spaceLeft: Single);
// do box layouting; call `layBox()` recursively if necessary
procedure layBox (boxidx: LayControlIdx);
@@ -236,12 +245,20 @@ function TFlexLayouterBase.TLayControl.horizBox (): Boolean; inline; begin resul
function TFlexLayouterBase.TLayControl.lineStart (): Boolean; inline; begin result := ((flags and FlagLineStart) <> 0); end;
function TFlexLayouterBase.TLayControl.canWrap (): Boolean; inline; begin result := ((flags and FlagLineCanWrap) <> 0); end;
function TFlexLayouterBase.TLayControl.inGroup (): Boolean; inline; begin result := ((flags and FlagInGroup) <> 0); end;
-function TFlexLayouterBase.TLayControl.expand (): Boolean; inline; begin result := ((flags and FlagExpand) <> 0); end;
function TFlexLayouterBase.TLayControl.firstInLine (): Boolean; inline; begin result := ((flags and FlagLineFirst) <> 0); end;
function TFlexLayouterBase.TLayControl.getDidWrap (): Boolean; inline; begin result := ((flags and FlagLineDidWrap) <> 0); end;
procedure TFlexLayouterBase.TLayControl.setDidWrap (v: Boolean); inline; begin if (v) then flags := flags or FlagLineDidWrap else flags := flags and (not FlagLineDidWrap); end;
+function TFlexLayouterBase.TLayControl.getExpand (): Boolean; inline; begin result := ((flags and FlagExpand) <> 0); end;
+procedure TFlexLayouterBase.TLayControl.setExpand (v: Boolean); inline; begin if (v) then flags := flags or FlagExpand else flags := flags and (not FlagExpand); end;
+
+function TFlexLayouterBase.TLayControl.alignLeft (): Boolean; inline; begin result := (aligndir < 0); end;
+function TFlexLayouterBase.TLayControl.alignTop (): Boolean; inline; begin result := (aligndir < 0); end;
+function TFlexLayouterBase.TLayControl.alignRight (): Boolean; inline; begin result := (aligndir > 0); end;
+function TFlexLayouterBase.TLayControl.alignBottom (): Boolean; inline; begin result := (aligndir > 0); end;
+function TFlexLayouterBase.TLayControl.alignCenter (): Boolean; inline; begin result := (aligndir = 0); end;
+
// ////////////////////////////////////////////////////////////////////////// //
constructor TFlexLayouterBase.TChildrenEnumerator.Create (constref actls: TLayCtlArray; acur: Integer);
lc, c: PLayControl;
msz: TLaySize;
negw, negh: Boolean;
+ zerow: Boolean;
curwdt, curhgt, totalhgt: Integer;
doWrap: Boolean;
begin
lc := @ctlist[cidx];
msz := lc.ctl.getMaxSize;
- negw := (lc.startsize.w <= 0);
- negh := (lc.startsize.h <= 0);
+ negw := (lc.startsize.w < 0);
+ negh := (lc.startsize.h < 0);
+ zerow := (lc.startsize.w = 0);
lc.tempFlex := lc.ctl.getFlex;
// horizontal boxes
if (negw) then lc.tempFlex := 0; // size is negative: don't expand
curwdt := lc.margins.horiz;
- curhgt := lc.margins.vert;
- totalhgt := 0;
+ curhgt := 0;
+ totalhgt := lc.margins.vert;
for c in forChildren(cidx) do
begin
// new line?
doWrap := (not c.firstInLine) and (c.lineStart);
// need to wrap?
- if (not doWrap) and (lc.canWrap) and (c.canWrap) and (msz.w > 0) and (curwdt+c.startsize.w > lc.startsize.w) then doWrap := true;
+ if (not doWrap) and zerow and (lc.canWrap) and (c.canWrap) and (msz.w > 0) and (curwdt+c.startsize.w > lc.startsize.w) then doWrap := true;
if (doWrap) then
begin
totalhgt += curhgt;
curwdt += c.startsize.w;
if (curhgt < c.startsize.h) then curhgt := c.startsize.h;
end;
+ //writeln('00: ', cidx, ': totalhgt=', totalhgt);
totalhgt += curhgt;
+ //writeln('01: ', cidx, ': totalhgt=', totalhgt);
if (lc.startsize.w < curwdt) then lc.startsize.w := curwdt;
if (lc.startsize.h < totalhgt) then lc.startsize.h := totalhgt;
end
grp: PLayGroup;
maxsz: Integer;
cidx: LayControlIdx;
+ ct: PLayControl;
mr: TLayMargins;
begin
// reset all 'laywrap' flags for controls, set initial 'startsize'
ctlist[f].startsize := ctlist[f].ctl.getDefSize;
mr := ctlist[f].ctl.getMargins;
ctlist[f].margins := mr;
- ctlist[f].startsize.w += mr.horiz;
- ctlist[f].startsize.h += mr.vert;
+ //ctlist[f].startsize.w += mr.horiz;
+ //ctlist[f].startsize.h += mr.vert;
end;
// setup sizes
calcMaxSizeInternal(0); // this also sets `tempFlex`
+ //writeln('=== calculated max size (0) ==='); dump();
// find max size for group, adjust 'startsize' controls to group max size
needRecalcMaxSize := false;
for gtype := 0 to 1 do
for c := 0 to High(grp.ctls) do
begin
cidx := grp.ctls[c];
- if (maxsz < ctlist[cidx].startsize[gtype]) then maxsz := ctlist[cidx].startsize[gtype];
+ ct := @ctlist[cidx];
+ if (maxsz < ct.startsize[gtype]) then maxsz := ct.startsize[gtype];
end;
for c := 0 to High(grp.ctls) do
begin
cidx := grp.ctls[c];
- if (maxsz <> ctlist[cidx].startsize[gtype]) then
+ ct := @ctlist[cidx];
+ if (maxsz <> ct.startsize[gtype]) then
begin
needRecalcMaxSize := true;
- ctlist[cidx].startsize[gtype] := maxsz;
+ ct.startsize[gtype] := maxsz;
end;
end;
end;
for f := 0 to High(ctlist) do ctlist[f].desiredsize := ctlist[f].startsize;
// set flags
firstTime := true;
- //writeln('=== calculated max size ===');
- //dump();
+ //writeln('=== calculated max size (final) ==='); dump();
end;
-procedure TFlexLayouterBase.fixLine (me: PLayControl; i0, i1: LayControlIdx; cury: Integer; var spaceLeft: Single; var flexTotal: Integer; var flexBoxCount: Integer);
+procedure TFlexLayouterBase.fixLine (me: PLayControl; i0, i1: LayControlIdx; var cury: Integer; var spaceLeft: Single);
var
+ flexTotal: Integer = 0; // total sum of flex fields
+ flexBoxCount: Integer = 0; // number of boxes
curx: Integer;
lc: PLayControl;
osz: TLaySize;
begin
curx := me.margins.left;
sti0 := i0;
- // calc minimal line height
+ // calc minimal line height, count flexboxes
lineh := 0;
while (i0 <> i1) do
begin
lc := @ctlist[i0];
lineh := nmax(lineh, lc.startsize.h);
+ if (lc.tempFlex > 0) then begin flexTotal += lc.tempFlex; flexBoxCount += 1; end;
i0 := lc.nextSibling;
end;
// distribute space, expand/align
end;
// expand or align
if (lc.expand) then lc.desiredsize.h := nmin(lc.maxsize.h, lineh) // expand
- else if (lc.aligndir > 0) then lc.desiredpos.y := cury+(lineh-lc.desiredsize.h) // bottom align
- else if (lc.aligndir = 0) then lc.desiredpos.y := cury+(lineh-lc.desiredsize.h) div 2; // center
+ else if (lc.alignBottom) then lc.desiredpos.y := cury+(lineh-lc.desiredsize.h) // bottom align
+ else if (lc.alignCenter) then lc.desiredpos.y := cury+(lineh-lc.desiredsize.h) div 2; // center
if (not osz.equals(lc.desiredsize)) then
begin
if (lc.inGroup) then groupElementChanged := true;
flexTotal := 0;
flexBoxCount := 0;
spaceLeft := me.desiredsize.w-me.margins.horiz;
+ cury += lineh;
end;
flexBoxCount: Integer; // number of boxes
spaceLeft: Single;
cury: Integer;
- maxwdt, maxhgt: Integer;
+ maxwdt: Integer;
lineStartIdx: LayControlIdx;
lc: PLayControl;
doWrap: Boolean;
begin
// horizontal boxes
cury := me.margins.top;
- maxhgt := 0;
- fixLine(me, -1, -1, cury, spaceLeft, flexTotal, flexBoxCount); //HACK!
+ fixLine(me, -1, -1, cury, spaceLeft); //HACK!
lineStartIdx := me.firstChild;
-
for lc in forChildren(boxidx) do
begin
// new line?
if (doWrap) then
begin
// new line, fix this one
- if (not lc.didWrap) then
- begin
- wrappingChanged := true;
- lc.didWrap := true;
- end;
- fixLine(me, lineStartIdx, lc.myidx, cury, spaceLeft, flexTotal, flexBoxCount);
- cury += maxhgt;
+ if (not lc.didWrap) then begin wrappingChanged := true; lc.didWrap := true; end;
+ fixLine(me, lineStartIdx, lc.myidx, cury, spaceLeft);
lineStartIdx := lc.myidx;
end
else
begin
- if (lc.didWrap) then
- begin
- wrappingChanged := true;
- lc.didWrap := false;
- end;
+ if (lc.didWrap) then begin wrappingChanged := true; lc.didWrap := false; end;
end;
spaceLeft -= lc.desiredsize.w;
- if (maxhgt < lc.desiredsize.h) then maxhgt := lc.desiredsize.h;
- if (lc.tempFlex > 0) then
- begin
- flexTotal += lc.tempFlex;
- flexBoxCount += 1;
- end;
+ //if (maxhgt < lc.desiredsize.h) then maxhgt := lc.desiredsize.h;
+ //if (lc.tempFlex > 0) then begin flexTotal += lc.tempFlex; flexBoxCount += 1; end;
end;
// fix last line
- fixLine(me, lineStartIdx, -1, cury, spaceLeft, flexTotal, flexBoxCount);
+ fixLine(me, lineStartIdx, -1, cury, spaceLeft);
end
else
begin
begin
spaceLeft -= lc.desiredsize.h;
if (maxwdt < lc.desiredsize.w) then maxwdt := lc.desiredsize.w;
- if (lc.tempFlex > 0) then
- begin
- flexTotal += lc.tempFlex;
- flexBoxCount += 1;
- end;
+ if (lc.tempFlex > 0) then begin flexTotal += lc.tempFlex; flexBoxCount += 1; end;
end;
// distribute space
end;
// expand or align
if (lc.expand) then lc.desiredsize.w := nmin(lc.maxsize.w, me.desiredsize.w-me.margins.vert) // expand
- else if (lc.aligndir > 0) then lc.desiredpos.x := me.desiredsize.w-me.margins.right-lc.desiredsize.w // right align
- else if (lc.aligndir = 0) then lc.desiredpos.x := (me.desiredsize.w-me.margins.horiz-lc.desiredsize.w) div 2; // center
+ else if (lc.alignRight) then lc.desiredpos.x := me.desiredsize.w-me.margins.right-lc.desiredsize.w // right align
+ else if (lc.alignCenter) then lc.desiredpos.x := (me.desiredsize.w-lc.desiredsize.w) div 2; // center
if (not osz.equals(lc.desiredsize)) then
begin
if (lc.inGroup) then groupElementChanged := true;
grp: PLayGroup;
f, c: Integer;
cidx: LayControlIdx;
+ ct: PLayControl;
begin
while true do
begin
for c := 0 to High(grp.ctls) do
begin
cidx := grp.ctls[c];
- if (maxsz < ctlist[cidx].startsize[gtype]) then maxsz := ctlist[cidx].startsize[gtype];
+ ct := @ctlist[cidx];
+ ct.expand := false; // don't expand grouped controls anymore
+ if (maxsz < ct.startsize[gtype]) then maxsz := ct.startsize[gtype];
end;
for c := 0 to High(grp.ctls) do
begin
cidx := grp.ctls[c];
- ctlist[cidx].startsize[gtype] := maxsz;
- ctlist[cidx].desiredsize[gtype] := maxsz;
- ctlist[cidx].tempFlex := 0; // don't change control size anymore
+ ct := @ctlist[cidx];
+ ct.startsize[gtype] := maxsz;
+ ct.desiredsize[gtype] := maxsz;
+ ct.tempFlex := 0; // don't change control size anymore
end;
end;
end;
begin
for f := 0 to High(ctlist) do
begin
+ ct := @ctlist[f];
+ if (ct.inGroup) then
+ begin
+ ct.expand := false; // don't expand grouped controls anymore
+ ct.tempFlex := 0; // don't change control size anymore
+ end;
for c := 0 to 1 do
begin
- if (ctlist[f].maxsize[c] <= 0) then continue;
- if (ctlist[f].desiredsize[c] > ctlist[f].maxsize[c]) then
+ if (ct.maxsize[c] < 0) then continue;
+ if (ct.desiredsize[c] > ct.maxsize[c]) then
begin
//writeln('ctl #', f, '; dimension #', c, ': desired=', ctlist[f].desiredsize[c], '; max=', ctlist[f].maxsize[c]);
- ctlist[f].startsize[c] := ctlist[f].maxsize[c];
- ctlist[f].desiredsize[c] := ctlist[f].maxsize[c];
- ctlist[f].tempFlex := 0; // don't change control size anymore
+ ct.startsize[c] := ct.maxsize[c];
+ ct.desiredsize[c] := ct.maxsize[c];
+ ct.tempFlex := 0; // don't change control size anymore
secondAgain := true;
end;
end;