on develop help sign in
Merge pull request #114 from reflex-frp/add-fast-sortable-list

Add a widget module; add fast sortable list widget

commit1d3a26b3f7d7d50cfe95bb3a28eca38981ad9ec3 authorRyan Trinkle <ryan.trinkle@gmail.com> dateFri 7 Jul 2017, 07:18 (9 years ago) parent50305c7906c517
2 files changed+44−1
reflex.cabal+2−1 src/Reflex/Widget/Basic.hs+42
reflex.cabal+2−1
@@ -97,7 +97,8 @@ library
9797 Reflex.Requester.Base,
9898 Reflex.Requester.Class,
9999 Reflex.Spider,
100− Reflex.Spider.Internal
100+ Reflex.Spider.Internal,
101+ Reflex.Widget.Basic
101102
102103 ghc-options: -Wall -fwarn-tabs -funbox-strict-fields -O2
103104 ghc-prof-options: -fprof-auto
src/Reflex/Widget/Basic.hsnew file+42
@@ -0,0 +1,42 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE ExplicitForAll #-}
3+{-# LANGUAGE MultiParamTypeClasses #-}
4+{-# LANGUAGE RecursiveDo #-}
5+#ifdef USE_REFLEX_OPTIMIZER
6+{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
7+#endif
8+
9+module Reflex.Widget.Basic where
10+
11+import Control.Monad.Fix (MonadFix)
12+import Data.Map (Map)
13+import Reflex.Class
14+import Reflex.Patch.MapWithMove
15+
16+
17+-- | Build sortable content in such a way that re-sorting it can cause minimal
18+-- disruption to an existing context.
19+--
20+-- Naively re-sorting a list of images would destroy every image and add them back
21+-- in the new order. This framework is able to avoid that by preserving the
22+-- identity of each image and simply moving it to the new location.
23+--
24+-- Example:
25+--
26+-- > let sortByFst = buttonA $> comparing fst
27+-- > sortBySnd = buttonB $> comparing snd
28+-- > sortEvent = leftmost [sortByFst, sortBySnd]
29+-- > sortableList
30+-- > (\k v -> text $ "\n" ++ show k ++ " " ++ v) -- show each element on a new line
31+-- > (Map.fromList $ zip [0..] [(3, "a"), (2, "b"), (1, "c")])
32+-- > sortEvent
33+sortableList :: forall t m k v a. (MonadHold t m, MonadFix m, MonadAdjust t m, Ord k)
34+ => (k -> v -> m a) -- ^ Function to render the content for each key/value pair
35+ -> Map k v -- ^ The sortable list with an initial ordering determined by the @Map@ keys in ascending order
36+ -> Event t (v -> v -> Ordering) -- ^ An event carrying a sort function for the list
37+ -> m (Map k a)
38+sortableList f m0 reSortFunc = do
39+ rec let reSortPatch = attachWith (flip patchThatSortsMapWith) (currentIncremental m) reSortFunc
40+ m <- holdIncremental m0 reSortPatch
41+ (results, _) <- mapMapWithAdjustWithMove f m0 reSortPatch
42+ pure results