I've put the grid to one side and have been tackling the box-fitting issue more directly. After a few days and a bit of scribbling, the problem of ordering has (contrary to my earlier assumption) shown itself to be a Hard Problem.
I've attempted a basic flex-box (1D) in this code, and within that scope I think I'm on the right track. Over the next few days/week I'll try to work this into the bidirectional grid and/or add support for a proper tree of frames.
set display mode desktop width(), desktop height(), 32, 1
sync on : sync rate 30 : sync
global scrW, scrH
scrW = screen width()
scrH = screen height()
// /////////////////////////////////////
// /// DBP FLEXBOX 13Jan14 /// TomJK ///
// /////////////////////////////////////
// notes
// - should seperate concept of container into inner (content, scrollable, can fit size to content) and outer (frame) parts..
#Constant EPSILON = 0.01
#constant DEBUG_EVALFRAMEPASSEND 0 ` 1 shows frame details for each pass.
#constant DEBUG_FRAMESUMMARY 1 ` 1 shows list of frame details after computation.
#constant DEBUG_SHOWSIMPLEFRAME 1 ` 0 shows wrapped text in each frame, 1 doesn't and is much faster.
#constant UNIT_NONE 0 ` unset field
#constant UNIT_PX 1 ` px absolute pixel
#constant UNIT_PERC 2 ` pc relative percent
#constant UNIT_FR 3 ` fr relative fraction (of space remaining)
type t_measurement qu as float, un endtype // QUantity [of] UNit.
type t_frameStyle
// user-set style.
width as t_measurement, minWidth as t_measurement, maxWidth as t_measurement
// used properties. (for example, [width]fr capped at [max].px, treat as px-sized rather than fr-sized, but still keep reference in user-set style to desired sizing.)
usedWidth as t_measurement
// double-buffered properties. these buffer changes to values that should remain constant during a pass.
compWidth2 as t_measurement, compFrSpace2 as float, compFrDenom2 as float
// computed and render properties.
// compWidth, compFrSpace, compFrDenom, compMinWidth and rendWidth [currently unused] are all pixel measurements.
// compValid indicates if value should be treated as final [deprecated].
// compCanShrink/Grow [deprecated] determine if should invalidate frame when space runs out. CompMinWidth is minWidth.qu if minWidth.un = UNIT_PX, otherwise initialised to 0 then set at evaluation time.
compWidth as float, compFrSpace as float, compFrDenom as float
compValid, compCanShrink, compCanGrow, compMinWidth as float, compMaxWidth as float, rendWidth
endtype
global nullMeasurement as t_measurement // blank placeholder for some functions.
// font and string for wrapped text shown in frame.
f = a2createfont("calibri", 16, a2size_char(), 0)
test$ = "The quick brown fox jumps over the lazy dog. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris odio orci, porttitor vel elementum id, vulputate nec nunc. Curabitur ac orci vel erat accumsan volutpat sed sit amet dolor."
#constant numFrames 16
dim frame(numFrames) as t_frameStyle
SetFrameStyle_Width(0, "512px", "", "") // 0 is stand-in for parent container for now.
// -- FRAME SETUP --
// Set 1. [works fine now] [numFrames = any]
remstart
pc# = 100.0 / (numFrames/2)
for n = 1 to numFrames step 2
setFrameStyle_Width(n, "4px", "", "")
next n
for n = 2 to numFrames step 2
SetFrameStyle_Width(n, str$(pc#) + "%", str$(n*4)+"px", str$(n*16)+"px")
next n
remend
// Set 2. [works fine] [numFrames = 10]
remstart
setFrameStyle_Width(1, "20px", "", "")
setFrameStyle_Width(2, "80fr", "", "")
setFrameStyle_Width(3, "30px", "", "")
setFrameStyle_Width(4, "10%", "", "")
setFrameStyle_Width(5, "50px", "", "")
setFrameStyle_Width(6, "60px", "", "")
setFrameStyle_Width(7, "20%", "", "")
setFrameStyle_Width(8, "90px", "", "")
setFrameStyle_Width(9, "80fr", "", "")
setFrameStyle_Width(10, "30%", "", "")
remend
// Set 3. [works fine] [numFrames = 5]
remstart
SetFrameStyle_Width(1, "32px", "", "" )
SetFrameStyle_Width(2, "2fr", "100px", "" )
SetFrameStyle_Width(3, "40%", "", "200px")
SetFrameStyle_Width(4, "32px", "", "" )
SetFrameStyle_Width(5, "1fr", "100px", "" )
remend
// Set 4. [works?] [numFrames = 2]
remstart
setFrameStyle_Width(1, "150px", "70px", "150px")
setFrameStyle_Width(2, "50%", "80px", "120px")
remend
// Set 5. [?] [numFrames = 5]
remstart
setFrameStyle_Width(1, "250px", "", "")
setFrameStyle_Width(2, "25%", "4px", "96px") `2
setFrameStyle_Width(3, "25%", "28px", "48px") `3
setFrameStyle_Width(4, "45%", "200px", "228px") `4
setFrameStyle_Width(5, "250px", "", "")
remend
// Set 6 (Random set). [seems to work] [numFrames = any]
rem start
pcLeft# = 100.0
sz# = scrW*0.15 / numFrames
for n = 1 to numFrames
un = 1 + rnd(2)
select un
case UNIT_PX
qu# = 5 + rnd(sz#)
qu$ = str$(qu#) + "px"
endcase
case UNIT_PERC
qu# = 2 + rnd(pcLeft#-2) * 0.25
pcLeft# = pcLeft# - qu#
qu$ = str$(qu#) + "%"
endcase
case UNIT_FR
qu# = rnd(100) * 0.1
qu$ = str$(qu#) + "fr"
endcase
endselect
un = 1` + rnd(1)
select un
case UNIT_PX
minqu# = rnd(sz#*0.66)
minqu$ = str$(minqu#) + "px"
endcase
case UNIT_PERC
minqu# = rnd(50)
minqu$ = str$(minqu#) + "%"
endcase
endselect
un = 1` + rnd(1)
select un
case UNIT_PX
maxqu# = rnd(sz#*1.33)
maxqu$ = str$(maxqu#) + "px"
endcase
case UNIT_PERC
maxqu# = 49+rnd(50)
maxqu$ = str$(maxqu#) + "%"
endcase
endselect
setFrameStyle_Width(n, qu$, minqu$, maxqu$)
quPx# = CalcSize(frame(n).width.qu, frame(n).width.un, frame(0).width.qu, frame(0).width.un, 0, 0, UNIT_PX)
minquPx# = CalcSize(frame(n).minwidth.qu, frame(n).minwidth.un, frame(0).width.qu, frame(0).width.un, 0, 0, UNIT_PX)
maxquPx# = CalcSize(frame(n).maxwidth.qu, frame(n).maxwidth.un, frame(0).width.qu, frame(0).width.un, 0, 0, UNIT_PX)
if minquPx# > quPx# then minqu$ = ""
if maxquPx# < quPx# then maxqu$ = ""
setFrameStyle_Width(n, qu$, minqu$, maxqu$)
next n
rem end
// // MAIN LOOP. //
do
// update input.
omx = mx
mx = mousex()
// set container width to track mouse
SetFrameStyle_Width(0, str$(mx) + "px", "", "")
// [ set 5 -> frame 5: press up/down to resize ]
if numFrames >= 5 : if frame(5).width.un = UNIT_PX and frame(5).width.qu = 250+q#
oq# = q#
q# = q# + (upkey()-downkey())*0.5
setFrameStyle_Width(5, str$(250+q#)+"px", "", "")
endif : endif
// update and redraw if change made.
UpdateFrames = (omx <> mx or oq# <> q#)
if UpdateFrames
cls 0
// reset topmost container to knowable defaults.
frame(0).usedWidth = frame(0).width
frame(0).compWidth = CalcSize(frame(0).usedWidth.qu, frame(0).usedWidth.un, 0, 0, 0, 0, UNIT_PX)
// evaluate tree of frames.
ts = hitimer(10000)
EvaluateFrameWidth(0, -1)
te = hitimer(10000)
ev_t = te - ts
// Draw.
ts = hitimer(10000)
if DEBUG_FRAMESUMMARY
// draw header of frame summary list.
text 10, 160, "f style (min<def<max) used comp rend resolved,frDenom,frSpace,compMin,compMax"
a2line 10, 175, scrW, 175, 0xff404040
endif
x# = 0
for n = 0 to numFrames
w# = frame(n).compWidth `frame(n)
if w# - int(w#) >= 0.5 then w = floor(w# + 1.0) else w = w#
if x# - int(x#) >= 0.5 then x = floor(x# + 1.0) else x = x#
if n = 0
// draw container frame (pink).
a2box x, 0, x+w, 128, 0xff800080
else
if DEBUG_SHOWSIMPLEFRAME = 1
// draw frame without wrapped text.
a2box x, 0, x+w, 128, 0xffffffff
a2line x, 138, x+w, 138, 0x30ffffff
a2line x, 133, x, 143, 0x30ffffff
a2line x+w, 133, x+w, 143, 0x30ffffff
center text x+w/2, 131, str$(w)
else
// draw frame with wrapped text.
a2box x, 0, x+w, 128, 0xffffffff
a2setclip x+1, 1, x+w-1, 127
a2boxtext f, x+4, y+4, x+w-4, 124, test$, 0, 0, 1, 0x30ffffff
a2resetclip
a2line x, 138, x+w, 138, 0x30ffffff
a2line x, 133, x, 143, 0x30ffffff
a2line x+w, 133, x+w, 143, 0x30ffffff
center text x+w/2, 131, str$(w)
endif
x# = x# + w#
endif
// debug
if DEBUG_FRAMESUMMARY
if n <= 16
// entry for this frame in summary list.
s$ = padright$(str$(n), 3)
s$ = s$ + padright$(Measurement$(nullMeasurement, frame(n).minWidth.qu, frame(n).minWidth.un), 10) + " < " + padright$(Measurement$(nullMeasurement, frame(n).width.qu, frame(n).width.un), 10) + " < " + padright$(Measurement$(nullMeasurement, frame(n).maxWidth.qu, frame(n).maxWidth.un), 10) + " "
s$ = s$ + padright$(Measurement$(nullMeasurement, frame(n).usedWidth.qu, frame(n).usedWidth.un), 10) + " "
s$ = s$ + padright$(Measurement$(nullMeasurement, frame(n).compWidth, UNIT_PX), 10) + " "
s$ = s$ + padright$(Measurement$(nullMeasurement, frame(n).rendWidth, UNIT_PX), 10) + " "
s$ = s$ + str$(frame(n).compValid) + ", " + str$(frame(n).compFrDenom,3) + ", " + str$(frame(n).compFrSpace,3) + ", " + str$(frame(n).compMinWidth,2) + ", " + str$(frame(n).compMaxWidth,2)
text 10, 175+n*15, s$
else
// list runs out of room.
if n = 17 then text 10, 430, "... +" + str$(numFrames-16) + " more"
endif
endif
next n
te = hitimer(10000)
dr_t = te - ts
endif
a2fillbox 0, scrH-15, scrW, scrH, 0xff060606
text 0, scrH-15, "scrfps: " + str$(screen fps())
text 256, scrH-15, "Last calc time: " + str$(ev_t*0.1,1) + "ms Last draw time: " + str$(dr_t*0.1,1) + "ms"
sync
nice wait 15
loop
// accepts a measurement type variable or two variables representing a measurement.
function Measurement$(in as t_measurement, in2Qu as float, in2Un)
if in2Un <> 0
in.qu = in2Qu
in.un = in2Un
endif
select in.un
case UNIT_PX : out$ = str$(in.qu,2) + "px" : endcase
case UNIT_PERC : out$ = str$(in.qu,2) + "%" : endcase
case UNIT_FR : out$ = str$(in.qu,2) + "fr" : endcase
case default : out$ = "" : endcase
endselect
endfunction out$
function EvaluateFrameWidth(id, parId)
local width as t_measurement, minWidth as t_measurement, maxWidth as t_measurement
width = frame(id).usedWidth : minWidth = frame(id).minWidth : maxWidth = frame(id).maxWidth
compWidth# = frame(id).compWidth
if id = 0
// reset container.
frame(id).compFrSpace = frame(id).compWidth
frame(id).compFrDenom = 0
// reset children to defaults.
for n = 1 to numFrames
frame(n).compValid = 0
frame(n).usedWidth = frame(n).width
frame(n).compWidth = 0
remstart if frame(n).width.un = UNIT_PX
// pixel (absolutely) sized frames need no further processing.
frame(n).compMinWidth = frame(n).width.qu
frame(n).compWidth = frame(n).width.qu
frame(n).compValid = 1
else: remend
if frame(n).minWidth.un = UNIT_PX
frame(n).compMinWidth = frame(n).minWidth.qu
else
frame(n).compMinWidth = 0
endif`:endif
if frame(n).maxWidth.un = UNIT_PX
frame(n).compMaxWidth = frame(n).maxWidth.qu
else
frame(n).compMaxWidth = 100000.0 // @ some large number.
endif
if frame(n).width.un = UNIT_FR
frame(id).compFrDenom = frame(id).compFrDenom + frame(n).width.qu
else
`frame(id).compFrSpace = frame(id).compFrSpace - frame(n).compMinWidth
endif
next n
// iterate and resolve children.
pass = 0
repeat
inc pass
noConstrain = 1
// STEP 1 // Calculate non-fr frame widths based on used size.
frame(id).compFrSpace2 = frame(id).compFrSpace
frame(id).compFrDenom2 = frame(id).compFrDenom
for n = 1 to numFrames
if frame(n).usedWidth.un = UNIT_PERC or frame(n).usedWidth.un = UNIT_PX then EvaluateFrameWidth(n, id)
next n
// STEP 2 // Apply constraints to non-fr frames.
frame(id).compFrSpace = frame(id).compFrSpace2
frame(id).compFrDenom = frame(id).compFrDenom2
`repeat
for n = 1 to numFrames
if frame(n).usedWidth.un = UNIT_PERC or frame(n).usedWidth.un = UNIT_PX then noConstrain = noConstrain && ConstrainFrameWidth(n, id)
next n
`until allResolved
// STEP 3 // Calculate fr frames.
frame(id).compFrSpace = frame(id).compFrSpace2
frame(id).compFrDenom = frame(id).compFrDenom2
for n = 1 to numFrames
if frame(n).usedWidth.un = UNIT_FR then EvaluateFrameWidth(n, id)
next n
// STEP 4 // Apply constraints to fr frames.
frame(id).compFrSpace = frame(id).compFrSpace2
frame(id).compFrDenom = frame(id).compFrDenom2
for n = 1 to numFrames
if frame(n).usedWidth.un = UNIT_FR then noConstrain = noConstrain && ConstrainFrameWidth(n, id)` : if pass = 2 then text 0+n*100, 700, str$(n) + ":" + str$(frame(n).compWidth) + "px"
next n
// STEP 5 // respond to changes in available/free space.
frame(id).compFrSpace = frame(id).compFrSpace2
frame(id).compFrDenom = frame(id).compFrDenom2
unresolved = 0
if frame(id).compFrSpace < 0
rem start
for n = 1 to numFrames
if frame(n).width.un = UNIT_PERC and frame(n).usedWidth.un <> UNIT_FR
if frame(n).compWidth > frame(n).compMinWidth
frame(id).compFrSpace2 = frame(id).compFrSpace2 + frame(n).compWidth // remove contribution to used space.
frame(id).compFrDenom2 = frame(id).compFrDenom2 + frame(n).compWidth `frame(n).width.qu
frame(n).usedWidth.qu = frame(n).compWidth `CalcSize(frame(n).usedWidth.qu, frame(n).usedWidth.un, frame(parId).compWidth.qu, frame(parId).compWidth.un, frame(parId).compFrSpace2, frame(parId).compFrDenom2, UNIT_FR)
`frame(n).usedWidth.qu = CalcSize(frame(n).usedWidth.qu, frame(n).usedWidth.un, frame(id).compWidth.qu, frame(id).compWidth.un, frame(id).compFrSpace2, frame(id).compFrDenom2, UNIT_FR)
frame(n).usedWidth.un = UNIT_FR
unresolved = 1
endif
endif
next n
rem end
endif
// check no overflow of container/exit conditions.
frame(id).compFrSpace = frame(id).compFrSpace2
frame(id).compFrDenom = frame(id).compFrDenom2
totalWidth# = 0
canCompress = 0
canEnlarge = 0
frSpaceUsed# = 0
for n = 1 to numFrames
totalWidth# = totalWidth# + frame(n).compWidth
if frame(n).usedWidth.un = UNIT_FR then frSpaceUsed# = frSpaceUsed# + frame(n).compWidth
if frame(n).compWidth > frame(n).compMinWidth then canCompress = 1
if frame(n).compWidth < frame(n).compMaxWidth then canEnlarge = 1
next n
// DEBUG //
if DEBUG_EVALFRAMEPASSEND
x = 0
s$ = "End pass " + str$(pass) + ": FrSpc = " + str$(frame(id).compFrSpace,1) + "px, FrDen = " + str$(frame(id).compFrDenom,1)
s$ = s$ + "px, totalW = " + str$(totalWidth#,1) + "px[?c"+str$(canCompress)+",e"+str$(canEnlarge) + "], FrSpcUsed = " + str$(frSpaceUsed#,1) + ", nocnstr? = " + str$(noConstrain)+", unrslvd? = " + str$(unresolved) + " "
ink 0xff808080,0 : text x, 460+pass*45, s$` : inc x, text width(s$)
ink 0xffffffff,0 : x = 32 `960
for n = 1 to numFrames
`s$ =
s$ = Measurement$(nullMeasurement, frame(n).compWidth, UNIT_PX)
text x, 478+pass*45, s$ : inc x, text width(s$)
s$ = " " + chr$(171) + " " + Measurement$(nullMeasurement, frame(n).usedWidth.qu, frame(n).usedWidth.un) + " " + chr$(171) + " " + Measurement$(nullMeasurement, frame(n).width.qu, frame(n).width.un)
if n < numFrames then s$ = s$ + ", "
ink 0xffa0a0a0, 0 : text x, 478+pass*45, s$ : inc x, text width(s$)
ink 0xffffffff, 0
next n
endif
until ((pass > 0 and noConstrain = 1 and unresolved = 0) or pass=100)` and ((abs(frSpaceUsed# - frame(id).compFrSpace) < EPSILON) or (abs(totalWidth# - frame(id).compWidth) < EPSILON or (totalWidth# > frame(id).compWidth and canCompress = 0) or (totalWidth# < frame(id).compWidth and canEnlarge = 0)))) or pass = 10
// @ force container to be at least as wide as children (if free space is negative then subtract it).
frame(id).compWidth = max(frame(id).compWidth, totalWidth#)
endif
// quick fix for root container.
if id = 0 then exitfunction
// CALCULATE FRAME WIDTH. //
// evaluate style.
select width.un
case UNIT_PX
frame(id).compWidth = CalcSize(width.qu, width.un, frame(parId).compWidth, UNIT_PX, 0, 0, UNIT_PX)
`frame(parId).compFrSpace2 = frame(parId).compFrSpace2 - frame(id).compWidth
`frame(id).compValid = 1
endcase
case UNIT_PERC
frame(id).compWidth = CalcSize(width.qu, width.un, frame(parId).compWidth, UNIT_PX, 0, 0, UNIT_PX)
`frame(parId).compFrSpace2 = frame(parId).compFrSpace2 - frame(id).compWidth
`frame(id).compValid = 1
endcase
case UNIT_FR
frame(id).compWidth = CalcSize(width.qu, width.un, frame(parId).compWidth, UNIT_PX, frame(parId).compFrSpace, frame(parId).compFrDenom, UNIT_PX)
`text 0+id*50, 780, "e:" + str$(id) + ":" + str$(frame(id).compWidth)
`frame(id).compValid = 1
endcase
endselect
if frame(id).usedWidth.un <> UNIT_FR `frame(id).width.un <> UNIT_FR
frame(parId).compFrSpace2 = frame(parId).compFrSpace2 - (frame(id).compWidth - compWidth#)
endif
endfunction
function ConstrainFrameWidth(id, parId)
local resolved = 1
local width as t_measurement, minWidth as t_measurement, maxWidth as t_measurement
width = frame(id).usedWidth : minWidth = frame(id).minWidth : maxWidth = frame(id).maxWidth
compWidth# = frame(id).compWidth
if maxWidth.un <> UNIT_NONE
maxWidthPx# = CalcSize(maxWidth.qu, maxWidth.un, frame(parId).compWidth, UNIT_PX, 0, 0, UNIT_PX)
frame(id).compMaxWidth = maxWidthPx#
if frame(id).compWidth > maxWidthPx#
// apply constraint directly if absolute (px-based), or leave to next pass otherwise.
frame(id).usedWidth = maxWidth
frame(id).compWidth = maxWidthPx#
`frame(id).compValid = 1
resolved = 0
endif
endif
if minWidth.un <> UNIT_NONE
minWidthPx# = CalcSize(minWidth.qu, minWidth.un, frame(parId).compWidth, UNIT_PX, 0, 0, UNIT_PX)
frame(id).compMinWidth = minWidthPx#
if frame(id).compWidth < minWidthPx#
// apply constraint directly if absolute (px-based), or leave to next pass otherwise.
frame(id).usedWidth = minWidth
frame(id).compWidth = minWidthPx#
`frame(id).compValid = 1
resolved = 0
endif
endif
if resolved = 0
if frame(id).usedWidth.un <> UNIT_FR
if width.un <> UNIT_FR
frame(parId).compFrSpace2 = frame(parId).compFrSpace2 - (frame(id).compWidth - compWidth#)
else
frame(parId).compFrSpace2 = frame(parId).compFrSpace2 - frame(id).compWidth
frame(parId).compFrDenom2 = frame(parId).compFrDenom2 - width.qu
`text 0+id*50, 760, str$(id)+","+str$(frame(id).compWidth)+"px"
endif
else
endif
endif
endfunction resolved
// converts between units.
function CalcSize(inSize as float, inUnit, parSize as float, parUnit, parCompFrSpace as float, parCompFrDenom as float, outUnit)
local outSize as float
// ensure parSize in px (or otherwise not referring to it)
if parUnit <> UNIT_NONE and parUnit <> UNIT_PX then parSize = CalcSize(parSize, parUnit, scrW, UNIT_PX, 0, 0, UNIT_PX)
select inUnit
case UNIT_PX
select outUnit
case UNIT_PX : outSize = inSize : endcase // [in]px [out]px
case UNIT_PERC : outSize = inSize * 100.0 / parSize : endcase // [in]px -> [out]%
case UNIT_FR : outSize = inSize / parCompFrSpace * parCompFrDenom : endcase // [in]px -> [out]fr
endselect
endcase
case UNIT_PERC
select outUnit
case UNIT_PX : outSize = inSize * 0.01 * parSize : endcase // [in]% -------> [out]px
case UNIT_PERC : outSize = inSize : endcase // [in]% [out]%
case UNIT_FR : outSize = (inSize * 0.01 * parSize) / parCompFrSpace * parCompFrDenom : endcase // [in]% -> px -> [out]fr
endselect
endcase
case UNIT_FR
select outUnit
case UNIT_PX : outSize = inSize / parCompFrDenom * parCompFrSpace : endcase // [in]fr -------> [out]px
case UNIT_PERC : outSize = (inSize / parCompFrDenom * parCompFrSpace) / parSize * 100.0 : endcase // [in]fr -> px -> [out]%
case UNIT_FR : outSize = inSize : endcase // [in]fr [out]fr
endselect
endcase
endselect
endfunction outSize
function SetFrameStyle_Width(id, width$, minWidth$, maxWidth$)
frame(id).width.qu = QuantityFromMeasurementString(width$)
frame(id).width.un = UnitFromMeasurementString(width$)
frame(id).minWidth.qu = QuantityFromMeasurementString(minWidth$)
frame(id).minWidth.un = UnitFromMeasurementString(minWidth$)
frame(id).maxWidth.qu = QuantityFromMeasurementString(maxWidth$)
frame(id).maxWidth.un = UnitFromMeasurementString(maxWidth$)
// @ disallow setting fr-based min/max widths.
if frame(id).minWidth.un = UNIT_FR then frame(id).minWidth.un = UNIT_NONE
if frame(id).maxWidth.un = UNIT_FR then frame(id).maxWidth.un = UNIT_NONE
// @ enforce sensible lower limit.
if frame(id).width.un <> UNIT_PX
if frame(id).minWidth.un = UNIT_NONE
frame(id).minWidth.qu = 0
frame(id).minWidth.un = UNIT_PX
endif
endif
// @ quick fix: px-sized frames without min and max set cause errors in layout sizing.
`if frame(id).width.un = UNIT_PX
` frame(id).minWidth = frame(id).width
` frame(id).maxWidth = frame(id).width
`endif
// if nonsense widths set (eg. min:20px and max:10px), raise error/warning?
endfunction
function QuantityFromMeasurementString(in$)
out# = val(in$)
endfunction out#
function UnitFromMeasurementString(in$)
if in$ = "" then exitfunction UNIT_NONE
subIn$ = lower$(right$(in$, 2))
if subIn$ = "px" then exitfunction UNIT_PX
if subIn$ = "fr" then exitfunction UNIT_FR
if mid$(subIn$, 2) = "%" then exitfunction UNIT_PERC
endfunction UNIT_NONE
It requires advanced2d and M1U to run, though all the a2d (except the wrapped box-text) can be replaced with standard DBP stuff (I might edit this post to add a non-a2d copy).
Pic.
Things to try:
- Change the three DEBUG switches at the top (FRAMESUMMARY is probably most useful).
- In the Frame Setup section, swap in different box setups by commenting in and out the 6 presets (also be sure to change numFrames to required).
- Make custom sets.
- Set 5's frame 5 can be adjusted with the up/down arrow keys.
- The width of the container is adjusted by moving the mouse.
Things to note:
- It's a wip so there's probably a couple of loose ends and unused variables.
- There are a couple of assumptions in the code. %-sized frames scale with the size of the container when there is free space available in the container; they scale with the amount of remaining space when there is not. The behaviour with frames that have min-width greater than max-width is undefined (read: I haven't tried it yet).
- At the moment the "inner" width of the container is equal to its "outer" width. That is, there is no overflow (content wider than the box, usually with a scrollbar). If you have two frames, both set to take 100% of the space, they will follow the assumption above and take up 100/200th's of available space each (that is, they'll behave as though they were both 50%), whereas with overflow you'd have a scrollbar and the "inner" width would be twice that of the "outer" width.
Let me know if it breaks