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 setNAttr :: NoteAttr -> Action -> Action
26 setNAttr _ Inert = Inert
27 setNAttr _ Absorb = Absorb
28 setNAttr na (Stop _) = Stop na
29 setNAttr na (ChDir b _ dir) = ChDir b na dir
30 setNAttr na (Split _) = Split na
32 getNAttr :: Action -> Maybe NoteAttr
33 getNAttr Inert = Nothing
34 getNAttr Absorb = Nothing
35 getNAttr (Stop na) = Just na
36 getNAttr (ChDir _ na _) = Just na
37 getNAttr (Split na) = Just na
39 symbolString :: [(Duration,String)]
40 symbolString = map (\(_,y,z) -> (z,y)) noteSymbList
42 noteList :: [(String,Duration)]
43 noteList = map (\(x,_,y) -> (x,y)) noteSymbList
45 noteSymbList :: [(String, String, Duration)]
46 noteSymbList = sortBy (comparing (\(_,_,x) -> x))
47 [ ("♩", "Quarter note", 1 % 4)
48 , ("♪", "Eighth note ", 1 % 8)
49 , ("𝅗𝅥", "Half note", 1 % 2)
50 , ("𝅘𝅥𝅯", "Sixteenth note", 1 % 16)
51 , ("𝅝", "Whole note", 1)
54 comboBoxIndexRV :: (ComboBoxClass box) =>
55 box -> ReactiveFieldReadWrite IO Int
56 comboBoxIndexRV box = ReactiveFieldReadWrite setter getter notifier
57 where getter = comboBoxGetActive box
58 setter = comboBoxSetActive box
59 notifier = void . on box changed
61 clickHandling :: (ReactiveValueWrite cell GUICell IO) =>
63 -> IOBoard -> VBox -> IO VBox
64 clickHandling pieceArrRV board pieceBox = do
65 naBox <- vBoxNew False 10
66 boxPackStart pieceBox naBox PackNatural 10
69 artCombo <- comboBoxNewText
70 artIndex <- mapM (\art -> do i <- comboBoxAppendText artCombo
71 (fromString $ show art)
72 return (art,i)) [NoAccent ..]
73 comboBoxSetActive artCombo 0
74 boxPackStart naBox artCombo PackNatural 10
76 fromMaybe (error "In indexToArt: failed \
77 \to find the selected \
78 \articulation.") $ lookup i $ map swap artIndex
79 artToIndex a = fromMaybe (error "In artToIndex: failed \
80 \to find the correct index \
82 \articulation.") $ lookup a artIndex
83 artComboRV = bijection (indexToArt,artToIndex) `liftRW`
84 comboBoxIndexRV artCombo
87 slideCombo <- comboBoxNewText
88 slideIndex <- mapM (\sli -> do i <- comboBoxAppendText slideCombo
89 (fromString $ show sli)
90 return (sli,i)) [NoSlide ..]
91 comboBoxSetActive slideCombo 0
92 boxPackStart naBox slideCombo PackNatural 10
94 fromMaybe (error "In indexToSlide: failed \
95 \to find the correct slide \
97 \index.") $ lookup i $ map swap slideIndex
99 fromMaybe (error "In slideToIndex: failed \
102 \for the slide.") $ lookup s slideIndex
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
114 fromMaybe (error "In indexToDur: failed \
115 \to find the correct \
117 \selected index.") $ lookup i $ map swap noteDurIndex
119 fromMaybe (error "In durToIndex: \
122 \for the duration.") $ lookup d noteDurIndex
123 noteDurRV = bijection (indexToDur, durToIndex) `liftRW`
124 comboBoxIndexRV noteDurCombo
125 noteDurLabel <- labelNew =<< (`lookup` symbolString) <$> reactiveValueRead noteDurRV
126 let noteDurLabelRV = labelTextReactive noteDurLabel
127 boxPackStart naBox noteDurBox PackNatural 10
128 boxPackStart noteDurBox noteDurCombo PackNatural 10
129 boxPackStart noteDurBox noteDurLabel PackNatural 10
132 rCountAdj <- adjustmentNew 1 0 100 1 1 0
133 rCount <- spinButtonNew rCountAdj 1 0
134 boxPackStart pieceBox rCount PackNatural 10
135 let rCountRV = spinButtonValueIntReactive rCount
138 -- Carries the index of the tile to display and what to display.
139 setRV <- newCBMVarRW ((0,0),inertCell)
141 reactiveValueOnCanRead noteDurRV $ do
142 nDur <- reactiveValueRead noteDurRV
143 (i,oCell) <- reactiveValueRead setRV
144 let nCa :: Maybe NoteAttr
145 nCa = (\na -> na { naDur = nDur }) <$> getNAttr (cellAction oCell)
147 nCell = if isJust nCa
148 then oCell { cellAction =
149 setNAttr (fromJust nCa) (cellAction oCell) }
151 reactiveValueWrite setRV (i,nCell)
152 fromMaybeM_ $ reactiveValueWrite noteDurLabelRV <$> lookup nDur symbolString
153 reactiveValueWrite (pieceArrRV ! i) nCell
156 reactiveValueOnCanRead rCountRV $ do
157 nRCount <- reactiveValueRead rCountRV
158 (i,oCell) <- reactiveValueRead setRV
159 let nCell = oCell { repeatCount = nRCount }
160 reactiveValueWrite setRV (i,nCell)
161 reactiveValueWrite (pieceArrRV ! i) nCell
163 reactiveValueOnCanRead slideComboRV $ do
164 nSlide <- reactiveValueRead slideComboRV
165 (i,oCell) <- reactiveValueRead setRV
166 let nCa :: Maybe NoteAttr
167 nCa = (\na -> na { naOrn = (naOrn na) { ornSlide = nSlide } }) <$>
168 getNAttr (cellAction oCell)
170 nCell = if isJust nCa
171 then oCell { cellAction =
172 setNAttr (fromJust nCa) (cellAction oCell)
175 reactiveValueWrite setRV (i,nCell)
176 reactiveValueWrite (pieceArrRV ! i) nCell
178 reactiveValueOnCanRead artComboRV $ do
179 nArt <- reactiveValueRead artComboRV
180 (i,oCell) <- reactiveValueRead setRV
181 let nCa :: Maybe NoteAttr
182 nCa = (\na -> na { naArt = nArt }) <$> getNAttr (cellAction oCell)
184 nCell = if isJust nCa
185 then oCell { cellAction =
186 setNAttr (fromJust nCa) (cellAction oCell) }
188 reactiveValueWrite setRV (i,nCell)
189 reactiveValueWrite (pieceArrRV ! i) nCell
192 hideNa = do widgetHide slideCombo
195 widgetHideAll noteDurBox
197 showNa = do widgetShow slideCombo
200 widgetShowAll noteDurBox
201 updateNaBox :: GUICell -> IO ()
202 updateNaBox GUICell { cellAction = act } = case act of
207 state <- newEmptyMVar
209 (\iPos -> liftIO $ do
210 postGUIAsync $ void $ tryPutMVar state iPos
215 button <- eventButton
218 mp <- boardGetPiece fPos board
219 mstate <- tryTakeMVar state
220 when (fPos `elem` validArea && isJust mp) $ do
221 let piece = snd $ fromJust mp
222 when (button == RightButton && maybe False (== fPos) mstate) $
223 boardSetPiece fPos (BF.second rotateGUICell (Player,piece)) board
224 nmp <- boardGetPiece fPos board
226 when (button == LeftButton && isJust nmp) $ do
227 let nC = snd $ fromJust nmp
228 reactiveValueWrite setRV (fPos,nC)
229 fromMaybeM_ $ reactiveValueWrite artComboRV . naArt <$>
230 getNAttr (cellAction nC)
232 reactiveValueWrite slideComboRV . ornSlide . naOrn <$> getNAttr (cellAction nC)
233 reactiveValueWrite rCountRV $ repeatCount nC
234 fromMaybeM_ $ reactiveValueWrite noteDurRV . naDur <$>
235 getNAttr (cellAction nC)
239 reactiveValueOnCanRead setRV (reactiveValueRead setRV >>= updateNaBox . snd)