{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE DeriveDataTypeable #-} -- | GetAttributes is used by the GraphEditor to pop up HTk windows -- to get information from the user. module Graphs.GetAttributes( NodeTypeAttributes(..), -- instance of Typeable getNodeTypeAttributes, -- :: IO (Maybe NodeTypeAttributes) NodeAttributes(..), -- instance of Typeable getNodeAttributes, -- :: IO (Maybe NodeAttributes) ArcTypeAttributes(..), -- instance of Typeable getArcTypeAttributes, -- :: IO (Maybe ArcTypeAttributes) ArcAttributes(..), -- instance of Typeable getArcAttributes, -- :: IO (Maybe ArcAttributes) displayError, -- :: String -> IO () ) where import Control.Exception import Util.Dynamics import Util.Registry hiding (getValue) import qualified Util.Registry as Registry (getValue) import Util.Messages import HTk.Toplevel.HTk hiding (Icon) import HTk.Toolkit.InputWin import HTk.Toolkit.InputForm import qualified Graphs.GraphConfigure as GraphConfigure ------------------------------------------------------------------------ -- NodeTypes ------------------------------------------------------------------------ data ShapeSort = Box | Circle | Ellipse | Rhombus | Triangle | Icon deriving (Enum,Read,Show) instance GUIValue ShapeSort where cdefault = Box data NodeTypeAttributes nodeLabel = NodeTypeAttributes { shape :: GraphConfigure.Shape nodeLabel, nodeTypeTitle :: String } deriving (Read,Show,Typeable) data PreAttributes = PreAttributes { shapeSort :: ShapeSort, nodeTypeTitle' :: String } getNodeTypeAttributes :: IO (Maybe(NodeTypeAttributes nodeLabel)) getNodeTypeAttributes = allowCancel ( do PreAttributes {shapeSort=shapeSort,nodeTypeTitle'=nodeTypeTitle} <- getNodeTypeAttributes1 shape <- case shapeSort of Box -> return GraphConfigure.Box Circle -> return GraphConfigure.Circle Ellipse -> return GraphConfigure.Ellipse Rhombus -> return GraphConfigure.Rhombus Triangle -> return GraphConfigure.Triangle Icon -> do fname <- getSingleString "Icon filename" return (GraphConfigure.Icon fname) return NodeTypeAttributes {shape=shape,nodeTypeTitle=nodeTypeTitle} ) getNodeTypeAttributes1 :: IO PreAttributes -- This returns the sort of shape + the node type title. getNodeTypeAttributes1 = do let def = PreAttributes {shapeSort=Box,nodeTypeTitle'=""} (iw, form) <- createInputWin "Node Type Attributes" (\p-> newInputForm p (Just def) []) [] newEnumField form [Box .. Icon] [ -- text "Node Shape", selector shapeSort, modifier (\ old newShape -> old {shapeSort = newShape}) ] newEntryField form [ text "Node Type title", selector nodeTypeTitle', modifier (\ old newTitle -> old {nodeTypeTitle' = newTitle}), width 20 ] result <- wait iw True case result of Just value -> return value Nothing -> cancelQuery ------------------------------------------------------------------------ -- Nodes ------------------------------------------------------------------------ data NodeAttributes nodeType = NodeAttributes { nodeType :: nodeType, nodeTitle :: String } deriving (Read,Show,Typeable) data NodePreAttributes = NodePreAttributes { preNodeType :: String, preNodeTitle :: String } deriving Show getNodeAttributes :: (Registry String nodeType) -> IO (Maybe (NodeAttributes nodeType)) -- getNodeAttributes gets the required attributes of a node given -- its possible types (with their titles). getNodeAttributes registry = allowCancel ( do knownTypeNames <- listKeys registry case knownTypeNames of [] -> do displayError "You must first define some node types" cancelQuery _ -> return () let def = NodePreAttributes { preNodeType=head knownTypeNames, preNodeTitle="" } -- iform p = newInputForm p (Just def) [] (inputWin, form) <- createInputWin "Node Attributes" (\p-> newInputForm p (Just def) []) [] newEnumField form knownTypeNames [ -- text "Node Type", selector preNodeType, modifier (\ old nodeTypeName -> old {preNodeType = nodeTypeName}) ] newEntryField form [ text "Node title", selector preNodeTitle, modifier (\ old newTitle -> old {preNodeTitle = newTitle}), width 20 ] result <- wait inputWin True case result of Just (NodePreAttributes { preNodeTitle = nodeTitle, preNodeType = nodeTypeName }) -> do nodeType <- Registry.getValue registry nodeTypeName return (NodeAttributes { nodeTitle = nodeTitle, nodeType = nodeType }) Nothing -> cancelQuery ) ------------------------------------------------------------------------ -- Arc Types ------------------------------------------------------------------------ data ArcTypeAttributes = ArcTypeAttributes { arcTypeTitle :: String } deriving (Read,Show,Typeable) getArcTypeAttributes :: IO (Maybe ArcTypeAttributes) getArcTypeAttributes = do let def = ArcTypeAttributes {arcTypeTitle=""} (iw, form) <- createInputWin "Arc Type Attributes" (\p-> newInputForm p (Just def) []) [] newEntryField form [ text "Arc Type title", selector arcTypeTitle, modifier (\ old newTitle -> old {arcTypeTitle = newTitle}), width 20 ] wait iw True ------------------------------------------------------------------------ -- Arcs ------------------------------------------------------------------------ data ArcAttributes arcType = ArcAttributes { arcType :: arcType } deriving (Read,Show,Typeable) data ArcPreAttributes = ArcPreAttributes { preArcType :: String } getArcAttributes :: (Registry String arcType) -> IO (Maybe (ArcAttributes arcType)) -- getArcAttributes gets the required attributes of an arc given -- its possible types (with their titles). getArcAttributes registry = allowCancel ( do knownTypeNames <- listKeys registry case knownTypeNames of [] -> do displayError "You must first define some arc types" cancelQuery _ -> return () let def = ArcPreAttributes { preArcType=head knownTypeNames } (iw, form) <- createInputWin "Arc Attributes" (\p-> newInputForm p (Just def) []) [] newEnumField form knownTypeNames [ -- text "Arc Type", selector preArcType, modifier (\ old arcTypeName -> old {preArcType = arcTypeName}) ] result <- wait iw True case result of Just (ArcPreAttributes { preArcType = arcTypeName }) -> do arcType <- Registry.getValue registry arcTypeName return (ArcAttributes { arcType = arcType }) Nothing -> cancelQuery ) ------------------------------------------------------------------------ -- General Routines ------------------------------------------------------------------------ displayError :: String -> IO () -- This displays an error message. displayError = errorMess getSingleString :: String -> IO String -- This gets a single string from the user, prompting with the argument -- provided. getSingleString query = do (inputWin, form) <- createInputWin "" (\p-> newInputForm p (Just "") []) [] (entryField :: EntryField String String) <- newEntryField form [ text query, selector id, modifier (\ oldValue newValue -> newValue), width 20 ] result <- wait inputWin True case result of Just value -> return value Nothing -> cancelQuery newtype CancelException = CancelException () deriving (Typeable) cancelQuery :: IO anything cancelQuery = throwDyn (CancelException ()) allowCancel :: IO a -> IO (Maybe a) allowCancel action = catchDyn (do result <- action return (Just result) ) (\ (CancelException ()) -> return Nothing)