threepenny-editors 0.3.0 → 0.4.0
raw patch · 6 files changed
+47/−44 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Graphics.UI.Threepenny.Editors.Base: [editorDefSetup] :: EditorDef a -> UI Element -> UI Element
- Graphics.UI.Threepenny.Editors.Base: liftEditorDef :: (UI Element -> UI Element) -> EditorDef a -> EditorDef a
- Graphics.UI.Threepenny.Editors.Profunctor: liftEditor :: (UI Element -> UI Element) -> EditorFactory a b -> EditorFactory a b
+ Graphics.UI.Threepenny.Editors: Grid :: (Seq (Seq (Maybe Element))) -> Layout
+ Graphics.UI.Threepenny.Editors: horizontal :: Layout -> Layout -> Layout
+ Graphics.UI.Threepenny.Editors: newtype Layout
+ Graphics.UI.Threepenny.Editors: vertical :: Layout -> Layout -> Layout
+ Graphics.UI.Threepenny.Editors.Base: horizontal :: Layout -> Layout -> Layout
+ Graphics.UI.Threepenny.Editors.Base: vertical :: Layout -> Layout -> Layout
+ Graphics.UI.Threepenny.Editors.Profunctor: Grid :: (Seq (Seq (Maybe Element))) -> Layout
+ Graphics.UI.Threepenny.Editors.Profunctor: horizontal :: Layout -> Layout -> Layout
+ Graphics.UI.Threepenny.Editors.Profunctor: newtype Layout
+ Graphics.UI.Threepenny.Editors.Profunctor: vertical :: Layout -> Layout -> Layout
- Graphics.UI.Threepenny.Editors: editorSum :: (Show tag, Ord tag) => [(tag, EditorFactory b b)] -> (b -> tag) -> EditorFactory b b
+ Graphics.UI.Threepenny.Editors: editorSum :: (Show tag, Ord tag) => (Layout -> Layout -> Layout) -> [(tag, EditorFactory b b)] -> (b -> tag) -> EditorFactory b b
- Graphics.UI.Threepenny.Editors.Base: EditorDef :: Tidings a -> Layout -> (UI Element -> UI Element) -> EditorDef a
+ Graphics.UI.Threepenny.Editors.Base: EditorDef :: Tidings a -> Layout -> EditorDef a
- Graphics.UI.Threepenny.Editors.Base: editorSum :: (Ord tag, Show tag) => [(tag, Compose UI EditorDef a)] -> (a -> tag) -> Behavior a -> Compose UI EditorDef a
+ Graphics.UI.Threepenny.Editors.Base: editorSum :: (Ord tag, Show tag) => (Layout -> Layout -> Layout) -> [(tag, Compose UI EditorDef a)] -> (a -> tag) -> Behavior a -> Compose UI EditorDef a
- Graphics.UI.Threepenny.Editors.Profunctor: editorSum :: (Show tag, Ord tag) => [(tag, EditorFactory b b)] -> (b -> tag) -> EditorFactory b b
+ Graphics.UI.Threepenny.Editors.Profunctor: editorSum :: (Show tag, Ord tag) => (Layout -> Layout -> Layout) -> [(tag, EditorFactory b b)] -> (b -> tag) -> EditorFactory b b
Files
- CHANGELOG.md +4/−0
- examples/Person.hs +2/−2
- src/Graphics/UI/Threepenny/Editors.hs +4/−0
- src/Graphics/UI/Threepenny/Editors/Base.hs +28/−31
- src/Graphics/UI/Threepenny/Editors/Profunctor.hs +8/−10
- threepenny-editors.cabal +1/−1
CHANGELOG.md view
@@ -1,3 +1,7 @@+# 0.4.0 (2017-07-13)+ * Fixed a bug in the layout engine+ * Dropped editorDefSetup+ * Exposed the Layout primitives # 0.3.0 (2017-07-13) * Version bump required to comply with the Haskell PvP, as the recent layout changes were breaking changes due to deleted constructors.
examples/Person.hs view
@@ -12,7 +12,7 @@ import qualified Generics.SOP as SOP import GHC.Generics import Graphics.UI.Threepenny.Core-import Graphics.UI.Threepenny.Editors+import Graphics.UI.Threepenny.Editors hiding (Single) import Graphics.UI.Threepenny.Elements main :: IO ()@@ -47,7 +47,7 @@ let selector x = case x of Other _ -> "Other" _ -> show x- editorSum+ editorSum horizontal [ ("Basic", const Basic <$> editorUnit) , ("Intermediate", const Intermediate <$> editorUnit) , ("Other", dimap (fromMaybe "" . getOther) Other editor)
src/Graphics/UI/Threepenny/Editors.hs view
@@ -24,6 +24,10 @@ -- ** Generic editors , editorGeneric , editorGenericSimple+ -- ** Layouts+ , Layout(Grid, Single)+ , horizontal+ , vertical )where import Graphics.UI.Threepenny.Editors.Profunctor
src/Graphics/UI/Threepenny/Editors/Base.hs view
@@ -15,9 +15,10 @@ -- ** Editor definitions , EditorDef(..) , runEditorDef- , liftEditorDef -- ** Layouts , Layout(Grid, Single)+ , horizontal+ , vertical -- ** Editor composition , (|*|), (|*), (*|) , (-*-), (-*), (*-)@@ -62,7 +63,7 @@ getElement = editorElement newtype Layout- = Grid (Seq (Seq (Maybe Element)))-- ^ A non empty list of rows, where all the rows are assumed to have the same length+ = Grid (Seq (Seq (Maybe Element))) -- ^ A non empty list of rows, where all the rows are assumed to have the same length pattern Single :: Element -> Layout pattern Single x <- Grid (Singleton (Singleton (Just x))) where Single x = Grid [[Just x]]@@ -74,16 +75,19 @@ vertical (Grid rows@(length.head.toList -> l1)) (Grid rows'@(length.head.toList -> l2)) = Grid $ fmap pad1 rows <> fmap pad2 rows' where- pad l1 l2 | l1 >= l2 = id+ pad l1 l2 | l1 >= l2 = id | otherwise = (<> Seq.replicate (l2-l1) Nothing) pad1 = pad l1 l2 pad2 = pad l2 l1 -horizontal (Grid rows@(length.head.toList -> l1)) (Grid rows'@(length.head.toList -> l2)) =- Grid $ Seq.zipWith (<>) (pad1 rows) (pad2 rows')+horizontal (Grid rows@(length -> l1)) (Grid rows'@(length -> l2)) =+ Grid $ Seq.zipWith (<>) (pad1 rows) (pad2 rows') where- pad l1 l2 | l1 >= l2 = id- | otherwise = \x -> let padding = Seq.replicate (length $ head $ toList x) Nothing in x <> Seq.replicate (l2-l1) padding+ pad l1 l2+ | l1 >= l2 = id+ | otherwise = \x ->+ let padding = Seq.replicate (length $ head $ toList x) Nothing+ in x <> Seq.replicate (l2 - l1) padding pad1 = pad l1 l2 pad2 = pad l2 l1 @@ -93,24 +97,17 @@ data EditorDef a = EditorDef { editorDefTidings :: Tidings a , editorDefLayout :: Layout- , editorDefSetup :: UI Element -> UI Element } deriving Functor -editorDef :: Tidings a -> Layout -> EditorDef a-editorDef tidings layout = EditorDef tidings layout id- editedDef :: EditorDef a -> Event a editedDef = rumors . editorDefTidings runEditorDef :: EditorDef a -> UI (Editor a) runEditorDef def = do- el <- runLayout (editorDefLayout def) # editorDefSetup def+ el <- runLayout (editorDefLayout def) return $ Editor (editorDefTidings def) el -liftEditorDef :: (UI Element -> UI Element) -> EditorDef a -> EditorDef a-liftEditorDef f def = def{editorDefSetup = f . editorDefSetup def }- -- | The class of Editable datatypes. class Editable a where -- | The editor factory@@ -125,7 +122,7 @@ a <- getCompose a b <- getCompose b let ab = horizontal (editorDefLayout a) (editorDefLayout b)- return $ editorDef (editorDefTidings a <*> editorDefTidings b) ab+ return $ EditorDef (editorDefTidings a <*> editorDefTidings b) ab -- | Left-right composition of an element with a editor (*|) :: UI Element -> Compose UI EditorDef a -> Compose UI EditorDef a@@ -133,7 +130,7 @@ e <- e a <- getCompose a let ea = horizontal (Single e) (editorDefLayout a)- return $ editorDef (editorDefTidings a) ea+ return $ EditorDef (editorDefTidings a) ea -- | Left-right composition of an element with a editor (|*) :: Compose UI EditorDef a -> UI Element -> Compose UI EditorDef a@@ -141,7 +138,7 @@ e <- e a <- getCompose a let ea = horizontal (editorDefLayout a) (Single e)- return $ editorDef (editorDefTidings a) ea+ return $ EditorDef (editorDefTidings a) ea -- | Top-down editor composition (-*-) :: Compose UI EditorDef (b -> a) -> Compose UI EditorDef b -> Compose UI EditorDef a@@ -149,7 +146,7 @@ a <- getCompose a b <- getCompose b let ab = vertical (editorDefLayout a) (editorDefLayout b)- return $ editorDef (editorDefTidings a <*> editorDefTidings b) ab+ return $ EditorDef (editorDefTidings a <*> editorDefTidings b) ab -- | Top-down composition of an element with a editor (*-) :: UI Element -> Compose UI EditorDef a -> Compose UI EditorDef a@@ -157,7 +154,7 @@ e <- e a <- getCompose a let ea = vertical (Single e) (editorDefLayout a)- return $ editorDef (editorDefTidings a) ea+ return $ EditorDef (editorDefTidings a) ea -- | Top-down composition of an element with a editor (-*) :: Compose UI EditorDef a -> UI Element -> Compose UI EditorDef a@@ -165,7 +162,7 @@ e <- e a <- getCompose a let ea = vertical (editorDefLayout a) (Single e)- return $ editorDef (editorDefTidings a) ea+ return $ EditorDef (editorDefTidings a) ea editorReadShow :: (Read a, Show a) => Behavior (Maybe a) -> Compose UI EditorDef (Maybe a) editorReadShow b = Compose $ do@@ -173,7 +170,7 @@ let readIt "" = Nothing readIt x = readMaybe x let t = tidings b (readIt <$> editedDef e)- return $ editorDef t (editorDefLayout e)+ return $ EditorDef t (editorDefLayout e) -- An editor that presents a choice of values. editorEnumBounded@@ -187,7 +184,7 @@ => 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)+ return $ EditorDef (tidings b (rumors $ userSelection l)) (Single $ getElement l) -- | Ignores 'Nothing' values and only updates for 'Just' values editorJust :: (Behavior (Maybe b) -> Compose UI EditorDef (Maybe b))@@ -196,13 +193,13 @@ editorJust editor b = Compose $ do e <- getCompose $ editor (Just <$> b) let ev = filterJust (editedDef e)- return $ editorDef (tidings b ev) (editorDefLayout e)+ return $ EditorDef (tidings b ev) (editorDefLayout e) -- | 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+ => (Layout -> Layout -> Layout) -> [(tag, Compose UI EditorDef a)] -> (a -> tag) -> Behavior a -> Compose UI EditorDef a+editorSum combineLayout options selector ba = Compose $ do options <- mapM (\(tag, Compose mk) -> (tag,) <$> (mk >>= runEditorDef)) options let tag = selector <$> ba tag' <- calmB tag@@ -213,14 +210,14 @@ nestedEditorDef <- new # sink children ((\x -> [maybe (error "editorSum") editorElement (build x)]) <$> tag') --- let composed = vertical (Single (getElement l)) (Single nestedEditorDef)+ let composed = combineLayout (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 $ 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+ return $ EditorDef (tidings ba editedE) composed -- | Returns a new behavior that only notifies for new values. calmB :: Eq a => Behavior a -> UI (Behavior a)@@ -252,7 +249,7 @@ instance Editable () where editor b = Compose $ do t <- new- return $ editorDef (tidings b never) (Single t)+ return $ EditorDef (tidings b never) (Single t) instance a ~ Char => Editable [a] where editor b = Compose $ do@@ -262,12 +259,12 @@ initialValue <- currentValue b _ <- runUI w $ set value initialValue (element t) return ()- return $ editorDef (userText t) (Single $ getElement t)+ return $ EditorDef (userText t) (Single $ getElement t) instance Editable Bool where editor b = Compose $ do t <- sink checked b $ input # set type_ "checkbox"- return $ editorDef (tidings b $ checkedChange t) (Single t)+ return $ EditorDef (tidings b $ checkedChange t) (Single t) instance Editable (Maybe Int) where editor = editorReadShow instance Editable (Maybe Double) where editor = editorReadShow
src/Graphics/UI/Threepenny/Editors/Profunctor.hs view
@@ -22,7 +22,6 @@ , Base.contents , EditorFactory(..) , createEditor- , liftEditor , Editable(..) -- ** Editor composition , (|*|), (|*), (*|)@@ -41,6 +40,10 @@ -- ** Generic editors , editorGeneric , editorGenericSimple+ -- ** Layouts+ , Base.Layout(Grid, Single)+ , Base.horizontal+ , Base.vertical )where import Data.Bifunctor@@ -61,11 +64,6 @@ { run :: Behavior a -> Compose UI Base.EditorDef b } -liftEditor :: (UI Element -> UI Element) -> EditorFactory a b -> EditorFactory a b-liftEditor f (EditorFactory run) = EditorFactory $ \b ->- case run b of- Compose uidef -> Compose $ fmap (Base.liftEditorDef f) uidef- -- | Create an editor to display the argument. -- User edits are fed back via the 'edited' 'Event'. createEditor :: EditorFactory b a -> Behavior b -> UI (Base.Editor a)@@ -139,10 +137,10 @@ -- | An editor for union types, built from editors for its constructors. editorSum :: (Show tag, Ord tag)- => [(tag, EditorFactory b b)] -> (b -> tag) -> EditorFactory b b-editorSum nested tagger = EditorFactory $ \b ->+ => (Base.Layout -> Base.Layout -> Base.Layout) -> [(tag, EditorFactory b b)] -> (b -> tag) -> EditorFactory b b+editorSum layout nested tagger = EditorFactory $ \b -> let nested' = [ (tag, run f b) | (tag, f) <- nested ]- in Base.editorSum nested' tagger b+ in Base.editorSum layout nested' tagger b instance Editable () where editor = EditorFactory Base.editor instance Editable String where editor = EditorFactory Base.editor@@ -198,7 +196,7 @@ (All (All Editable `And` All Default) xx) => DatatypeInfo xx -> EditorFactory (SOP I xx) (SOP I xx) editorGeneric' (ADT _ _ (c :* Nil)) = constructorEditorFor c-editorGeneric' (ADT _ _ cc) = editorSum editors constructor where+editorGeneric' (ADT _ _ cc) = editorSum Base.vertical editors constructor where editors :: [(Tag, EditorFactory (SOP I xx) (SOP I xx))] editors = map (first Tag) $ constructorEditorsFor cc constructors = hmap (K . constructorName) cc
threepenny-editors.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack name: threepenny-editors-version: 0.3.0+version: 0.4.0 synopsis: Composable algebraic editors description: This package provides a type class 'Editable' and combinators to easily put together form-like editors for algebraic datatypes.