1 {-# LANGUAGE ScopedTypeVariables, TupleSections #-}
3 module RMCA.GUI.NoteSettings where
5 import Control.Concurrent.MVar
7 import Control.Monad.IO.Class
9 import qualified Data.Bifunctor as BF
14 import Data.ReactiveValue
17 import Graphics.UI.Gtk hiding (Action)
18 import Graphics.UI.Gtk.Board.TiledBoard hiding (Board)
19 import Graphics.UI.Gtk.Reactive
20 import RMCA.Auxiliary.RV
24 fromMaybeM_ :: (Monad m) => Maybe (m ()) -> m ()
25 fromMaybeM_ = fromMaybe (return ())
27 setNAttr :: NoteAttr -> Action -> Action
28 setNAttr _ Inert = Inert
29 setNAttr _ Absorb = Absorb
30 setNAttr na (Stop _) = Stop na
31 setNAttr na (ChDir b _ dir) = ChDir b na dir
32 setNAttr na (Split _) = Split na
34 getNAttr :: Action -> Maybe NoteAttr
35 getNAttr Inert = Nothing
36 getNAttr Absorb = Nothing
37 getNAttr (Stop na) = Just na
38 getNAttr (ChDir _ na _) = Just na
39 getNAttr (Split na) = Just na
41 noteList :: [(String, Duration)]
42 noteList = sortBy (comparing snd)
43 [ ("♩ quarter note", 1 % 4)
44 , ("♪ eighth note", 1 % 8)
45 , ("𝅗𝅥 half note", 1 % 2)
46 , ("𝅘𝅥𝅯 sixteenth note", 1 % 16)
50 comboBoxIndexRV :: (ComboBoxClass box) =>
51 box -> ReactiveFieldReadWrite IO Int
52 comboBoxIndexRV box = ReactiveFieldReadWrite setter getter notifier
53 where getter = comboBoxGetActive box
54 setter = comboBoxSetActive box
55 notifier = void . on box changed
57 clickHandling :: Array Pos (ReactiveFieldWrite IO GUICell)
58 -> IOBoard -> VBox -> IO VBox
59 clickHandling pieceArrRV board pieceBox = do
60 naBox <- vBoxNew False 10
61 boxPackStart pieceBox naBox PackNatural 10
64 artCombo <- comboBoxNewText
65 artIndex <- mapM (\art -> do i <- comboBoxAppendText artCombo
66 (fromString $ show art)
67 return (art,i)) [NoAccent ..]
68 comboBoxSetActive artCombo 0
69 boxPackStart naBox artCombo PackNatural 10
70 let indexToArt i = fromMaybe NoAccent $ lookup i $ map swap artIndex
71 artToIndex a = fromMaybe (-1) $ lookup a artIndex
72 artComboRV = bijection (indexToArt,artToIndex) `liftRW`
73 comboBoxIndexRV artCombo
76 slideCombo <- comboBoxNewText
77 slideIndex <- mapM (\sli -> do i <- comboBoxAppendText slideCombo
78 (fromString $ show sli)
79 return (sli,i)) [NoSlide ..]
80 comboBoxSetActive slideCombo 0
81 boxPackStart naBox slideCombo PackNatural 10
82 let indexToSlide i = fromMaybe NoSlide $ lookup i $ map swap slideIndex
83 slideToIndex s = fromMaybe (-1) $ lookup s slideIndex
84 slideComboRV = bijection (indexToSlide,slideToIndex) `liftRW`
85 comboBoxIndexRV slideCombo
88 noteDurCombo <- comboBoxNewText
89 noteDurIndex <- mapM (\(str,dur) -> do i <- comboBoxAppendText noteDurCombo
91 return (dur,i)) noteList
92 comboBoxSetActive noteDurCombo 0
93 boxPackStart naBox noteDurCombo PackNatural 10
94 let indexToDur i = fromMaybe (1 % 4) $ lookup i $ map swap noteDurIndex
95 durToIndex d = fromMaybe 0 $ lookup d noteDurIndex
96 noteDurRV = bijection (indexToDur, durToIndex) `liftRW`
97 comboBoxIndexRV noteDurCombo
100 rCountAdj <- adjustmentNew 1 0 10 1 1 0
101 rCount <- spinButtonNew rCountAdj 1 0
102 boxPackStart pieceBox rCount PackNatural 10
103 let rCountRV = spinButtonValueIntReactive rCount
106 -- Carries the index of the tile to display and what to display.
107 setRV <- newCBMVarRW ((0,0),inertCell)
109 reactiveValueOnCanRead noteDurRV $ do
110 nDur <- reactiveValueRead noteDurRV
111 (i,oCell) <- reactiveValueRead setRV
112 let nCa :: Maybe NoteAttr
113 nCa = (\na -> na { naDur = nDur }) <$> getNAttr (cellAction oCell)
115 nCell = if isJust nCa
116 then oCell { cellAction =
117 setNAttr (fromJust nCa) (cellAction oCell) }
119 reactiveValueWrite setRV (i,nCell)
120 reactiveValueWrite (pieceArrRV ! i) nCell
123 reactiveValueOnCanRead rCountRV $ do
124 nRCount <- reactiveValueRead rCountRV
125 (i,oCell) <- reactiveValueRead setRV
126 let nCell = oCell { repeatCount = nRCount }
127 reactiveValueWrite setRV (i,nCell)
128 reactiveValueWrite (pieceArrRV ! i) nCell
130 reactiveValueOnCanRead slideComboRV $ do
131 nSlide <- reactiveValueRead slideComboRV
132 (i,oCell) <- reactiveValueRead setRV
133 let nCa :: Maybe NoteAttr
134 nCa = (\na -> na { naOrn = (naOrn na) { ornSlide = nSlide } }) <$>
135 getNAttr (cellAction oCell)
137 nCell = if isJust nCa
138 then oCell { cellAction =
139 setNAttr (fromJust nCa) (cellAction oCell)
142 reactiveValueWrite setRV (i,nCell)
143 reactiveValueWrite (pieceArrRV ! i) nCell
145 reactiveValueOnCanRead artComboRV $ do
146 --nArt <- reactiveValueRead artComboRV
147 (i,oCell) <- reactiveValueRead setRV
148 let nCa :: Maybe NoteAttr
149 nCa = getNAttr $ cellAction oCell
151 nCell = if isJust nCa
152 then oCell { cellAction =
153 setNAttr (fromJust nCa) (cellAction oCell) }
155 reactiveValueWrite setRV (i,nCell)
156 reactiveValueWrite (pieceArrRV ! i) nCell
159 hideNa = do widgetHide slideCombo
162 widgetHide noteDurCombo
164 showNa = do widgetShow slideCombo
167 widgetShow noteDurCombo
168 updateNaBox :: GUICell -> IO ()
169 updateNaBox GUICell { cellAction = act } = case act of
174 state <- newEmptyMVar
176 (\iPos -> liftIO $ do
177 postGUIAsync $ void $ tryPutMVar state iPos
181 (\fPos -> liftIO $ do
183 mp <- boardGetPiece fPos board
184 mstate <- tryTakeMVar state
185 when (fPos `elem` validArea && isJust mp) $ do
186 let piece = snd $ fromJust mp
187 when (maybe False (== fPos) mstate) $
188 boardSetPiece fPos (BF.second rotateGUICell (Player,piece)) board
189 nmp <- boardGetPiece fPos board
191 when (isJust nmp) $ do
192 let nC = snd $ fromJust nmp
193 reactiveValueWrite setRV (fPos,nC)
194 fromMaybeM_ $ reactiveValueWrite artComboRV . naArt <$>
195 getNAttr (cellAction nC)
197 reactiveValueWrite slideComboRV . ornSlide . naOrn <$> getNAttr (cellAction nC)
198 reactiveValueWrite rCountRV $ repeatCount nC
199 fromMaybeM_ $ reactiveValueWrite noteDurRV . naDur <$>
200 getNAttr (cellAction nC)
204 reactiveValueOnCanRead setRV (reactiveValueRead setRV >>= updateNaBox . snd)