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 Data.IORef
import Control.Monad
import Data.Functor ()
import Control.Applicative ()
= Int
20
font :: BitmapFont
font = BitmapFont
Fixed9By15
setupMenu ∷ IORef (GlobalVars n) → IO ()
IORef (GlobalVars n)
globalVars = do
Window
c ← GlobalVars n -> Window
forall n. GlobalVars n -> Window
canvas (GlobalVars n -> Window) -> IO (GlobalVars n) -> IO Window
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IORef (GlobalVars n) -> IO (GlobalVars n)
forall a. IORef a -> IO a
readIORef IORef (GlobalVars n)
globalVars
RuleTree n
ruleTree ← GlobalVars n -> RuleTree n
forall n. GlobalVars n -> RuleTree n
getRules (GlobalVars n -> RuleTree n)
-> IO (GlobalVars n) -> IO (RuleTree n)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IORef (GlobalVars n) -> IO (GlobalVars n)
forall a. IORef a -> IO a
readIORef IORef (GlobalVars n)
globalVars
GLint
charWidth ← BitmapFont -> String -> IO GLint
forall a (m :: * -> *).
(Font a, MonadIO m) =>
a -> String -> m GLint
forall (m :: * -> *). MonadIO m => BitmapFont -> String -> m GLint
stringWidth BitmapFont
font String
"0"
let cols :: GLint
cols = Int -> GLint
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> GLint) -> Int -> GLint
forall a b. (a -> b) -> a -> b
$ [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (String -> Int) -> [String] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> [Int]) -> [String] -> [Int]
forall a b. (a -> b) -> a -> b
$ String -> [String]
lines (String -> [String]) -> String -> [String]
forall a b. (a -> b) -> a -> b
$ RuleTree n -> String
forall n. RuleTree n -> String
showRuleTree RuleTree n
ruleTree
let winWidth :: GLint
winWidth = (GLint
cols GLint -> GLint -> GLint
forall a. Num a => a -> a -> a
+ GLint
1) GLint -> GLint -> GLint
forall a. Num a => a -> a -> a
* GLint -> GLint -> GLint
forall a. Ord a => a -> a -> a
min GLint
10 GLint
charWidth
let ruleListLength :: Int
ruleListLength = RuleTree n -> Int
forall a. LabelledTree a -> Int
numNodes RuleTree n
ruleTree
let winSize :: Size
winSize = GLint -> GLint -> Size
Size GLint
winWidth (Int -> GLint
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> GLint) -> Int -> GLint
forall a b. (a -> b) -> a -> b
$ Int
menuItemHeight Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
ruleListLength)
Window
menu ← Window -> Position -> Size -> IO Window
forall (m :: * -> *).
MonadIO m =>
Window -> Position -> Size -> m Window
createSubWindow Window
c (GLint -> GLint -> Position
GL.Position GLint
0 GLint
0) Size
winSize
IORef (GlobalVars n) -> (GlobalVars n -> GlobalVars n) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef IORef (GlobalVars n)
globalVars ((GlobalVars n -> GlobalVars n) -> IO ())
-> (GlobalVars n -> GlobalVars n) -> IO ()
forall a b. (a -> b) -> a -> b
$ \GlobalVars n
x -> GlobalVars n
x {menu=menu}
StateVar (Color4 GLfloat)
clearColor StateVar (Color4 GLfloat) -> Color4 GLfloat -> IO ()
forall t a (m :: * -> *).
(HasSetter t a, MonadIO m) =>
t -> a -> m ()
forall (m :: * -> *).
MonadIO m =>
StateVar (Color4 GLfloat) -> Color4 GLfloat -> m ()
$= (GLfloat -> GLfloat -> GLfloat -> GLfloat -> Color4 GLfloat
forall a. a -> a -> a -> a -> Color4 a
Color4 GLfloat
1 GLfloat
1 GLfloat
1 GLfloat
0 ∷ Color4 GLclampf)
StateVar Cursor
GLUT.cursor StateVar Cursor -> Cursor -> IO ()
forall t a (m :: * -> *).
(HasSetter t a, MonadIO m) =>
t -> a -> m ()
forall (m :: * -> *).
MonadIO m =>
StateVar Cursor -> Cursor -> m ()
$= Cursor
GLUT.LeftArrow
Int -> IORef (GlobalVars n) -> IO ()
forall {n}. Int -> IORef (GlobalVars n) -> IO ()
selectRule Int
0 IORef (GlobalVars n)
globalVars
SettableStateVar (IO ())
displayCallback SettableStateVar (IO ()) -> IO () -> IO ()
forall t a (m :: * -> *).
(HasSetter t a, MonadIO m) =>
t -> a -> m ()
forall (m :: * -> *).
MonadIO m =>
SettableStateVar (IO ()) -> IO () -> m ()
$= IORef (GlobalVars n) -> IO ()
forall n. IORef (GlobalVars n) -> IO ()
displayMenu IORef (GlobalVars n)
globalVars
SettableStateVar (Maybe KeyboardMouseCallback)
keyboardMouseCallback SettableStateVar (Maybe KeyboardMouseCallback)
-> Maybe KeyboardMouseCallback -> IO ()
forall t a (m :: * -> *).
(HasSetter t a, MonadIO m) =>
t -> a -> m ()
forall (m :: * -> *).
MonadIO m =>
SettableStateVar (Maybe KeyboardMouseCallback)
-> Maybe KeyboardMouseCallback -> m ()
$= KeyboardMouseCallback -> Maybe KeyboardMouseCallback
forall a. a -> Maybe a
Just ((MouseButton -> Int -> IO ()) -> KeyboardMouseCallback
forall {m :: * -> *} {p}.
Monad m =>
(MouseButton -> Int -> m ())
-> Key -> KeyState -> p -> Position -> m ()
inputCallback ((MouseButton -> Int -> IO ()) -> KeyboardMouseCallback)
-> (MouseButton -> Int -> IO ()) -> KeyboardMouseCallback
forall a b. (a -> b) -> a -> b
$ Window -> IORef (GlobalVars n) -> MouseButton -> Int -> IO ()
forall {n}.
Window -> IORef (GlobalVars n) -> MouseButton -> Int -> IO ()
menuClick Window
menu IORef (GlobalVars n)
globalVars)
where
displayMenu :: IORef (GlobalVars n) -> IO ()
displayMenu IORef (GlobalVars n)
globalVars = do
GlobalVars n
gv <- IORef (GlobalVars n) -> IO (GlobalVars n)
forall a. IORef a -> IO a
readIORef IORef (GlobalVars n)
globalVars
[ClearBuffer] -> IO ()
clear [ClearBuffer
ColorBuffer]
Color3 GLfloat -> IO ()
forall a. Color a => a -> IO ()
color (GLfloat -> GLfloat -> GLfloat -> Color3 GLfloat
forall a. a -> a -> a -> Color3 a
Color3 GLfloat
0 GLfloat
0 GLfloat
0 ∷ Color3 GLfloat)
RuleTree n
ruleTree ← GlobalVars n -> RuleTree n
forall n. GlobalVars n -> RuleTree n
getRules (GlobalVars n -> RuleTree n)
-> IO (GlobalVars n) -> IO (RuleTree n)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IORef (GlobalVars n) -> IO (GlobalVars n)
forall a. IORef a -> IO a
readIORef IORef (GlobalVars n)
globalVars
let ruleListLength :: Int
ruleListLength = RuleTree n -> Int
forall a. LabelledTree a -> Int
numNodes RuleTree n
ruleTree
let displayLine :: String -> Int -> IO ()
displayLine String
line Int
i = do
GlobalVars n
gv <- IORef (GlobalVars n) -> IO (GlobalVars n)
forall a. IORef a -> IO a
readIORef IORef (GlobalVars n)
globalVars
if Int
i Int -> Int -> Bool
forall α. Eq α => α -> α -> Bool
≡ GlobalVars n -> Int
forall n. GlobalVars n -> Int
selectedRule GlobalVars n
gv
then Color3 GLfloat -> IO ()
forall a. Color a => a -> IO ()
GL.color (GLfloat -> GLfloat -> GLfloat -> Color3 GLfloat
forall a. a -> a -> a -> Color3 a
GL.Color3 GLfloat
1 GLfloat
0 GLfloat
0 ∷ GL.Color3 GL.GLfloat)
else Color3 GLfloat -> IO ()
forall a. Color a => a -> IO ()
GL.color (GLfloat -> GLfloat -> GLfloat -> Color3 GLfloat
forall a. a -> a -> a -> Color3 a
GL.Color3 GLfloat
0 GLfloat
0 GLfloat
0 ∷ GL.Color3 GL.GLfloat)
Vertex2 GLint -> IO ()
forall a. WindowPos a => a -> IO ()
windowPos (GLint -> GLint -> Vertex2 GLint
forall a. a -> a -> Vertex2 a
Vertex2 GLint
0 (Int -> GLint
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> GLint) -> Int -> GLint
forall a b. (a -> b) -> a -> b
$ (Int
ruleListLength Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
menuItemHeight Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
5) ∷ Vertex2 GLint)
BitmapFont -> String -> IO ()
forall a (m :: * -> *). (Font a, MonadIO m) => a -> String -> m ()
forall (m :: * -> *). MonadIO m => BitmapFont -> String -> m ()
renderString BitmapFont
font String
line
(String -> Int -> IO ()) -> [String] -> [Int] -> IO ()
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m ()
zipWithM_ String -> Int -> IO ()
displayLine (String -> [String]
lines (String -> [String]) -> String -> [String]
forall a b. (a -> b) -> a -> b
$ RuleTree n -> String
forall n. RuleTree n -> String
showRuleTree RuleTree n
ruleTree) [Int
0..]
IO ()
forall (m :: * -> *). MonadIO m => m ()
swapBuffers
inputCallback :: (MouseButton -> Int -> m ())
-> Key -> KeyState -> p -> Position -> m ()
inputCallback MouseButton -> Int -> m ()
handler (MouseButton MouseButton
button) KeyState
Up p
modifiers (Position GLint
x GLint
y) = do
let idx :: Int
idx = GLint -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GLint
y Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
menuItemHeight
MouseButton -> Int -> m ()
handler MouseButton
button Int
idx
inputCallback MouseButton -> Int -> m ()
_ Key
_ KeyState
_ p
_ Position
_ = () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
menuClick :: Window -> IORef (GlobalVars n) -> MouseButton -> Int -> IO ()
menuClick Window
menu IORef (GlobalVars n)
globalVars MouseButton
LeftButton Int
idx = do
IORef (GlobalVars n) -> (GlobalVars n -> GlobalVars n) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef IORef (GlobalVars n)
globalVars ((GlobalVars n -> GlobalVars n) -> IO ())
-> (GlobalVars n -> GlobalVars n) -> IO ()
forall a b. (a -> b) -> a -> b
$ \GlobalVars n
x -> GlobalVars n
x {selectedRule = idx}
GlobalVars n
gv <- IORef (GlobalVars n) -> IO (GlobalVars n)
forall a. IORef a -> IO a
readIORef IORef (GlobalVars n)
globalVars
Int -> IORef (GlobalVars n) -> IO ()
forall {n}. Int -> IORef (GlobalVars n) -> IO ()
selectRule Int
idx IORef (GlobalVars n)
globalVars
Window -> IO ()
redisplay Window
menu
menuClick Window
menu IORef (GlobalVars n)
globalVars MouseButton
RightButton Int
idx = do
GlobalVars n
gv <- IORef (GlobalVars n) -> IO (GlobalVars n)
forall a. IORef a -> IO a
readIORef IORef (GlobalVars n)
globalVars
()
_ ← (Rule n -> Rule n) -> Int -> IORef (GlobalVars n) -> IO ()
forall n.
(Rule n -> Rule n) -> Int -> IORef (GlobalVars n) -> IO ()
applyLeafRules Rule n -> Rule n
forall a. a -> a
id Int
idx IORef (GlobalVars n)
globalVars
IORef (GlobalVars n) -> IO ()
forall n. IORef (GlobalVars n) -> IO ()
highlight IORef (GlobalVars n)
globalVars
menuClick Window
_ IORef (GlobalVars n)
_ MouseButton
_ Int
_ = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()