1 {-# LANGUAGE ScopedTypeVariables, TupleSections, FlexibleContexts #-}
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 symbolString :: [(Duration,String)]
42 symbolString = map (\(_,y,z) -> (z,y)) noteSymbList
44 noteList :: [(String,Duration)]
45 noteList = map (\(x,_,y) -> (x,y)) noteSymbList
47 noteSymbList :: [(String, String, Duration)]
48 noteSymbList = sortBy (comparing (\(_,_,x) -> x))
49 [ ("♩", "Quarter note", 1 % 4)
50 , ("♪", "Eighth note ", 1 % 8)
51 , ("𝅗𝅥", "Half note", 1 % 2)
52 , ("𝅘𝅥𝅯", "Sixteenth note", 1 % 16)
53 , ("𝅝", "Whole note", 1)
56 comboBoxIndexRV :: (ComboBoxClass box) =>
57 box -> ReactiveFieldReadWrite IO Int
58 comboBoxIndexRV box = ReactiveFieldReadWrite setter getter notifier
59 where getter = comboBoxGetActive box
60 setter = comboBoxSetActive box
61 notifier = void . on box changed
63 clickHandling :: (ReactiveValueWrite cell GUICell IO) =>
65 -> IOBoard -> VBox -> IO VBox
66 clickHandling pieceArrRV board pieceBox = do
67 naBox <- vBoxNew False 10
68 boxPackStart pieceBox naBox PackNatural 10
71 artCombo <- comboBoxNewText
72 artIndex <- mapM (\art -> do i <- comboBoxAppendText artCombo
73 (fromString $ show art)
74 return (art,i)) [NoAccent ..]
75 comboBoxSetActive artCombo 0
76 boxPackStart naBox artCombo PackNatural 10
77 let indexToArt i = case lookup i $ map swap artIndex of
78 Nothing -> error "In indexToArt: failed \
79 \to find the selected articulation."
81 artToIndex a = case lookup a artIndex of
82 Nothing -> error "In artToIndex: failed \
83 \to find the correct index for the articulation."
85 artComboRV = bijection (indexToArt,artToIndex) `liftRW`
86 comboBoxIndexRV artCombo
89 slideCombo <- comboBoxNewText
90 slideIndex <- mapM (\sli -> do i <- comboBoxAppendText slideCombo
91 (fromString $ show sli)
92 return (sli,i)) [NoSlide ..]
93 comboBoxSetActive slideCombo 0
94 boxPackStart naBox slideCombo PackNatural 10
95 let indexToSlide i = case lookup i $ map swap slideIndex of
96 Nothing -> error "In indexToSlide: failed\
97 \to find the correct slide for the selected index."
99 slideToIndex s = case lookup s slideIndex of
100 Nothing -> error "In slideToIndex: failed\
101 \to find the correct index for the slide."
103 slideComboRV = bijection (indexToSlide,slideToIndex) `liftRW`
104 comboBoxIndexRV slideCombo
107 noteDurBox <- hBoxNew False 10
108 noteDurCombo <- comboBoxNewText
109 noteDurIndex <- mapM (\(str,dur) -> do i <- comboBoxAppendText noteDurCombo
111 return (dur,i)) noteList
112 comboBoxSetActive noteDurCombo 0
113 let indexToDur i = case lookup i $ map swap noteDurIndex of
114 Nothing -> error "In indexToDur: failed\
115 \to find the correct duration for the selected index."
117 durToIndex d = case lookup d noteDurIndex of
118 Nothing -> error "In durToIndex: failed\
119 \to find the correct index for the duration."
121 noteDurRV = bijection (indexToDur, durToIndex) `liftRW`
122 comboBoxIndexRV noteDurCombo
123 noteDurLabel <- labelNew =<< (\d -> lookup d symbolString) <$> reactiveValueRead noteDurRV
124 let noteDurLabelRV = labelTextReactive noteDurLabel
125 boxPackStart naBox noteDurBox PackNatural 10
126 boxPackStart noteDurBox noteDurCombo PackNatural 10
127 boxPackStart noteDurBox noteDurLabel PackNatural 10
130 rCountAdj <- adjustmentNew 1 0 100 1 1 0
131 rCount <- spinButtonNew rCountAdj 1 0
132 boxPackStart pieceBox rCount PackNatural 10
133 let rCountRV = spinButtonValueIntReactive rCount
136 -- Carries the index of the tile to display and what to display.
137 setRV <- newCBMVarRW ((0,0),inertCell)
139 reactiveValueOnCanRead noteDurRV $ do
140 nDur <- reactiveValueRead noteDurRV
141 (i,oCell) <- reactiveValueRead setRV
142 let nCa :: Maybe NoteAttr
143 nCa = (\na -> na { naDur = nDur }) <$> getNAttr (cellAction oCell)
145 nCell = if isJust nCa
146 then oCell { cellAction =
147 setNAttr (fromJust nCa) (cellAction oCell) }
149 reactiveValueWrite setRV (i,nCell)
150 fromMaybeM_ $ reactiveValueWrite noteDurLabelRV <$> lookup nDur symbolString
151 reactiveValueWrite (pieceArrRV ! i) nCell
154 reactiveValueOnCanRead rCountRV $ do
155 nRCount <- reactiveValueRead rCountRV
156 (i,oCell) <- reactiveValueRead setRV
157 let nCell = oCell { repeatCount = nRCount }
158 reactiveValueWrite setRV (i,nCell)
159 reactiveValueWrite (pieceArrRV ! i) nCell
161 reactiveValueOnCanRead slideComboRV $ do
162 nSlide <- reactiveValueRead slideComboRV
163 (i,oCell) <- reactiveValueRead setRV
164 let nCa :: Maybe NoteAttr
165 nCa = (\na -> na { naOrn = (naOrn na) { ornSlide = nSlide } }) <$>
166 getNAttr (cellAction oCell)
168 nCell = if isJust nCa
169 then oCell { cellAction =
170 setNAttr (fromJust nCa) (cellAction oCell)
173 reactiveValueWrite setRV (i,nCell)
174 reactiveValueWrite (pieceArrRV ! i) nCell
176 reactiveValueOnCanRead artComboRV $ do
177 nArt <- reactiveValueRead artComboRV
178 (i,oCell) <- reactiveValueRead setRV
179 let nCa :: Maybe NoteAttr
180 nCa = (\na -> na { naArt = nArt }) <$> getNAttr (cellAction oCell)
182 nCell = if isJust nCa
183 then oCell { cellAction =
184 setNAttr (fromJust nCa) (cellAction oCell) }
186 reactiveValueWrite setRV (i,nCell)
187 reactiveValueWrite (pieceArrRV ! i) nCell
190 hideNa = do widgetHide slideCombo
193 widgetHideAll noteDurBox
195 showNa = do widgetShow slideCombo
198 widgetShowAll noteDurBox
199 updateNaBox :: GUICell -> IO ()
200 updateNaBox GUICell { cellAction = act } = case act of
205 state <- newEmptyMVar
207 (\iPos -> liftIO $ do
208 postGUIAsync $ void $ tryPutMVar state iPos
212 (\fPos -> liftIO $ do
214 mp <- boardGetPiece fPos board
215 mstate <- tryTakeMVar state
216 when (fPos `elem` validArea && isJust mp) $ do
217 let piece = snd $ fromJust mp
218 when (maybe False (== fPos) mstate) $
219 boardSetPiece fPos (BF.second rotateGUICell (Player,piece)) board
220 nmp <- boardGetPiece fPos board
222 when (isJust nmp) $ do
223 let nC = snd $ fromJust nmp
224 reactiveValueWrite setRV (fPos,nC)
225 fromMaybeM_ $ reactiveValueWrite artComboRV . naArt <$>
226 getNAttr (cellAction nC)
228 reactiveValueWrite slideComboRV . ornSlide . naOrn <$> getNAttr (cellAction nC)
229 reactiveValueWrite rCountRV $ repeatCount nC
230 fromMaybeM_ $ reactiveValueWrite noteDurRV . naDur <$>
231 getNAttr (cellAction nC)
235 reactiveValueOnCanRead setRV (reactiveValueRead setRV >>= updateNaBox . snd)