module GraphRewriting.GL.Menu (LabeledTree (..), setupMenu) where import Prelude.Unicode 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 data LabeledTree a = Branch String [LabeledTree a] | Leaf String a flattenLT ∷ String → ([a] → a) → LabeledTree 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 menuItemHeight = 20 font = Fixed9By15 setupMenu ∷ LabeledTree (Rule n) → IORef (GlobalVars n) → IO () setupMenu rules globalVars = do c ← liftM canvas $ readIORef globalVars winWidth ← liftM (fromIntegral . maximum) (mapM (stringWidth font) ruleNames) let winSize = Size winWidth (fromIntegral $ menuItemHeight * n) menu ← createSubWindow c (GL.Position 0 0) winSize clearColor $= (Color4 1 1 1 0 ∷ Color4 GLclampf) GLUT.cursor $= GLUT.LeftArrow selectedIndex ← newIORef (0 ∷ Int) selectRule (ruleList !! 0) globalVars displayCallback $= (displayMenu =<< readIORef selectedIndex) keyboardMouseCallback $= Just (inputCallback $ menuClick menu selectedIndex) where (ruleNames, ruleList) = unzip $ snd $ flattenLT " " anyOf rules n = length ruleNames displayMenu selectedIndex = do clear [ColorBuffer] color (Color3 0 0 0 ∷ Color3 GLfloat) zipWithM_ displayLine ruleNames [0..] swapBuffers where displayLine name i = do if i ≡ selectedIndex 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) renderString font name inputCallback handler (MouseButton button) Up modifiers (Position x y) = do let idx = fromIntegral y `div` menuItemHeight when (0 <= idx ∧ idx < n) (handler button idx) inputCallback _ _ _ _ _ = return () menuClick menu selectedIndex LeftButton idx = do writeIORef selectedIndex idx selectRule (ruleList !! idx) globalVars postRedisplay $ Just menu menuClick menu selectedIndex RightButton idx = applyRule (everywhere $ ruleList !! idx) globalVars menuClick _ _ _ _ = return ()