-- | This module provides an easy-to-use interface to create an interactive, graphical front-end for you graph rewriting system. The controls of the GUI are: -- -- - left-click on a menu entry: rule selection. At all times for each redex (according to the selected rule) one node of the redex (the first node that is matched) is marked red in the graph. -- -- - right-click on a menu entry: applies the rule once for each redex currently existing in the graph. No contractions take place for redexes deleted or arisen during this process. -- -- - right-click on a (red) node: applies the selected rule to the redex containing the node. -- -- - drag a node: by this you can manually help out the graph drawing mechanism to find a better layout. -- -- - drag outside of a node: scroll around. -- -- - mouse wheel: zoom -- -- - @z@: autozoom -- -- - @space@: pause/resume layouting -- -- Please have a look the graph-rewriting-ski package for an example application that makes use of this library. module GraphRewriting.GL.UI (module GraphRewriting.GL.UI, LabeledTree (..)) where import qualified Graphics.UI.GLUT as GL import Graphics.UI.GLUT (($=), get) import GraphRewriting.Graph import GraphRewriting.Graph.Read import GraphRewriting.Rule import Data.IORef import GraphRewriting.GL.Render import GraphRewriting.GL.Global import GraphRewriting.GL.HyperEdge import GraphRewriting.GL.Canvas import GraphRewriting.GL.Menu import GraphRewriting.Layout.RotPortSpec import Data.Set as Set import Control.Monad -- | Initialises GLUT. Returns program name and command line arguments. initialise ∷ IO (String, [String]) initialise = GL.getArgsAndInitialize -- | After initialisation 'run' can be used to start the GUI run ∷ (View [Port] n, Render n, View Position n, PortSpec n, View Rotation n) ⇒ Int -- ^ The number of layout steps to apply before displaying the graph → (Graph n → Graph n) -- ^ A projection function that is applied just before displaying the graph → Rewrite n a -- ^ The monadic graph transformation code for a layout step → Graph n → LabeledTree (Rule n) -- ^ The rule menu given as a tree of named rules → IO () run initSteps project layoutStep g rules = do globalVars ← newIORef $ GlobalVars {graph = execGraph (replicateM_ initSteps layoutStep) g, paused = False, selectedRule = fail "none", highlighted = Set.empty, layoutStep = layoutStep >> return (), canvas = undefined} -- print =<< get GL.sampleBuffers -- print =<< get GL.samples -- print =<< get GL.subpixelBits -- GL.initialDisplayCapabilities $= [GL.With GL.DisplayDouble, GL.With GL.DisplaySamples] -- GL.multisample $= GL.Enabled GL.initialDisplayMode $= [GL.DoubleBuffered, GL.Multisampling] p ← get GL.displayModePossible when (not p) $ do GL.initialDisplayMode $= [GL.DoubleBuffered] p ← get GL.displayModePossible when (not p) $ GL.initialDisplayMode $= [] c ← setupCanvas project star globalVars modifyIORef globalVars $ \v → v {canvas = c} setupMenu rules globalVars layoutLoop globalVars GL.mainLoop GL.exit