|
From: <kr_...@us...> - 2003-10-19 11:15:21
|
Update of /cvsroot/htoolkit/gio/src/Graphics/UI/GIO
In directory sc8-pr-cvs1:/tmp/cvs-serv7625/src/Graphics/UI/GIO
Modified Files:
Layout.hs
Log Message:
More clever layout algorithm. Added support for stretch/hstretch/vstretch
Index: Layout.hs
===================================================================
RCS file: /cvsroot/htoolkit/gio/src/Graphics/UI/GIO/Layout.hs,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** Layout.hs 10 Oct 2003 14:21:52 -0000 1.8
--- Layout.hs 19 Oct 2003 09:33:20 -0000 1.9
***************
*** 103,106 ****
--- 103,107 ----
-- * Stretch
, hfill, vfill, fill
+ , hstretch, vstretch, stretch
, hrigid, vrigid, rigid
, hfix, vfix
***************
*** 221,224 ****
--- 222,226 ----
| Changer (Pack -> Pack) Layout
| Control WindowHandle WindowHandle (WindowHandle -> IO Size) -- parent handle, control handle, get request size
+ | Empty
{--------------------------------------------------------------------
***************
*** 227,233 ****
-- | Primitive: An empty invisible control with a zero size.
empty :: Layout
! -- need to mimic a control instead of "Grid [[]]" or otherwise the calculation of
! -- the initial dialog size fails to take outer padding into account.
! empty = Control nullHandle nullHandle (\h -> return (Size 0 0)) -- Grid [[]]
-- | Primitive: Create a grid of controls, gives precise control over alignment. (See also 'tabular').
--- 229,233 ----
-- | Primitive: An empty invisible control with a zero size.
empty :: Layout
! empty = Empty
-- | Primitive: Create a grid of controls, gives precise control over alignment. (See also 'tabular').
***************
*** 257,282 ****
-- | Make a control rigid -- it won't stretch to fit the available space (default).
rigid :: Control w => w -> Layout
! rigid w = Changer (\l -> l{ stretchX = False, stretchY = False }) (pack w)
-- | Make a control vertically rigid -- it won't stretch to fit the available space (default).
vrigid :: Control w => w -> Layout
! vrigid w = Changer (\l -> l{ stretchY = False }) (pack w)
-- | Make a control horizontally rigid -- it won't stretch to fit the available space (default).
hrigid :: Control w => w -> Layout
! hrigid w = Changer (\l -> l{ stretchX = False }) (pack w)
-- | The control will stretch both horizontally and vertically to fill the available space.
fill :: Control w => w -> Layout
! fill w = Changer (\l -> l{ stretchX = True, stretchY = True }) (pack w)
-- | The control will stretch horizontally to fit in the available space.
hfill :: Control w => w -> Layout
! hfill w = Changer (\l -> l{ stretchX = True }) (pack w)
-- | The control stretches vertically to fit in the available space.
vfill :: Control w => w -> Layout
! vfill w = Changer (\l -> l{ stretchY = True }) (pack w)
-- | Set the preferred width of a control.
--- 257,309 ----
-- | Make a control rigid -- it won't stretch to fit the available space (default).
rigid :: Control w => w -> Layout
! rigid w = Changer (\l -> l{ stretchX = False, stretchY = False, fillX = False, fillY = False }) (pack w)
-- | Make a control vertically rigid -- it won't stretch to fit the available space (default).
vrigid :: Control w => w -> Layout
! vrigid w = Changer (\l -> l{ stretchY = False, fillY = False }) (pack w)
-- | Make a control horizontally rigid -- it won't stretch to fit the available space (default).
hrigid :: Control w => w -> Layout
! hrigid w = Changer (\l -> l{ stretchX = False, fillX = False }) (pack w)
-- | The control will stretch both horizontally and vertically to fill the available space.
+ -- Any grid with at least one filling item will also stretch to fill
+ -- the entire available space.
fill :: Control w => w -> Layout
! fill w = Changer (\l -> l{ stretchX = True, stretchY = True, fillX = True, fillY = True }) (pack w)
-- | The control will stretch horizontally to fit in the available space.
+ -- Any grid with at least one filling item will also stretch to fill
+ -- the entire available space.
hfill :: Control w => w -> Layout
! hfill w = Changer (\l -> l{ stretchX = True, fillX = True }) (pack w)
-- | The control stretches vertically to fit in the available space.
+ -- Any grid with at least one filling item will also stretch to fill
+ -- the entire available space.
vfill :: Control w => w -> Layout
! vfill w = Changer (\l -> l{ stretchY = True, fillY = True }) (pack w)
!
!
! -- | The control will stretch both horizontally and vertically to fill the available space.
! -- When the control is placed in grid then the available width is equal to maximal width
! -- of controls in the same column and the available height is equal to maximal height
! -- of controls in the same row.
! stretch :: Control w => w -> Layout
! stretch w = Changer (\l -> l{ stretchX = True, stretchY = True, fillX = False, fillY = False }) (pack w)
!
! -- | The control will stretch horizontally to fit in the available space.
! -- When the control is placed in grid then the available space is equal to maximal width
! -- of controls in the same column.
! hstretch :: Control w => w -> Layout
! hstretch w = Changer (\l -> l{ stretchX = True, fillX = False }) (pack w)
!
! -- | The control stretches vertically to fit in the available space.
! -- When the control is placed in grid then the available space is equal to maximal height
! -- of controls in the same row.
! vstretch :: Control w => w -> Layout
! vstretch w = Changer (\l -> l{ stretchY = True, fillY = False }) (pack w)
!
-- | Set the preferred width of a control.
***************
*** 354,362 ****
-- | A layout control of a certain width with no height. Used to implement padding.
hrod :: Int -> Layout
! hrod w = hfix w empty
-- | A layout control of a certain height with no width. Used to implement padding.
vrod :: Int -> Layout
! vrod h = vfix h empty
-- | Add a padding between each control in the layout, including a padding around
--- 381,389 ----
-- | A layout control of a certain width with no height. Used to implement padding.
hrod :: Int -> Layout
! hrod w = vstretch (hfix w empty)
-- | A layout control of a certain height with no width. Used to implement padding.
vrod :: Int -> Layout
! vrod h = hstretch (vfix h empty)
-- | Add a padding between each control in the layout, including a padding around
***************
*** 376,379 ****
--- 403,407 ----
Changer f l -> Changer f (inner l)
Control _ _ _ -> lay
+ Empty -> lay
Grid css -> Grid (intersperse vrods (map (intersperse (hrod m)) (map (map inner) css)))
where
***************
*** 388,394 ****
getLayoutSize c
= do p <- layoutToPack (pack c)
! let rs = layoutPack 0 0 0 0 p
! sz = rectSize $ foldr rectUnion (rectOfSize (Size 0 0)) rs
! return sz
-- | Positions a controls in a certain rectangle
--- 416,421 ----
getLayoutSize c
= do p <- layoutToPack (pack c)
! let (rs,needed) = layoutPack 0 0 0 0 p
! return needed
-- | Positions a controls in a certain rectangle
***************
*** 398,404 ****
| any (/= parent) parents = ioError (userError "Layout.layout: laying out controls from different windows")
| otherwise = do p <- layoutToPack layout
! let rs = layoutPack x y w h p
! needed = rectSize (foldr rectUnion (rectAt (pt x y) (sz 0 0)) rs)
! sequence_ (zipWith moveResize rs controls)
return needed
where
--- 425,430 ----
| any (/= parent) parents = ioError (userError "Layout.layout: laying out controls from different windows")
| otherwise = do p <- layoutToPack layout
! let (rs,needed) = layoutPack x y w h p
! mapM_ moveResize rs
return needed
where
***************
*** 407,416 ****
(Size w h) = rectSize r
! controls = extractControls layout
! parents = [hwnd | (Control hwnd _ _) <- controls, hwnd /= nullHandle]
parent = head parents
!
! moveResize rect (Control hparent hcontrol get)
! = if hcontrol /= nullHandle then Port.moveResizeControl hcontrol rect else return ()
--- 433,443 ----
(Size w h) = rectSize r
! parents = [hwnd | (Control hwnd _ _) <- extractControls layout]
parent = head parents
!
! moveResize (rect,layout) =
! case layout of
! Control hparent hcontrol get -> Port.moveResizeControl hcontrol rect
! Empty -> return ()
***************
*** 420,428 ****
mapM_ (\c -> Port.setControlVisible c True ) (new_controls \\ old_controls)
where
! old_controls = foldr collectHandles [] (extractControls old_lay)
! new_controls = foldr collectHandles [] (extractControls new_lay)
- collectHandles (Control _ h _) hs = if h /= nullHandle then h:hs else hs
-
extractControls :: Layout -> [Layout]
--- 447,453 ----
mapM_ (\c -> Port.setControlVisible c True ) (new_controls \\ old_controls)
where
! old_controls = [hwnd | (Control _ hwnd _) <- extractControls old_lay]
! new_controls = [hwnd | (Control _ hwnd _) <- extractControls new_lay]
extractControls :: Layout -> [Layout]
***************
*** 431,434 ****
--- 456,460 ----
Grid lss -> concat (map (concat . map extractControls) lss)
Changer f l -> extractControls l
+ Empty -> []
Control _ h _ -> [lay]
***************
*** 437,455 ****
The actual layout algorithm works on the (non-IO) Pack structure.
--------------------------------------------------------------------}
! data Pack = Table{ stretchX :: Bool, stretchY :: Bool
! , prefW :: Int, prefH :: Int
, translate :: Point -> Size -> Point
, rows :: [[Pack]]
}
! | Item { stretchX :: Bool, stretchY :: Bool
! , prefW :: Int, prefH :: Int
, translate :: Point -> Size -> Point
! }
table :: [[Pack]] -> Pack
! table rows = Table (any (any stretchX) rows) (any (any stretchY) rows)
! (sum (widths rows)) (sum (heights rows))
(\pos sz -> pos)
rows
layoutToPack :: Layout -> IO Pack
--- 463,487 ----
The actual layout algorithm works on the (non-IO) Pack structure.
--------------------------------------------------------------------}
! data Pack = Table{ fillX :: Bool, fillY :: Bool
! , stretchX :: Bool, stretchY :: Bool
! , prefW :: Int, prefH :: Int
, translate :: Point -> Size -> Point
, rows :: [[Pack]]
}
! | Item { fillX :: Bool, fillY :: Bool
! , stretchX :: Bool, stretchY :: Bool
! , prefW :: Int, prefH :: Int
, translate :: Point -> Size -> Point
! , control :: Layout
! }
table :: [[Pack]] -> Pack
! table rows = Table (any (any fillX) rows) (any (any fillY) rows)
! (any (all stretchX) cols) (any (all stretchY) rows)
! (sum (widths rows)) (sum (heights rows))
(\pos sz -> pos)
rows
+ where
+ cols = columns rows
layoutToPack :: Layout -> IO Pack
***************
*** 460,470 ****
Control hparent hcontrol getPrefSize
-> do (Size w h) <- getPrefSize hcontrol
! return (Item False False w h (\pos sz -> pos))
! Changer f lay -> do p <- layoutToPack lay
! return (f p)
{--------------------------------------------------------------------
Daan's ultra simple power-layout algorithm :-)
--------------------------------------------------------------------}
maximal :: [Int] -> Int
--- 492,503 ----
Control hparent hcontrol getPrefSize
-> do (Size w h) <- getPrefSize hcontrol
! return (Item False False False False w h (\pos sz -> pos) layout)
! Empty -> return (Item False False False False 0 0 (\pos sz -> pos) layout)
! Changer f lay -> do fmap f (layoutToPack lay)
{--------------------------------------------------------------------
Daan's ultra simple power-layout algorithm :-)
+ ** Modified and extended by Krasimir Angelov **
--------------------------------------------------------------------}
maximal :: [Int] -> Int
***************
*** 482,494 ****
! layoutPack :: Int -> Int -> Int -> Int -> Pack -> [Rect]
! layoutPack x y w h (Item stretchX stretchY prefW prefH trans)
! = let wd = if stretchX then max w prefW else prefW
! ht = if stretchY then max h prefH else prefH
sz = Size wd ht
pos = trans (pt x y) sz
! in [rectAt pos sz]
! layoutPack x y w h (Table stretchx stretchy prefW prefH trans rows)
= let mws = widths rows
mhs = heights rows
--- 515,527 ----
! layoutPack :: Int -> Int -> Int -> Int -> Pack -> ([(Rect,Layout)],Size)
! layoutPack x y w h (Item fillx filly stretchx stretchy prefW prefH trans layout)
! = let wd = if stretchx then max w prefW else prefW
! ht = if stretchy then max h prefH else prefH
sz = Size wd ht
pos = trans (pt x y) sz
! in ([(rectAt pos sz,layout)],sz)
! layoutPack x y w h (Table fillx filly stretchx stretchy prefW prefH trans rows)
= let mws = widths rows
mhs = heights rows
***************
*** 496,527 ****
dw = max 0 (w - prefW)
dh = max 0 (h - prefH)
! wstretch = map (any stretchX) (columns rows)
! hstretch = map (any stretchY) rows
! dws = deltas dw wstretch
! dhs = deltas dh hstretch
!
! ws | stretchx = zipWith (+) dws mws
! | otherwise = mws
! hs | stretchy = zipWith (+) dhs mhs
! | otherwise = mhs
! pos = trans (pt x y) (sz (sum ws) (sum hs))
xs = scanl (+) (px pos) ws
ys = scanl (+) (py pos) hs
! in concat [concat [layoutPack x y w h item | (item,w,x) <- zip3 row ws xs ] | (row,h,y) <- zip3 rows hs ys]
where
deltas total stretches
| count == 0 = repeat 0
! | otherwise = loop (mod total count) stretches
where
count = length (filter id stretches)
! delta = div total count
loop n [] = []
loop n (stretch:xs) | stretch && n > 0 = (delta+1):loop (n-1) xs
| stretch = delta:loop 0 xs
! | otherwise = 0:loop (n-1) xs
--- 529,561 ----
dw = max 0 (w - prefW)
dh = max 0 (h - prefH)
! wfill = map (\col -> any fillX col || all stretchX col) (columns rows)
! hfill = map (\row -> any fillY row || all stretchY row) rows
! dws = deltas dw wfill
! dhs = deltas dh hfill
! ws | fillx || stretchx = zipWith (+) dws mws
! | otherwise = mws
+ hs | filly || stretchy = zipWith (+) dhs mhs
+ | otherwise = mhs
! needed = sz (sum ws) (sum hs)
!
! pos = trans (pt x y) needed
xs = scanl (+) (px pos) ws
ys = scanl (+) (py pos) hs
! in (concat [concat [fst (layoutPack x y w h item) | (item,w,x) <- zip3 row ws xs] | (row,h,y) <- zip3 rows hs ys],needed)
where
deltas total stretches
| count == 0 = repeat 0
! | otherwise = loop rest stretches
where
count = length (filter id stretches)
! (delta,rest) = divMod total count
loop n [] = []
loop n (stretch:xs) | stretch && n > 0 = (delta+1):loop (n-1) xs
| stretch = delta:loop 0 xs
! | otherwise = 0:loop n xs
|