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.Graph 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 = do modifyGraph (execGraph $ apply $ everywhere $ ruleList !! idx) globalVars menuClick _ _ _ _ = return ()