1 {-# LANGUAGE FlexibleContexts, MultiParamTypeClasses #-}
3 module RMCA.Auxiliary.ReactiveValue where
8 import Data.ReactiveValue
10 import RMCA.Auxiliary.Misc
13 -- = Auxiliary functions for manipulating reactive values
15 -- | Creates a new 'CBMVar' wrapped into a reactive field.
16 newCBMVarRW :: a -> IO (ReactiveFieldReadWrite IO a)
19 let getter = readCBMVar mvar
20 setter = writeCBMVar mvar
21 notifier = installCallbackCBMVar mvar
22 return $ ReactiveFieldReadWrite setter getter notifier
24 -- | Writes a value to a reactive value if the value is different from the one already in the reactive value.
25 reactiveValueWriteOnNotEq :: ( Eq b
26 , ReactiveValueReadWrite a b m) =>
28 reactiveValueWriteOnNotEq rv nv = do
29 ov <- reactiveValueRead rv
30 when (ov /= nv) $ reactiveValueWrite rv nv
32 -- | Relation that will update when the value is an 'Event'.
33 (>:>) :: (ReactiveValueRead a (Event b) IO, ReactiveValueWrite c b IO) =>
35 eventRV >:> rv = reactiveValueOnCanRead eventRV syncOnEvent
36 where syncOnEvent = do
37 erv <- reactiveValueRead eventRV
38 when (isEvent erv) $ reactiveValueWrite rv $ fromEvent erv
40 -- | When the reactive value on the left changes, the value on the right is updated using the value it contains and the value on the left with the provided function.
41 syncRightOnLeftWithBoth :: ( ReactiveValueRead a b m
42 , ReactiveValueReadWrite c d m
43 ) => (b -> d -> d) -> a -> c -> m ()
44 syncRightOnLeftWithBoth f l r = reactiveValueOnCanRead l $ do
45 nl <- reactiveValueRead l
46 or <- reactiveValueRead r
47 reactiveValueWrite r (f nl or)
49 -- | Forces to update an reactive value by writing to it with the value it contains.
50 updateRV :: (ReactiveValueReadWrite a b m) => a -> m ()
51 updateRV rv = reactiveValueRead rv >>= reactiveValueWrite rv
53 floatConv :: (ReactiveValueReadWrite a b m,
54 Real c, Real b, Fractional c, Fractional b) =>
55 a -> ReactiveFieldReadWrite m c
56 floatConv = liftRW $ bijection (realToFrac, realToFrac)
58 swapHandlerStorage :: (ReactiveValueReadWrite a b IO) =>
59 a -> IO (ReactiveFieldReadWrite IO b)
60 swapHandlerStorage rv = do
62 let setter val = reactiveValueWrite rv val >> writeCBRef ioref ()
63 getter = reactiveValueRead rv
64 notifier = installCallbackCBRef ioref
65 return $ ReactiveFieldReadWrite setter getter notifier
68 , ReactiveValueWrite a b m
69 , ReactiveValueWrite c d m
70 , ReactiveValueWrite e f m) =>
71 (i -> (b,d,f)) -> a -> c -> e -> ReactiveFieldWrite m i
72 liftW3 f a b c = ReactiveFieldWrite setter
75 reactiveValueWrite a x1
76 reactiveValueWrite b x2
77 reactiveValueWrite c x3
79 liftRW3 :: ( ReactiveValueReadWrite a b m
80 , ReactiveValueReadWrite c d m
81 , ReactiveValueReadWrite e f m) =>
82 BijectiveFunc i (b,d,f) -> a -> c -> e -> ReactiveFieldReadWrite m i
84 ReactiveFieldReadWrite setter getter notifier
85 where ReactiveFieldRead getter notifier = liftR3 (curry3 f2) a b c
86 ReactiveFieldWrite setter = liftW3 f1 a b c
87 (f1, f2) = (direct bij, inverse bij)
89 liftR4 :: ( ReactiveValueRead a b m
90 , ReactiveValueRead c d m
91 , ReactiveValueRead e f m
92 , ReactiveValueRead g h m) =>
93 (b -> d -> f -> h -> i) -> a -> c -> e -> g -> ReactiveFieldRead m i
94 liftR4 f a b c d = ReactiveFieldRead getter notifier
96 x1 <- reactiveValueRead a
97 x2 <- reactiveValueRead b
98 x3 <- reactiveValueRead c
99 x4 <- reactiveValueRead d
100 return $ f x1 x2 x3 x4
102 reactiveValueOnCanRead a p
103 reactiveValueOnCanRead b p
104 reactiveValueOnCanRead c p
105 reactiveValueOnCanRead d p
108 , ReactiveValueWrite a b m
109 , ReactiveValueWrite c d m
110 , ReactiveValueWrite e f m
111 , ReactiveValueWrite g h m) =>
112 (i -> (b,d,f,h)) -> a -> c -> e -> g -> ReactiveFieldWrite m i
113 liftW4 f a b c d = ReactiveFieldWrite setter
115 let (x1,x2,x3,x4) = f x
116 reactiveValueWrite a x1
117 reactiveValueWrite b x2
118 reactiveValueWrite c x3
119 reactiveValueWrite d x4
121 liftRW4 :: ( ReactiveValueReadWrite a b m
122 , ReactiveValueReadWrite c d m
123 , ReactiveValueReadWrite e f m
124 , ReactiveValueReadWrite g h m) =>
125 BijectiveFunc i (b,d,f,h) -> a -> c -> e -> g
126 -> ReactiveFieldReadWrite m i
127 liftRW4 bij a b c d =
128 ReactiveFieldReadWrite setter getter notifier
129 where ReactiveFieldRead getter notifier = liftR4 (curry4 f2) a b c d
130 ReactiveFieldWrite setter = liftW4 f1 a b c d
131 (f1, f2) = (direct bij, inverse bij)
133 liftR5 :: ( ReactiveValueRead a b m
134 , ReactiveValueRead c d m
135 , ReactiveValueRead e f m
136 , ReactiveValueRead g h m
137 , ReactiveValueRead i j m) =>
138 (b -> d -> f -> h -> j -> k) -> a -> c -> e -> g -> i
139 -> ReactiveFieldRead m k
140 liftR5 f a b c d e = ReactiveFieldRead getter notifier
142 x1 <- reactiveValueRead a
143 x2 <- reactiveValueRead b
144 x3 <- reactiveValueRead c
145 x4 <- reactiveValueRead d
146 x5 <- reactiveValueRead e
147 return $ f x1 x2 x3 x4 x5
149 reactiveValueOnCanRead a p
150 reactiveValueOnCanRead b p
151 reactiveValueOnCanRead c p
152 reactiveValueOnCanRead d p
153 reactiveValueOnCanRead e p
156 , ReactiveValueWrite a b m
157 , ReactiveValueWrite c d m
158 , ReactiveValueWrite e f m
159 , ReactiveValueWrite g h m
160 , ReactiveValueWrite i j m) =>
161 (k -> (b,d,f,h,j)) -> a -> c -> e -> g -> i -> ReactiveFieldWrite m k
162 liftW5 f a b c d e = ReactiveFieldWrite setter
164 let (x1,x2,x3,x4,x5) = f x
165 reactiveValueWrite a x1
166 reactiveValueWrite b x2
167 reactiveValueWrite c x3
168 reactiveValueWrite d x4
169 reactiveValueWrite e x5
171 liftRW5 :: ( ReactiveValueReadWrite a b m
172 , ReactiveValueReadWrite c d m
173 , ReactiveValueReadWrite e f m
174 , ReactiveValueReadWrite g h m
175 , ReactiveValueReadWrite i j m) =>
176 BijectiveFunc k (b,d,f,h,j) -> a -> c -> e -> g -> i
177 -> ReactiveFieldReadWrite m k
178 liftRW5 bij a b c d e =
179 ReactiveFieldReadWrite setter getter notifier
180 where ReactiveFieldRead getter notifier = liftR5 (curry5 f2) a b c d e
181 ReactiveFieldWrite setter = liftW5 f1 a b c d e
182 (f1, f2) = (direct bij, inverse bij)