module Graphics.UI.WxGeneric.Layout
( smartLayout, oneColumnLayout, twoColumnLayout
, JoinLayout, SizedLayout
, toSizedLayout
)
where
import Graphics.UI.WX
import Data.List
smartMaxHorizontalSize :: Int
smartMaxHorizontalSize = 400
showWidgetSizeInHeadings :: Bool
showWidgetSizeInHeadings = False
type JoinLayout = String -> FromWxGenLayout Layout
type SizedLayout = (Int, Layout)
type FromWxGenLayout a = [(StaticText (), SizedLayout)] -> [SizedLayout] -> a
type WxGenLayout = ([(StaticText (), SizedLayout)], [SizedLayout])
estimateSize :: Dimensions w => w -> IO Int
estimateSize w = get w bestSize >>= return . sizeH
toSizedLayout :: (Widget w, Dimensions w) => w -> IO SizedLayout
toSizedLayout wid = do s <- estimateSize wid
return (s, widget wid)
smartLayout :: JoinLayout
smartLayout topHeading withLabels withoutLabels
| sum (sizes withLabels withoutLabels) > smartMaxHorizontalSize
= twoColumnLayout topHeading withLabels withoutLabels
| otherwise
= oneColumnLayout topHeading withLabels withoutLabels
toHeader :: String -> FromWxGenLayout String
toHeader header withLabels withoutLabels =
case showWidgetSizeInHeadings of
False -> header
True -> header ++ ", sizes=" ++ (show $ sizes withLabels withoutLabels)
sizes :: FromWxGenLayout [Int]
sizes withLabels withoutLabels
= map fst (map snd withLabels ++ withoutLabels)
oneColumnLayout :: JoinLayout
oneColumnLayout topHeading withLabels withoutLabels =
if (null withLabels && null withoutLabels)
then fill $ boxed "" $ label "no contents"
else let h = toHeader topHeading withLabels withoutLabels
in boxed h $ layoutColumn withLabels withoutLabels
twoColumnLayout :: JoinLayout
twoColumnLayout topHeading withLabels withoutLabels
= case splitMiddle withLabels withoutLabels of
(_, ([], [])) -> divergeOneColumn
(([], []), _) -> divergeOneColumn
(leftLay, rightLay)
-> let columnLayout lay = column 1 [ uncurry layoutColumn lay, glue ]
h = toHeader topHeading withLabels withoutLabels
in boxed h $ row 10 [ columnLayout leftLay
, columnLayout rightLay ]
where divergeOneColumn = oneColumnLayout topHeading withLabels withoutLabels
splitMiddle :: FromWxGenLayout (WxGenLayout, WxGenLayout)
splitMiddle labeled unlabeled =
let xs = sizes labeled unlabeled
middlePixel = sum xs `div` 2
middle = length $ takeWhile (< middlePixel) $ map sum $ tail $ inits xs
splitLabeled = splitAt middle labeled
splitUnlabeled = splitAt (middle length labeled) unlabeled
in ((fst splitLabeled, fst splitUnlabeled)
,(snd splitLabeled, snd splitUnlabeled))
layoutColumn :: FromWxGenLayout Layout
layoutColumn withLabels withoutLabels
= column 10 $
(if null withLabels
then []
else [grid 20 10 $ map toLayout withLabels ]
) ++ map snd withoutLabels
where
toLayout (lbl, (s, w)) =
case showWidgetSizeInHeadings of
True -> [alignLeft $ widget lbl, label $ show s, w]
False -> [alignLeft $ widget lbl, w]