module Sifflet.Data.Functoid (Functoid(..) , functoidName, functoidArgNames, functoidHeader , FunctoidLayout(..), flayout , flayoutBBox, flayoutSize, flayoutWidth, flayoutBottom , flayoutWiden) where import Data.Graph.Inductive as G import Sifflet.Data.Geometry import Sifflet.Language.Expr import Sifflet.Data.TreeLayout -- | A Functoid is either a FunctoidParts, representing a partially -- defined function, or a (completely defined) Function. -- A FunctoidParts represents an incompletely defined function, -- which has a function name, argument names, and a list of graph nodes -- representing the function body which might not yet form -- a complete expression tree, e.g., nodes might -- be unconnected. data Functoid = FunctoidParts {fpName :: String, fpArgs :: [String], fpNodes :: [G.Node]} | FunctoidFunc {fpFunc :: Function} deriving (Show) functoidName :: Functoid -> String functoidName (FunctoidParts {fpName = name}) = name functoidName (FunctoidFunc function) = functionName function functoidArgNames :: Functoid -> [String] functoidArgNames (FunctoidParts {fpArgs = args}) = args functoidArgNames (FunctoidFunc function) = functionArgNames function functoidHeader :: Functoid -> String functoidHeader f = unwords (functoidName f : functoidArgNames f) -- | What is a FunctoidLayout? You can think of it as a -- tree layout for a Frame, -- or for a Functoid, or as a Forest of Tree Layouts! -- For an Edit frame, it must be a forest, since the nodes are not -- yet necessarily connected into a tree. -- For a call frame, it will be a single TreeLayout (singleton list). data FunctoidLayout = FLayoutTree (TreeLayout ExprNode) | FLayoutForest [TreeLayout ExprNode] BBox -- | Graphically lay out the Functoid. -- mvalues: Nothing implies an uncalled frame, -- Just values implies a called frame, even with 0 arguments. flayout :: Style -> Functoid -> Env -> Maybe [Value] -> FunctoidLayout flayout style functoid env mvalues = case functoid of FunctoidParts {} -> -- STUB: [] and bbox *** -- WELL: is this supposed to CREATE the tlo or RETRIEVE the tlo? -- Either way, it won't work without access to the WGraph! FLayoutForest [] (BBox (hpad style) (vpad style) 300 300) FunctoidFunc function -> let expr = functionBody function exprTree = case mvalues of Nothing -> exprToTree expr Just _values -> evalTree (exprToTree expr) env tlo = treeLayout style (exprNodeIoletCounter env) exprTree in FLayoutTree tlo flayoutBBox :: FunctoidLayout -> BBox flayoutBBox aflayout = case aflayout of FLayoutTree t -> layoutTreeBB t FLayoutForest _ bbox -> bbox flayoutSize :: FunctoidLayout -> Size flayoutSize = bbSize . flayoutBBox flayoutWidth :: FunctoidLayout -> Double flayoutWidth = bbWidth . flayoutBBox flayoutBottom :: FunctoidLayout -> Double flayoutBottom = bbBottom . flayoutBBox flayoutWiden :: FunctoidLayout -> Double -> FunctoidLayout flayoutWiden aflayout minWidth = case aflayout of FLayoutTree t -> FLayoutTree (treeLayoutWiden t minWidth) FLayoutForest f bbox -> FLayoutForest f bbox -- STUB *** instance Translate FunctoidLayout where translate dx dy fl = case fl of FLayoutTree t -> FLayoutTree (translate dx dy t) FLayoutForest f b -> FLayoutForest (translate dx dy f) (translate dx dy b)