threepenny-editors 0.2.0.7 → 0.2.0.8
raw patch · 5 files changed
+50/−41 lines, 5 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Graphics.UI.Threepenny.Editors.Base: instance GHC.Classes.Eq tag => GHC.Classes.Eq (Graphics.UI.Threepenny.Editors.Base.SumWrapper tag a)
- Graphics.UI.Threepenny.Editors.Base: instance GHC.Classes.Ord tag => GHC.Classes.Ord (Graphics.UI.Threepenny.Editors.Base.SumWrapper tag a)
- Graphics.UI.Threepenny.Editors.Base: instance GHC.Show.Show tag => GHC.Show.Show (Graphics.UI.Threepenny.Editors.Base.SumWrapper tag a)
- Graphics.UI.Threepenny.Editors: editorSelection :: Eq a => Behavior [(String, a)] -> EditorFactory a a
+ Graphics.UI.Threepenny.Editors: editorSelection :: Ord a => Behavior [a] -> Behavior (a -> UI Element) -> EditorFactory (Maybe a) (Maybe a)
- Graphics.UI.Threepenny.Editors.Base: editorSelection :: Eq a => Behavior [(String, a)] -> Behavior a -> Compose UI EditorDef a
+ Graphics.UI.Threepenny.Editors.Base: editorSelection :: Ord a => Behavior [a] -> Behavior (a -> UI Element) -> Behavior (Maybe a) -> Compose UI EditorDef (Maybe a)
- Graphics.UI.Threepenny.Editors.Profunctor: editorSelection :: Eq a => Behavior [(String, a)] -> EditorFactory a a
+ Graphics.UI.Threepenny.Editors.Profunctor: editorSelection :: Ord a => Behavior [a] -> Behavior (a -> UI Element) -> EditorFactory (Maybe a) (Maybe a)
Files
- CHANGELOG.md +2/−0
- examples/Person.hs +2/−6
- src/Graphics/UI/Threepenny/Editors/Base.hs +43/−32
- src/Graphics/UI/Threepenny/Editors/Profunctor.hs +2/−2
- threepenny-editors.cabal +1/−1
CHANGELOG.md view
@@ -1,3 +1,5 @@+# 0.2.0.8 (2017-05-21)+ * Bug fixes # 0.2.0.7 (2017-05-20) * Added `editorSelection`. # 0.2.0.6 (2017-05-15)
examples/Person.hs view
@@ -80,9 +80,6 @@ instance SOP.Generic Person instance Default Person where def = Person Basic_ "First" "Last" (Just 18) def def -editorLegalStatus :: EditorFactory LegalStatus LegalStatus-editorLegalStatus = editorJust $ editorEnumBounded(pure(string.show))- editorPerson :: EditorFactory Person Person editorPerson = (\fn ln a e ls b -> Person e fn ln a b ls)@@ -90,16 +87,15 @@ -*- field "Last:" lastName editor -*- field "Age:" age editor -*- field "Education:" education editorEducation- -*- field "Status" status editorLegalStatus+ -*- field "Status" status (editorJust $ editorSelection (pure [minBound..]) (pure (string.show))) -*- field "Brexiter" brexiteer editor setup :: Window -> UI () setup w = void $ mdo _ <- return w # set title "Threepenny editors example" person1 <- createEditor editorPerson person1B- person1B <- stepper def (edited person1)- person2 <- createEditor editorGeneric person1B+ person1B <- stepper def (unionWith const (edited person1) (edited person2)) getBody w #+ [grid [ [return $ editorElement person1]
src/Graphics/UI/Threepenny/Editors/Base.hs view
@@ -26,7 +26,7 @@ )where import Data.Functor.Compose-import Data.Tuple+import Data.Maybe import Graphics.UI.Threepenny.Attributes import Graphics.UI.Threepenny.Core import Graphics.UI.Threepenny.Elements@@ -153,8 +153,14 @@ editorEnumBounded :: (Bounded a, Enum a, Ord a, Show a) => Behavior(a -> UI Element) -> Behavior (Maybe a) -> Compose UI EditorDef (Maybe a)-editorEnumBounded display b = Compose $ do- l <- listBox (pure $ enumFrom minBound) b display+editorEnumBounded = editorSelection (pure $ enumFrom minBound)++-- | An editor that presents a dynamic list of options.+editorSelection+ :: Ord a+ => Behavior [a] -> Behavior(a -> UI Element) -> Behavior (Maybe a) -> Compose UI EditorDef (Maybe a)+editorSelection options display b = Compose $ do+ l <- listBox options b display return $ EditorDef (tidings b (rumors $ userSelection l)) (single $ getElement l) @@ -166,51 +172,56 @@ let ev = filterJust (editedDef e) return $ EditorDef (tidings b ev) (editorDefLayout e) -data SumWrapper tag a = A {display :: tag, theEditor :: Editor a}--instance Eq tag => Eq (SumWrapper tag a) where A a _ == A b _ = a == b-instance Ord tag => Ord (SumWrapper tag a) where compare (A a _) (A b _) = compare a b-instance Show tag => Show (SumWrapper tag a) where show = show . display---- | An editor that presents a dynamic list of options-editorSelection :: Eq a => Behavior [(String,a)] -> Behavior a -> Compose UI EditorDef a-editorSelection options selected = Compose $ do- l <- listBox (fmap fst <$> options) ((\s o -> lookup s (fmap swap o)) <$> selected <*> options) (pure string)- let e = filterJust $ flip lookup <$> options <@> filterJust (rumors (userSelection l))- return $ EditorDef (tidings selected e) (single $ getElement l)- -- | An editor for union types, built from editors for its constructors. editorSum :: (Ord tag, Show tag) => [(tag, Compose UI EditorDef a)] -> (a -> tag) -> Behavior a -> Compose UI EditorDef a editorSum options selector ba = Compose $ do- w <- askWindow options <- traverse (\(tag, Compose mk) -> (tag,) <$> (mk >>= runEditorDef)) options- -- extract the tag from the current value- let bSelected =- let build a =- let tag = selector a- in A tag <$> lookup tag options- in build <$> ba+ let tag = selector <$> ba+ tag' <- calmB tag+ let build a = lookup a options -- build a tag selector following the current tag- l <-- listBox (pure $ fmap (uncurry A) options) bSelected (pure (string . show))+ l <- listBox (pure $ fmap fst options) (Just <$> tag) (pure (string . show)) -- a placeholder for the constructor editor- nestedEditorDef <- new- -- when the user selects a tag, refresh the nested editor- _ <-- liftIO $- register (filterJust $ rumors (userSelection l)) $ \x ->- runUI w $ set' children [getElement $ theEditor x] nestedEditorDef+ nestedEditorDef <-+ new # sink children ((\x -> [maybe (error "editorSum") editorElement (build x)]) <$> tag') -- let composed = Vertical [single (getElement l), single nestedEditorDef] -- the result event fires when any of the nested editors or the tag selector fire. let editedEvents = fmap (edited . snd) options- eTag = filterJust $ fmap display <$> rumors (userSelection l)+ eTag = filterJust $ rumors (userSelection l) taggedOptions = sequenceA [(tag, ) <$> contents e | (tag, e) <- options] editedTag = filterJust $ flip lookup <$> taggedOptions <@> eTag editedE = head <$> unions (editedTag : editedEvents) return $ EditorDef (tidings ba editedE) composed++-- | Returns a new behavior that only notifies for new values.+calmB :: Eq a => Behavior a -> UI (Behavior a)+calmB b = do+ w <- askWindow+ (e, trigger) <- liftIO newEvent+ liftIOLater $ do+ current <- currentValue b+ trigger current+ runUI w $ onChanges b (liftIO . trigger)+ eCalm <- calmE e+ fmap (fromMaybe (error "calmB")) <$> stepper Nothing (Just <$> eCalm)++data Memory a = Empty | New a | Same a+updateMemory :: Eq a => a -> Memory a -> Memory a+updateMemory x Empty = New x+updateMemory x (New a) | a /= x = New x+updateMemory x (Same a) | a /= x = New x+updateMemory x _ = Same x+isNew :: Memory a -> Maybe a+isNew (New x) = Just x+isNew _ = Nothing++-- | Returns a new 'Event' that skips consecutive triggers with the same value.+calmE :: Eq a => Event a -> UI (Event a)+calmE e =+ filterJust . fmap isNew <$> accumE Empty (updateMemory <$> e) instance Editable () where editor b = Compose $ do
src/Graphics/UI/Threepenny/Editors/Profunctor.hs view
@@ -111,8 +111,8 @@ editorJust e = EditorFactory $ Base.editorJust (run e) -- | An editor that presents a dynamic list of options-editorSelection :: Eq a => Behavior [(String,a)] -> EditorFactory a a-editorSelection sel = EditorFactory $ Base.editorSelection sel+editorSelection :: Ord a => Behavior [a] -> Behavior(a -> UI Element) -> EditorFactory (Maybe a) (Maybe a)+editorSelection opts displ = EditorFactory $ Base.editorSelection opts displ -- | An editor for union types, built from editors for its constructors. editorSum
threepenny-editors.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack name: threepenny-editors-version: 0.2.0.7+version: 0.2.0.8 synopsis: Composable algebraic editors description: This package provides a type class 'Editable' and combinators to easily put together form-like editors for algebraic datatypes.