-- | A simple container for a group of button widgets. module HTk.Toolkit.SelectBox ( SelectBox, newSelectBox, addButton, addSpace, getDefault, selectDefault ) where import HTk.Toplevel.HTk import HTk.Kernel.GUIObject import HTk.Widgets.Space import Reactor.ReferenceVariables -- ----------------------------------------------------------------------- -- SelectBox type -- ----------------------------------------------------------------------- -- | The @SelectBox@ datatype. data SelectBox = SelectBox Box (Maybe (Frame,Int)) (Ref [Button]) type Elements = [Button] -- ----------------------------------------------------------------------- -- creation -- ----------------------------------------------------------------------- -- | Constructs a new select box and returns a handler. newSelectBox :: Container par => par -- ^ the parent widget, which has to be a container widget. -> Maybe Int -- ^ the optional index of a default button. -> [Config SelectBox] -- ^ the list of configuration options for this select box. -> IO SelectBox -- ^ A select box. newSelectBox par def@(Nothing) cnf = do b <- newHBox par [] pack b [Expand On, Fill X] em <- newRef [] configure (SelectBox b Nothing em) cnf newSelectBox par def@(Just i) ol = do b <- newHBox par [] pack b [Expand On, Fill X] em <- newRef [] f <- newFrame b [relief Sunken, borderwidth 1] pack f [] configure (SelectBox b (Just (f,i)) em) ol -- ----------------------------------------------------------------------- -- SelectBox instances -- ----------------------------------------------------------------------- -- | Internal. instance Eq SelectBox where w1 == w2 = (toGUIObject w1) == (toGUIObject w2) -- | A select box can be destroyed. instance Destroyable SelectBox where -- Destroys a select box. destroy = destroy . toGUIObject -- | Internal. instance GUIObject SelectBox where toGUIObject (SelectBox b _ e) = toGUIObject b cname _ = "SelectBox" -- | A select box has a configureable foreground and background colour. instance HasColour SelectBox where legalColourID = hasForeGroundColour -- | A select box has standard widget properties -- (concerning focus, cursor). instance Widget SelectBox -- | A select box has a configureable size. instance HasSize SelectBox -- | A select box has a configureable border. instance HasBorder SelectBox -- | A select box is a stateful widget, it can be enabled or disabled. instance HasEnable SelectBox where -- Sets the select box\'es state. state st sb@(SelectBox b _ em) = synchronize sb (do ibs <- getRef em foreach ibs (\ib -> configure ib [state st]) return sb) -- Gets the select box\'es state. getState sb = do b <- isEnabled sb if b then return Normal else return Disabled -- @True@, if the select box is enabled, otherwise -- @False@. isEnabled sb@(SelectBox b _ em) = synchronize sb (do ibs <- getRef em sl <- sequence (map getState ibs) return (foldr (||) False (map (/= Disabled) sl))) -- | You can synchronize on a select box. instance Synchronized SelectBox where -- Synchronizes on a select box. synchronize = synchronize . toGUIObject -- ----------------------------------------------------------------------- -- selection -- ----------------------------------------------------------------------- -- | Selects the default button of a select box. selectDefault :: SelectBox -- ^ the concerned select box. -> IO () -- ^ None. selectDefault sb = do mbt <- getDefault sb incase mbt (\bt -> flash bt >> invoke bt) -- | Gets the default button from a select box (if there is one). getDefault :: SelectBox -- ^ the concerned select box. -> IO (Maybe Button) -- ^ The default button of the select box -- (if there is one). getDefault sb@(SelectBox b Nothing em) = return Nothing getDefault sb@(SelectBox b (Just (f,i)) em) = do bts <- getRef em return (Just (bts !! i)) -- ----------------------------------------------------------------------- -- elements -- ----------------------------------------------------------------------- -- | Adds a space widget at the end of the select box. addSpace :: SelectBox -- ^ the concerned select box. -> Distance -- ^ the width of the space widget. -> IO Space -- ^ A space widget. addSpace sb@(SelectBox b _ em) dist = do s <- newSpace b dist [orient Horizontal] pack s [] return s -- | Adds a button widget at the end of the select box. addButton :: SelectBox -- ^ the concerned select box. -> [Config Button] -- ^ the list of configuration options for the constructed -- button. -> [PackOption] -- ^ the list of pack options for the constructed button. -> IO Button -- ^ A button widget. addButton sb@(SelectBox b Nothing em) cnf pcnf = synchronize sb (do bt <- newButton b cnf pack bt pcnf changeRef em (\el -> el ++ [bt]) return bt) addButton sb@(SelectBox b (Just (f,i)) em) cnf pcnf = synchronize sb (do el <- getRef em let is_default = (i == length el + 1) bt <- if is_default then newButton f cnf else newButton b cnf (if is_default then do bt <- newButton f cnf pack bt [Side AtLeft, PadX (cm 0.2), PadY (cm 0.1)] pack f (pcnf ++ [Side AtLeft, PadX (cm 0.2), PadY (cm 0.1)]) else do bt <- newButton b cnf pack bt (Side AtLeft : pcnf)) setRef em (el ++ [bt]) return bt)