packages feed

graph-rewriting-gl-0.6.9: GraphRewriting/GL/Menu.hs

module GraphRewriting.GL.Menu (LabelledTree (..), 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


menuItemHeight = 20
font = Fixed9By15

setupMenu ∷ LabelledTree (Rule n) → IORef (GlobalVars n) → IO ()
setupMenu rules 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
	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
	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
			gv <- readIORef globalVars
			if i ≡ selectedIndex 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)
			renderString font line

	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 globalVars LeftButton idx = do
		modifyIORef globalVars $ \x -> x {selectedIndex = idx}
		gv <- readIORef globalVars
		selectRule (ruleList !! idx) globalVars
		postRedisplay $ Just menu
	menuClick menu globalVars RightButton idx = do
		gv <- readIORef globalVars
		_ ← applyLeafRules idx globalVars
		-- TODO: update the resulting subtree
		highlight globalVars
--		applyRule (everywhere $ ruleList !! idx) globalVars
		postRedisplay $ Just menu
	menuClick _ _ _ _  = return ()