1 {-# LANGUAGE FlexibleContexts, MultiParamTypeClasses, ScopedTypeVariables,
4 module RMCA.GUI.NoteSettings where
6 import Control.Concurrent.MVar
8 import Control.Monad.IO.Class
10 import qualified Data.Bifunctor as BF
15 import Data.ReactiveValue
18 import Graphics.UI.Gtk hiding (Action)
19 import Graphics.UI.Gtk.Board.TiledBoard hiding (Board)
20 import Graphics.UI.Gtk.Reactive
25 fromMaybeM_ :: (Monad m) => Maybe (m ()) -> m ()
26 fromMaybeM_ = fromMaybe (return ())
28 setNAttr :: NoteAttr -> Action -> Action
29 setNAttr _ Inert = Inert
30 setNAttr _ Absorb = Absorb
31 setNAttr na (Stop _) = Stop na
32 setNAttr na (ChDir b _ dir) = ChDir b na dir
33 setNAttr na (Split _) = Split na
35 getNAttr :: Action -> Maybe NoteAttr
36 getNAttr Inert = Nothing
37 getNAttr Absorb = Nothing
38 getNAttr (Stop na) = Just na
39 getNAttr (ChDir _ na _) = Just na
40 getNAttr (Split na) = Just na
42 symbolString :: [(Duration,String)]
43 symbolString = map (\(_,y,z) -> (z,y)) noteSymbList
45 noteList :: [(String,Duration)]
46 noteList = map (\(x,_,y) -> (x,y)) noteSymbList
48 noteSymbList :: [(String, String, Duration)]
49 noteSymbList = sortBy (comparing (\(_,_,x) -> x))
50 [ ("♩", "Quarter note", 1 % 4)
51 , ("♪", "Eighth note ", 1 % 8)
52 , ("𝅗𝅥", "Half note", 1 % 2)
53 , ("𝅘𝅥𝅯", "Sixteenth note", 1 % 16)
54 , ("𝅝", "Whole note", 1)
57 comboBoxIndexRV :: (ComboBoxClass box) =>
58 box -> ReactiveFieldReadWrite IO Int
59 comboBoxIndexRV box = ReactiveFieldReadWrite setter getter notifier
60 where getter = comboBoxGetActive box
61 setter = comboBoxSetActive box
62 notifier = void . on box changed
64 clickHandling :: (ReactiveValueWrite cell GUICell IO) =>
66 -> IOBoard -> VBox -> IO VBox
67 clickHandling pieceArrRV board pieceBox = do
68 naBox <- vBoxNew False 10
69 boxPackStart pieceBox naBox PackNatural 10
72 artCombo <- comboBoxNewText
73 artIndex <- mapM (\art -> do i <- comboBoxAppendText artCombo
74 (fromString $ show art)
75 return (art,i)) [NoAccent ..]
76 comboBoxSetActive artCombo 0
77 boxPackStart naBox artCombo PackNatural 10
79 fromMaybe (error "In indexToArt: failed \
80 \to find the selected \
81 \articulation.") $ lookup i $ map swap artIndex
82 artToIndex a = fromMaybe (error "In artToIndex: failed \
83 \to find the correct index \
85 \articulation.") $ lookup a artIndex
86 artComboRV = bijection (indexToArt,artToIndex) `liftRW`
87 comboBoxIndexRV artCombo
90 slideCombo <- comboBoxNewText
91 slideIndex <- mapM (\sli -> do i <- comboBoxAppendText slideCombo
92 (fromString $ show sli)
93 return (sli,i)) [NoSlide ..]
94 comboBoxSetActive slideCombo 0
95 boxPackStart naBox slideCombo PackNatural 10
97 fromMaybe (error "In indexToSlide: failed \
98 \to find the correct slide \
100 \index.") $ lookup i $ map swap slideIndex
102 fromMaybe (error "In slideToIndex: failed \
105 \for the slide.") $ lookup s slideIndex
106 slideComboRV = bijection (indexToSlide,slideToIndex) `liftRW`
107 comboBoxIndexRV slideCombo
110 noteDurBox <- hBoxNew False 10
111 noteDurCombo <- comboBoxNewText
112 noteDurIndex <- mapM (\(str,dur) -> do i <- comboBoxAppendText noteDurCombo
114 return (dur,i)) noteList
115 comboBoxSetActive noteDurCombo 0
117 fromMaybe (error "In indexToDur: failed \
118 \to find the correct \
120 \selected index.") $ lookup i $ map swap noteDurIndex
122 fromMaybe (error "In durToIndex: \
125 \for the duration.") $ lookup d noteDurIndex
126 noteDurRV = bijection (indexToDur, durToIndex) `liftRW`
127 comboBoxIndexRV noteDurCombo
128 noteDurLabel <- labelNew =<< (`lookup` symbolString) <$> reactiveValueRead noteDurRV
129 let noteDurLabelRV = labelTextReactive noteDurLabel
130 boxPackStart naBox noteDurBox PackNatural 10
131 boxPackStart noteDurBox noteDurCombo PackNatural 10
132 boxPackStart noteDurBox noteDurLabel PackNatural 10
135 rCountAdj <- adjustmentNew 1 0 100 1 1 0
136 rCount <- spinButtonNew rCountAdj 1 0
137 boxPackStart pieceBox rCount PackNatural 10
138 let rCountRV = spinButtonValueIntReactive rCount
141 -- Carries the index of the tile to display and what to display.
142 setRV <- newCBMVarRW ((0,0),inertCell)
144 reactiveValueOnCanRead noteDurRV $ do
145 nDur <- reactiveValueRead noteDurRV
146 (i,oCell) <- reactiveValueRead setRV
147 let nCa :: Maybe NoteAttr
148 nCa = (\na -> na { naDur = nDur }) <$> getNAttr (cellAction oCell)
150 nCell = if isJust nCa
151 then oCell { cellAction =
152 setNAttr (fromJust nCa) (cellAction oCell) }
154 reactiveValueWrite setRV (i,nCell)
155 fromMaybeM_ $ reactiveValueWrite noteDurLabelRV <$> lookup nDur symbolString
156 reactiveValueWrite (pieceArrRV ! i) nCell
159 reactiveValueOnCanRead rCountRV $ do
160 nRCount <- reactiveValueRead rCountRV
161 (i,oCell) <- reactiveValueRead setRV
162 let nCell = oCell { repeatCount = nRCount }
163 reactiveValueWrite setRV (i,nCell)
164 reactiveValueWrite (pieceArrRV ! i) nCell
166 reactiveValueOnCanRead slideComboRV $ do
167 nSlide <- reactiveValueRead slideComboRV
168 (i,oCell) <- reactiveValueRead setRV
169 let nCa :: Maybe NoteAttr
170 nCa = (\na -> na { naOrn = (naOrn na) { ornSlide = nSlide } }) <$>
171 getNAttr (cellAction oCell)
173 nCell = if isJust nCa
174 then oCell { cellAction =
175 setNAttr (fromJust nCa) (cellAction oCell)
178 reactiveValueWrite setRV (i,nCell)
179 reactiveValueWrite (pieceArrRV ! i) nCell
181 reactiveValueOnCanRead artComboRV $ do
182 nArt <- reactiveValueRead artComboRV
183 (i,oCell) <- reactiveValueRead setRV
184 let nCa :: Maybe NoteAttr
185 nCa = (\na -> na { naArt = nArt }) <$> getNAttr (cellAction oCell)
187 nCell = if isJust nCa
188 then oCell { cellAction =
189 setNAttr (fromJust nCa) (cellAction oCell) }
191 reactiveValueWrite setRV (i,nCell)
192 reactiveValueWrite (pieceArrRV ! i) nCell
195 hideNa = do widgetHide slideCombo
198 widgetHideAll noteDurBox
200 showNa = do widgetShow slideCombo
203 widgetShowAll noteDurBox
204 updateNaBox :: GUICell -> IO ()
205 updateNaBox GUICell { cellAction = act } = case act of
210 state <- newEmptyMVar
212 (\iPos -> liftIO $ do
213 postGUIAsync $ void $ tryPutMVar state iPos
218 button <- eventButton
221 mp <- boardGetPiece fPos board
222 mstate <- tryTakeMVar state
223 when (fPos `elem` validArea && isJust mp) $ do
224 let piece = snd $ fromJust mp
225 when (button == RightButton && maybe False (== fPos) mstate) $
226 boardSetPiece fPos (BF.second rotateGUICell (Player,piece)) board
227 nmp <- boardGetPiece fPos board
229 when (button == LeftButton && isJust nmp) $ do
230 let nC = snd $ fromJust nmp
231 reactiveValueWrite setRV (fPos,nC)
232 fromMaybeM_ $ reactiveValueWrite artComboRV . naArt <$>
233 getNAttr (cellAction nC)
235 reactiveValueWrite slideComboRV . ornSlide . naOrn <$> getNAttr (cellAction nC)
236 reactiveValueWrite rCountRV $ repeatCount nC
237 fromMaybeM_ $ reactiveValueWrite noteDurRV . naDur <$>
238 getNAttr (cellAction nC)
242 reactiveValueOnCanRead setRV (reactiveValueRead setRV >>= updateNaBox . snd)