monomer-1.4.0.0: src/Monomer/Widgets/Singles/Spacer.hs
{-|
Module : Monomer.Widgets.Singles.Spacer
Copyright : (c) 2018 Francisco Vallarino
License : BSD-3-Clause (see the LICENSE file)
Maintainer : fjvallarino@gmail.com
Stability : experimental
Portability : non-portable
Spacer is used for adding a fixed space between two widgets.
@
hstack [
label \"Username\",
spacer,
label username
]
@
Filler is used for taking all the unused space between two widgets. Useful for
alignment purposes.
@
hstack [
label "Section title",
filler,
button \"Close\" CloseSection
]
@
Both adapt to the active layout direction.
-}
{-# LANGUAGE FlexibleContexts #-}
module Monomer.Widgets.Singles.Spacer (
-- * Configuration
SpacerCfg,
-- * Constructors
spacer,
spacer_,
filler,
filler_
) where
import Control.Applicative ((<|>))
import Control.Lens ((^.))
import Data.Default
import Data.Maybe
import Data.Tuple
import Monomer.Widgets.Single
import qualified Monomer.Core.Lens as L
{-|
Configuration options for spacer widget:
- 'width': the max width for spacer, the reference for filler.
- 'resizeFactor': flexibility to have more or less spaced assigned.
-}
data SpacerCfg = SpacerCfg {
_spcWidth :: Maybe Double,
_spcFactor :: Maybe Double
}
instance Default SpacerCfg where
def = SpacerCfg {
_spcWidth = Nothing,
_spcFactor = Nothing
}
instance Semigroup SpacerCfg where
(<>) s1 s2 = SpacerCfg {
_spcWidth = _spcWidth s2 <|> _spcWidth s1,
_spcFactor = _spcFactor s2 <|> _spcFactor s1
}
instance Monoid SpacerCfg where
mempty = def
instance CmbWidth SpacerCfg where
width w = def {
_spcWidth = Just w
}
instance CmbResizeFactor SpacerCfg where
resizeFactor f = def {
_spcFactor = Just f
}
-- | Creates a spacer widget.
spacer :: WidgetNode s e
spacer = spacer_ def
-- | Creates a spacer widget. Accepts config.
spacer_ :: [SpacerCfg] -> WidgetNode s e
spacer_ configs = defaultWidgetNode "spacer" widget where
config = mconcat (resizeFactor 0 : configs)
widget = makeSpacer config
-- | Creates a filler widget.
filler :: WidgetNode s e
filler = filler_ def
-- | Creates a filler widget. Accepts config.
filler_ :: [SpacerCfg] -> WidgetNode s e
filler_ configs = defaultWidgetNode "filler" widget where
config = mconcat configs
widget = makeSpacer config
makeSpacer :: SpacerCfg -> Widget s e
makeSpacer config = widget where
widget = createSingle () def {
singleGetSizeReq = getSizeReq
}
getSizeReq wenv node = sizeReq where
direction = wenv ^. L.layoutDirection
factor = fromMaybe 0.5 (_spcFactor config)
isFixed = factor < 0.01
width
| isFixed = fromMaybe 10 (_spcWidth config)
| otherwise = fromMaybe 5 (_spcWidth config)
flexSide = flexSize 5 0.5
fixedW = fixedSize width
flexW = flexSize width factor
expandW = expandSize width factor
sizeReq
| isFixed && direction == LayoutNone = (fixedW, fixedW)
| isFixed && direction == LayoutHorizontal = (fixedW, flexSide)
| isFixed = (flexSide, fixedW)
| direction == LayoutNone = (expandW, expandW)
| direction == LayoutHorizontal = (expandW, flexW)
| otherwise = (flexW, expandW)