graph-rewriting-gl 0.6.9 → 0.7
raw patch · 6 files changed
+153/−297 lines, 6 files
Files
- GraphRewriting/GL/Canvas.hs +5/−13
- GraphRewriting/GL/Global.hs +89/−214
- GraphRewriting/GL/Menu.hs +21/−25
- GraphRewriting/GL/Render.hs +1/−0
- GraphRewriting/GL/UI.hs +36/−44
- graph-rewriting-gl.cabal +1/−1
GraphRewriting/GL/Canvas.hs view
@@ -6,8 +6,8 @@ import Graphics.Rendering.OpenGL (($=)) import GraphRewriting.Graph import GraphRewriting.Graph.Read-import qualified GraphRewriting.Graph.Write.Unsafe as Unsafe import GraphRewriting.Pattern+import qualified GraphRewriting.Graph.Write.Unsafe as Unsafe import GraphRewriting.GL.Render import GraphRewriting.GL.Global import Data.IORef@@ -48,19 +48,12 @@ inputCallback (GL.MouseButton GL.RightButton) GL.Down mod pos = do pause globalVars- rule ← selectedRule <$> readIORef globalVars node ← nodeAt pos case node of Nothing → return () Just n → do- gv ← readIORef globalVars- idx ← getRuleIndex gv (nextIs n rule) (getRules gv)- case idx of- Nothing -> return ()- Just i -> do- let newRuleTree = branchSums $ increaseCounter 0 i 1 (getRules gv)- modifyIORef globalVars $ \x -> x {getRules = newRuleTree}- applyRule (nextIs n rule) globalVars+ _ ← (\idx → applyLeafRules (nextIs n) idx globalVars) =<< selectedRule <$> readIORef globalVars+ highlight globalVars inputCallback (GL.MouseButton GL.RightButton) GL.Up mod (GL.Position x y) = resume globalVars @@ -122,9 +115,8 @@ mapM_ (uncurry renderLine) (concatMap (uncurry hyperEdgeToLines) (edges g)) hl ← highlighted <$> readIORef globalVars mapM_ (renderNode hl) (evalGraph readNodeList g `zip` nodes g)- w ← liftM menu $ readIORef globalVars--- GL.currentWindow $= Just w- GL.postRedisplay (Just w) -- redisplay the menu subwindow+ w ← menu <$> readIORef globalVars+ redisplay w -- redisplay the menu subwindow GL.swapBuffers
GraphRewriting/GL/Global.hs view
@@ -11,9 +11,8 @@ import GraphRewriting.Layout.RotPortSpec import qualified Data.Set as Set import Data.Set (Set)-import Data.List ((\\), foldl')-import Control.Monad (when, replicateM, replicateM_)-import Data.Monoid+import Data.List ((\\))+import Control.Monad (when, replicateM_) import Data.Foldable import Data.Functor import Data.Traversable@@ -23,32 +22,47 @@ data GlobalVars n = GlobalVars {graph ∷ Graph n, paused ∷ Bool,- selectedRule ∷ Rule n,+ selectedRule ∷ Int, highlighted ∷ Set Node, layoutStep ∷ Node → Rewrite n (), canvas ∷ Window, menu ∷ Window,- getRules ∷ RuleTree n,- selectedIndex ∷ Int}+ getRules ∷ RuleTree n} data LabelledTree a = Branch String [LabelledTree a] | Leaf String a ---data LTZipper a = Root (LabelledTree a) | Child String [LabelledTree a] (LabelledTree a) [LabelledTree a]+data LTZipper a = Root | Child String [LabelledTree a] (LTZipper a) [LabelledTree a] ---forward ∷ LTZipper a → Maybe (LTZipper a)---forward (Root l) = ---forward (Child label ls child rs) = case child of--- Leaf {} → forwardHere--- Branch label' [ ] → forwardHere--- Branch label' (t:ts) → --- where--- forwardHere = case rs of--- [ ] → Nothing--- r:rs → Just $ Child label (ls ⧺ [child]) r rs--- [ ] → Nothing--- r:rs → Just $ Child label (ls ⧺ [child]) r rs---forward (Child label ls child@(Leaf {}) (r:rs)) = Just $ Child label (ls ⧺ [child]) r rs+type LTLoc a = (LabelledTree a, LTZipper a) +-- depth-first traversal+next ∷ LTLoc a → Maybe (LTLoc a)+next (Branch b (t:ts), p) = Just (t, Child b [] p ts)+next (Leaf l x, p) = right (Leaf l x, p)+next _ = Nothing++nth ∷ Int → LTLoc a → Maybe (LTLoc a)+nth n l = iterate (>>= next) (Just l) !! n++right ∷ LTLoc a → Maybe (LTLoc a)+right (t, Child c ls p (r:rs)) = Just (r, Child c (ls ⧺ [t]) p rs)+right (t, Child c ls p []) = up (t, Child c ls p []) >>= right+right _ = Nothing++up ∷ LTLoc a → Maybe (LTLoc a)+up (t, Child c ls p rs) = Just (Branch c (ls ⧺ [t] ⧺ rs), p)+up _ = Nothing++put ∷ LTLoc a → LabelledTree a → LTLoc a+put (_, p) t = (t, p)++top ∷ LTLoc a → LTLoc a+top (t, Root) = (t, Root)+top (t, Child c ls p rs) = top (Branch c (ls ⧺ [t] ⧺ rs), p)++root ∷ LabelledTree a → LTLoc a+root t = (t, Root)+ instance Foldable LabelledTree where foldr f y (Leaf l x) = f x y foldr f y (Branch l ts) = foldr (flip $ foldr f) y ts@@ -62,49 +76,29 @@ traverse f (Branch l ts) = Branch l <$> traverse (traverse f) ts showRuleTree ∷ RuleTree n → String-showRuleTree t = show $ fmap (\(n,r) → n) t--- indentation = 2--- srt t = case t of--- Leaf l x → (x, l ⧺ " " ⧺ show x)--- Branch l ts → (x, l ⧺ " " ⧺ show x ⧺ concatMap indent lines) where--- (xs, lines) = unzip $ map srt ts--- x = mconcat xs--- indent line = "\n" ⧺ replicate indentation ' ' ⧺ line--instance Show a ⇒ Show (LabelledTree a) where- show (Leaf l x) = l ⧺ " " ⧺ show x- show (Branch l s) = l ⧺ " " ⧺ unlines (map (indent . show) s)- where indent str = replicate 2 ' ' ⧺ str+showRuleTree = showLabelledTree 2 0 (+) . fmap fst --- two labeled trees are equal iff their labels and counters are equal---instance Eq (LabelledTree (Rule n)) where--- Leaf l1 r1 c1 == Leaf l2 r2 c2 = l1 == l2 && c1 == c2--- Branch l1 c1 rs1 == Branch l2 c2 rs2 = l1 == l2 && c1 == c2 && and (zipWith (==) rs1 rs2)--- _ == _ = False+showLabelledTree ∷ Show a ⇒ Int → a → (a → a → a) → LabelledTree a → String+showLabelledTree indentation init combine = snd . rec where --- (Pattern n a, [(String, Pattern n a)]) -→ ruleList ∷ [Pattern n a]---flattenLT ∷ String → ([a] → a) → LabelledTree a → (a,[(String, a)])---flattenLT indent combine tree = case tree of--- Leaf l x c → (x,[(l,x)])--- Branch b c cs → (x, (b,x) : zip (Prelude.map (indent ⧺) strs) ys) where--- x = combine xs--- (xs,css) = unzip $ Prelude.map (flattenLT indent combine) cs--- (strs,ys) = unzip $ concat css+ rec (Leaf l x) = (x, l ⧺ " " ⧺ show x)+ rec (Branch l ts) = (x, l ⧺ " " ⧺ show x ⧺ "\n" ⧺ indent (unlines ls)) where+ x = foldr combine init xs+ (xs, ls) = unzip $ map rec ts -flattenLT ∷ String → ([a] → a) → LabelledTree a → (a,[(String, a)])-flattenLT indent combine tree = case tree of- Leaf l x → (x,[(l,x)])- Branch b cs → (x, (b,x) : zip (map (indent ⧺) strs) ys) where- x = combine xs- (xs,css) = unzip $ map (flattenLT indent combine) cs- (strs,ys) = unzip $ concat css+ indent str = unlines $ map (replicate indentation ' ' ⧺) (lines str) + unlines [] = ""+ unlines [x] = x+ unlines xs = head xs ⧺ "\n" ⧺ unlines (tail xs) --- | Useful for benchmarking. Print the flattened counters of the rule tree, separated--- by tabs, so that the numbers can be pasted directly into several cells of a spreadsheet.-showFlatTabs ∷ Show a ⇒ LabelledTree a → String-showFlatTabs (Leaf l x) = show l ⧺ "\t"-showFlatTabs (Branch l s) = show l ⧺ "\t" ⧺ concatMap showFlatTabs s+instance Show a ⇒ Show (LabelledTree a) where+ show (Leaf l x) = l ⧺ " " ⧺ show x+ show (Branch l s) = l ⧺ "\n" ⧺ indent (unlines $ map show s) where+ indent str = unlines $ map (replicate 2 ' ' ⧺) (lines str)+ unlines [] = ""+ unlines [x] = x+ unlines xs = head xs ⧺ "\n" ⧺ unlines (tail xs) redisplay ∷ Window → IO () redisplay = postRedisplay . Just@@ -114,7 +108,6 @@ modifyGraph f globalVars = do modifyIORef globalVars $ \v → v {graph = f $ graph v}--- highlight globalVars -- this doesn't work with the command line benchmarking applyRule ∷ Rule n → IORef (GlobalVars n) → IO () applyRule r globalVars = do@@ -128,12 +121,17 @@ writeGraph (execGraph (replicateM_ 15 $ mapM layout newNodes) g') globalVars highlight globalVars -selectRule r globalVars = do- modifyIORef globalVars $ \v → v {selectedRule = r}- highlight globalVars+selectRule i globalVars = do+ ruleListLength ← numNodes <$> getRules <$> readIORef globalVars+ if 0 ≤ i ∧ i < ruleListLength+ then do+ modifyIORef globalVars $ \v → v {selectedRule = i}+ highlight globalVars+ else return () highlight globalVars = do- gv@GlobalVars {graph = g, selectedRule = rule, highlighted = h, canvas = c} ← readIORef globalVars+ gv@GlobalVars {graph = g, getRules = rs, selectedRule = r, highlighted = h, canvas = c} ← readIORef globalVars+ let rule = fold $ fmap snd (subtrees rs !! r) let h' = Set.fromList [head match | (match,rewrite) ← runPattern rule g] writeIORef globalVars $ gv {highlighted = h'} redisplay c@@ -152,174 +150,51 @@ modifyIORef globalVars $ \vs → vs {paused = False} layoutLoop globalVars --- | Increases the counter of a Leaf or Branch at the given index by nn-increaseCounter ∷ Int → Int → Int → LabelledTree (a,Int) → LabelledTree (a,Int)-increaseCounter = undefined---increaseCounter i idx nn (Leaf n r c) | i == idx = Leaf n r (c+nn)--- | otherwise = Leaf n r c---increaseCounter i idx nn (Branch n c rs) | i == idx = Branch n (c+nn) rs--- | otherwise = Branch n c $ increaseCounter' (i+1) idx nn rs------increaseCounter' ∷ Int → Int → Int → [LabelledTree a] → [LabelledTree a]---increaseCounter' i idx nn [] = []---increaseCounter' i idx nn (Leaf n r c:rs) | i == idx = Leaf n r (c+nn) : rs--- | otherwise = Leaf n r c : increaseCounter' (i+1) idx nn rs---increaseCounter' i idx nn (b@(Branch n c rss):rs) | i == idx = Branch n (c+nn) rss : rs--- | otherwise = Branch n c (increaseCounter' (i+1) idx nn rss)--- : increaseCounter' (i + nrnodes) idx nn rs--- where nrnodes = length (flattenedLT b)- subtrees ∷ LabelledTree a → [LabelledTree a] subtrees t = t : case t of Leaf _ _ → [] Branch l ts → concatMap subtrees ts ---subtree' i (Branch l s) = ---subtree' i (l@(Leaf n r c):rs) | i == idx = Right l--- | otherwise = subtree' (i+1) idx rs---subtree' i idx (b@(Branch n c rss):rs) | i == idx = Right b--- | otherwise = case subtree' (i+1) idx rss of--- Left i → subtree' i idx rs -- we already increased i earlier here--- Right t → Right t---- | Given a list of matches (i.e. [[Node]]) it will pick all matches if none of--- its nodes has been picked before-filterOverlaps ∷ [Match] → Set Match-filterOverlaps = Set.fromList . snd . foldr add (Set.empty, []) where- add m (ns, ms) = if any (`Set.member` ns) m then (ns, ms) else (foldr Set.insert ns m, m:ms)----applyLeafRule ∷ Int → [Match] → IORef (GlobalVars n) → LabelledTree (Rule n) → IO ()---applyLeafRule idx ms gvs (Leaf n r c) = do--- gv ← readIORef gvs--- layout ← liftM layoutStep $ readIORef gvs--- g ← readGraph gvs--- let ns = evalGraph readNodeList g--- let redexes = head $ evalPattern (amnesia $ matches r) (graph gv)--- nonOverlappingMatches = [m | m ← filterOverlaps redexes, m `elem` ms]--- nrMatched = length nonOverlappingMatches--- newRuleTree = branchSums $ increaseCounter 0 idx nrMatched (getRules gv)--- g' = execGraph (apply $ exhaustive $ restrictOverlap (\past future → future `elem` nonOverlappingMatches) r) g--- modifyIORef gvs $ \x → x {getRules = newRuleTree}--- let ns' = evalGraph readNodeList g'--- let newNodes = ns' Data.List.\\ ns--- writeGraph (execGraph (replicateM_ 15 $ mapM layout newNodes) g') gvs---applyLeafRule idx ms gvs (Branch n c rs) = return ()+numNodes ∷ LabelledTree a → Int+numNodes = length . subtrees type RuleTree n = LabelledTree (Int, Rule n) -- | Traverses the rule tree depth-first and executes all leaf rules it encounters. Rules are -- executed everywhere they match, except if they overlap one of them is chosen at random. -- So this corresponds to a complete development.-applyLeafRules ∷ Int → IORef (GlobalVars n) → IO ()-applyLeafRules idx gvs = do+applyLeafRules ∷ (Rule n → Rule n) → Int → IORef (GlobalVars n) → IO ()+applyLeafRules restriction idx gvs = do g ← readGraph gvs comptree ← getRules <$> readIORef gvs- let trees = subtrees comptree- if not $ 0 ≤ idx ∧ idx < length trees- then return ()- else do- let tree = trees !! idx+ let pos = nth idx (root comptree)+ case pos of+ Nothing → return ()+ Just (tree,p) → do let ns = evalGraph readNodeList g- let rule = fold $ fmap snd tree- let nonOverlappingMatches = filterOverlaps $ head $ evalPattern (matches rule) g- let ((_, g'), tree') = mapAccumR applyLeafRules' (nonOverlappingMatches, g) tree+ -- first we mark all redexes+ let rule = restriction $ fold $ fmap snd tree+ -- then we find a non-overlapping subset+ let ms = head $ evalPattern (matches rule) g+ -- then we apply the rules in the leafs while restricting them to that subset+ let ((_, g'), tree') = mapAccumL applyLeafRules' (ms, g) tree let ns' = evalGraph readNodeList g' let newNodes = ns' Data.List.\\ ns layout ← layoutStep <$> readIORef gvs writeGraph (execGraph (replicateM_ 15 (mapM layout newNodes)) g') gvs- modifyIORef gvs $ \x → x {getRules = insertTree idx tree tree'}--insertTree ∷ Int → LabelledTree a → LabelledTree a → LabelledTree a-insertTree pos tree tree' = tree---insertTree pos subtree tree = case insert' pos tree of--- Left pos' → tree--- Right res → res--- where--- insert' 0 t = Right subtree--- insert' p t = case t of--- Leaf l x → Left (p+1)--- Branch l [] → Left p--- Branch l ts → case muh ts (Left p) of--- Left p' → Left p'--- Right ts' → Right $ Branch l ts'--- where--- muh ∷ [LabelledTree a] → Either Int [LabelledTree a] → Either Int [LabelledTree a]--- muh [] (Left p) = Left p--- muh (t:ts) (Left p) = case insert' p t of--- Left p' → --- Right t' → Right $ t'--- muh t (Left p) = insert' p t---- At every leaf apply the rule restricted to the set of predetermined matches, every time removing the--- the match from the set updating the graph and the counter.-applyLeafRules' ∷ (Set Match, Graph n) → (Int, Rule n) → ((Set Match, Graph n), (Int, Rule n))-applyLeafRules' (matches, g) (n, r) = let- ms = runPattern r' g- r' = restrictOverlap (\past future → future `elem` matches) r- in if null ms- then ((matches, g), (n, r))- else let- (match, rewrite) = head ms- g' = execGraph rewrite g- in applyLeafRules' (Set.delete match matches, g') (n+1, r)----applyLeafRules' idx ms gvs (l@(Leaf n r c):rs) = do--- applyLeafRule idx ms gvs l--- applyLeafRules' (idx+1) ms gvs rs---applyLeafRules' idx ms gvs (b@(Branch n c rss):rs) = do--- selIdx ← applyLeafRules' (idx+1) ms gvs rss -- get the last index in a subtree--- applyLeafRules' selIdx ms gvs rs---applyLeafRules' idx ms gvs [] = return idx---- | Flattens the LabelledTree into a list of its nodes, where the branch nodes have--- empty lists attached to them---flattenedLT ∷ LabelledTree a → [LabelledTree a]---flattenedLT l@(Leaf n r c) = [l]---flattenedLT (Branch n c rs) = Branch n c [] : concatMap flattenedLT rs----branchSums ∷ LabelledTree a → LabelledTree a---branchSums l@(Leaf n r c) = l---branchSums (Branch n c rs) = Branch n (sum $ childCounters rs) (Prelude.map branchSums rs)----childCounters ∷ [LabelledTree a] → [Int]---childCounters [] = []---childCounters ((Leaf n r c):rs) = c : childCounters rs---childCounters ((Branch n c rss):rs) = sum (childCounters rss) : childCounters rs---- | Looks up the index of a given leaf rule in the rule tree.---getRuleIndex ∷ GlobalVars n → Rule n → LabelledTree (Rule n) → IO (Maybe Int)---getRuleIndex gvs rl l = getRuleIndex' 0 gvs rl l+ modifyIORef gvs $ \x → x {getRules = fst $ top (tree',p)} ---getRuleIndex' ∷ Int → GlobalVars n → Rule n → LabelledTree (Rule n) → IO (Maybe Int)---getRuleIndex' idx gvs rl (Leaf n r c) = do--- let rlMatches = getMatches rl gvs--- rMatches = getMatches r gvs--- if Prelude.null rlMatches--- then return Nothing--- else if head rlMatches `elem` rMatches--- then return (Just idx)--- else return Nothing---getRuleIndex' idx gvs rl (Branch n c rs) = do--- selIdx ← getRuleIndex'' (idx+1) gvs rl rs--- case selIdx of--- Left _ → return Nothing--- Right i → return (Just i)+ where ---getRuleIndex'' ∷ Int → GlobalVars n → Rule n → [LabelledTree (Rule n)] → IO (Either Int Int)---getRuleIndex'' idx gvs rl [] = return (Left idx)---getRuleIndex'' idx gvs rl ((Leaf n r c):rs) = do--- let rlMatches = getMatches rl gvs--- rMatches = getMatches r gvs--- if Prelude.null rlMatches--- then return (Left idx)--- else if head rlMatches `elem` rMatches--- then return (Right idx)--- else getRuleIndex'' (idx+1) gvs rl rs---getRuleIndex'' idx gvs rl ((Branch n c rss):rs) = do--- selIdx ← getRuleIndex'' (idx+1) gvs rl rss--- case selIdx of--- Left i → getRuleIndex'' i gvs rl rs--- Right i → return (Right i)------getMatches ∷ Rule n → GlobalVars n → [Match]---getMatches r gvs = Prelude.map fst $ snd $ head $ runPattern (amnesia $ match r) (graph gvs)+ -- At every leaf apply the rule restricted to the set of predetermined matches, every time removing the+ -- the match from the set updating the graph and the counter.+-- applyLeafRules' ∷ ([Match], Graph n) → (Int, Rule n) → (([Match], Graph n), (Int, Rule n))+ applyLeafRules' (matches, g) (n, r) = let+ ms = runPattern r' g+ r' = restrictOverlap (\past future → future `elem` matches) (restriction r)+ in if null ms+ then ((matches, g), (n, r))+ else let+ (match, rewrite) = head ms+ g' = execGraph rewrite g+ in applyLeafRules' (filter (\m → not $ any (`elem` match) m) matches, g') (n + 1, r)
GraphRewriting/GL/Menu.hs view
@@ -4,64 +4,60 @@ import Graphics.UI.GLUT as GLUT import qualified Graphics.Rendering.OpenGL as GL import GraphRewriting.GL.Global-import GraphRewriting.Rule import Data.IORef-import GraphRewriting.Pattern import Control.Monad+import Data.Functor+import Control.Applicative menuItemHeight = 20 font = Fixed9By15 -setupMenu ∷ LabelledTree (Rule n) → IORef (GlobalVars n) → IO ()-setupMenu rules globalVars = do+setupMenu ∷ IORef (GlobalVars n) → IO ()+setupMenu globalVars = do c ← liftM canvas $ readIORef globalVars- winWidth ← liftM fromIntegral (stringWidth font $ showRuleTree ruleTree)- let winSize = Size (winWidth + 60) (fromIntegral $ menuItemHeight * n) -- a little wider to display counters+ ruleTree ← getRules <$> readIORef globalVars+ winWidth ← liftM fromIntegral <$> (+) <$> (stringWidth font $ showRuleTree ruleTree) <*> stringWidth font "0"+ let ruleListLength = numNodes ruleTree+ let winSize = Size winWidth (fromIntegral $ menuItemHeight * ruleListLength) menu ← createSubWindow c (GL.Position 0 0) winSize modifyIORef globalVars $ \x -> x {menu=menu} -- set the menu subwindow clearColor $= (Color4 1 1 1 0 ∷ Color4 GLclampf) GLUT.cursor $= GLUT.LeftArrow- selectRule (ruleList !! 0) globalVars+ selectRule 0 globalVars displayCallback $= displayMenu globalVars keyboardMouseCallback $= Just (inputCallback $ menuClick menu globalVars) where - ruleTree = fmap (\r → (0,r)) rules-- (ruleNames, ruleList) = unzip $ snd $ flattenLT " " anyOf rules- n = length ruleNames- displayMenu globalVars = do gv <- readIORef globalVars clear [ColorBuffer] color (Color3 0 0 0 ∷ Color3 GLfloat)- zipWithM_ displayLine (lines $ showRuleTree ruleTree) [0..]- swapBuffers- where displayLine line i = do -- display one line of the menu+ ruleTree ← getRules <$> readIORef globalVars+ let ruleListLength = numNodes ruleTree+ let displayLine line i = do -- display one line of the menu gv <- readIORef globalVars- if i ≡ selectedIndex gv+ if i ≡ selectedRule gv then GL.color (GL.Color3 1 0 0 ∷ GL.Color3 GL.GLfloat) else GL.color (GL.Color3 0 0 0 ∷ GL.Color3 GL.GLfloat)- windowPos (Vertex2 0 (fromIntegral $ (n - i - 1) * menuItemHeight + 5) ∷ Vertex2 GLint)+ windowPos (Vertex2 0 (fromIntegral $ (ruleListLength - i - 1) * menuItemHeight + 5) ∷ Vertex2 GLint) renderString font line+ zipWithM_ displayLine (lines $ showRuleTree ruleTree) [0..]+ swapBuffers inputCallback handler (MouseButton button) Up modifiers (Position x y) = do let idx = fromIntegral y `div` menuItemHeight- when (0 <= idx ∧ idx < n) (handler button idx)+ handler button idx inputCallback _ _ _ _ _ = return () menuClick menu globalVars LeftButton idx = do- modifyIORef globalVars $ \x -> x {selectedIndex = idx}+ modifyIORef globalVars $ \x -> x {selectedRule = idx} gv <- readIORef globalVars- selectRule (ruleList !! idx) globalVars- postRedisplay $ Just menu+ selectRule idx globalVars+ redisplay menu menuClick menu globalVars RightButton idx = do gv <- readIORef globalVars- _ ← applyLeafRules idx globalVars- -- TODO: update the resulting subtree+ _ ← applyLeafRules id idx globalVars highlight globalVars--- applyRule (everywhere $ ruleList !! idx) globalVars- postRedisplay $ Just menu menuClick _ _ _ _ = return ()
GraphRewriting/GL/Render.hs view
@@ -29,6 +29,7 @@ vertex2 ∷ (Double,Double) → IO () vertex2 (x,y) = GL.vertex $ GL.Vertex2 (convertDouble x) (convertDouble y) +renderString ∷ String → IO () renderString label = GL.preservingMatrix $ do GL.translate $ vector2 (-0.3,-0.3) GL.scale 0.007 0.007 (0 ∷ GL.GLdouble)
GraphRewriting/GL/UI.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE UnicodeSyntax, FlexibleContexts #-} -- | 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 as follows: -- -- - Left-click on a menu entry to /select/ a rewriting rule. At all times all redexes with respect to the selected rule are marked red in the graph. Note that the menu is hierarchical, which means that selecting a rule that has subordinate entries has the effect of all these entries being selected.@@ -15,7 +16,7 @@ -- - Press space to pause/resume layouting. Currently layouting is automatically resumed when the graph is rewritten by right-clicking on an individual node and not when right-clicking on a menu entry. This also requires the mouse cursor to be positioned in the canvas area. -- -- 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+module GraphRewriting.GL.UI (module GraphRewriting.GL.UI, LabelledTree (..)) where import qualified Graphics.UI.GLUT as GL import Graphics.UI.GLUT (($=), get)@@ -41,62 +42,53 @@ → (Graph n → Graph n') -- ^ A projection function that is applied just before displaying the graph → (Node → 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+ → LabelledTree (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 $ mapM layoutStep =<< readNodeList) g, paused = False,- selectedRule = fail "none",+ selectedRule = 0, highlighted = Set.empty, layoutStep = \n → layoutStep n >> return (), canvas = undefined, menu = undefined,- getRules = rules,- selectedIndex = 0}+ getRules = fmap (\r → (0,r)) rules} -- command line benchmarking- file <- case args of- ("--bench":f:[]) -> do- gvs <- readIORef globalVars- finalTree <- reduceAll globalVars (graph gvs) rules+-- gvs <- readIORef globalVars+-- finalTree <- reduceAll globalVars (graph gvs) rules -- putStrLn ("Nr of reductions to normal form:\n" ++ showIndent 0 finalTree) -- (getTopCounter finalTree))- putStrLn $ showFlatTabs finalTree- _ -> do- GL.initialDisplayMode $= [GL.DoubleBuffered, GL.Multisampling]--- print =<< get GL.sampleBuffers--- print =<< get GL.samples--- print =<< get GL.subpixelBits+-- putStrLn $ showFlatTabs finalTree+ GL.initialDisplayMode $= [GL.DoubleBuffered, GL.Multisampling]+-- 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- 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 -- creates the window, registers callbacks- modifyIORef globalVars $ \v → v {canvas = c}- setupMenu rules globalVars- layoutLoop globalVars- GL.mainLoop- GL.exit+-- GL.initialDisplayCapabilities $= [GL.With GL.DisplayDouble, GL.With GL.DisplaySamples]+-- GL.multisample $= GL.Enabled+ 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 -- creates the window, registers callbacks+ modifyIORef globalVars $ \v → v {canvas = c}+ setupMenu globalVars+ layoutLoop globalVars+ GL.mainLoop+ GL.exit return () -reduceAll :: IORef (GlobalVars n) -> Graph n -> LabeledTree (Rule n) -> IO (LabeledTree (Rule n))-reduceAll globalVars g ruleTree = do- let ns = evalGraph readNodeList g- applyLeafRules 0 globalVars ruleTree- gvs <- readIORef globalVars- let g' = graph gvs- ruleTree' = getRules gvs- ns' = evalGraph readNodeList g'- if ruleTree == ruleTree'- then return ruleTree'- else reduceAll globalVars g' ruleTree'--getTopCounter :: LabeledTree (Rule n) -> Int-getTopCounter (Leaf n r c) = c-getTopCounter (Branch n c rs) = c-+--reduceAll :: IORef (GlobalVars n) -> Graph n -> RuleTree n -> IO (RuleTree n)+--reduceAll globalVars g ruleTree = do+-- let ns = evalGraph readNodeList g+-- applyLeafRules 0 globalVars+-- gvs <- readIORef globalVars+-- let g' = graph gvs+-- ruleTree' = getRules gvs+-- ns' = evalGraph readNodeList g'+-- if ruleTree == ruleTree'+-- then return ruleTree'+-- else reduceAll globalVars g' ruleTree'
graph-rewriting-gl.cabal view
@@ -1,5 +1,5 @@ Name: graph-rewriting-gl-Version: 0.6.9+Version: 0.7 Copyright: (c) 2010, Jan Rochel License: BSD3 License-File: LICENSE