packages feed

brick 0.7 → 0.8

raw patch · 7 files changed

+89/−13 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Brick.Widgets.Center: centerLayer :: Widget n -> Widget n
+ Brick.Widgets.Center: hCenterLayer :: Widget n -> Widget n
+ Brick.Widgets.Center: vCenterLayer :: Widget n -> Widget n
- Brick.Types: attrL :: Getting r Context Attr
+ Brick.Types: attrL :: forall r. Getting r Context Attr
- Brick.Types: cursorLocationL :: Lens' (CursorLocation n_anLE) Location
+ Brick.Types: cursorLocationL :: forall n_aw7h. Lens' (CursorLocation n_aw7h) Location
- Brick.Types: cursorLocationNameL :: Lens (CursorLocation n_anLE) (CursorLocation n_anUy) (Maybe n_anLE) (Maybe n_anUy)
+ Brick.Types: cursorLocationNameL :: forall n_aw7h n_awgq. Lens (CursorLocation n_aw7h) (CursorLocation n_awgq) (Maybe n_aw7h) (Maybe n_awgq)
- Brick.Types: cursorsL :: Lens (Result n_aqWI) (Result n_arsB) [CursorLocation n_aqWI] [CursorLocation n_arsB]
+ Brick.Types: cursorsL :: forall n_azJ4 n_aAvg. Lens (Result n_azJ4) (Result n_aAvg) [CursorLocation n_azJ4] [CursorLocation n_aAvg]
- Brick.Types: imageL :: Lens' (Result n_aqWI) Image
+ Brick.Types: imageL :: forall n_azJ4. Lens' (Result n_azJ4) Image
- Brick.Types: visibilityRequestsL :: Lens' (Result n_aqWI) [VisibilityRequest]
+ Brick.Types: visibilityRequestsL :: forall n_azJ4. Lens' (Result n_azJ4) [VisibilityRequest]
- Brick.Widgets.Dialog: dialogButtonsL :: Lens (Dialog a_aPc8) (Dialog a_aPcB) [(String, a_aPc8)] [(String, a_aPcB)]
+ Brick.Widgets.Dialog: dialogButtonsL :: forall a_a1545 a_a154F. Lens (Dialog a_a1545) (Dialog a_a154F) [(String, a_a1545)] [(String, a_a154F)]
- Brick.Widgets.Dialog: dialogSelectedIndexL :: Lens' (Dialog a_aPc8) (Maybe Int)
+ Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_a1545. Lens' (Dialog a_a1545) (Maybe Int)
- Brick.Widgets.Dialog: dialogTitleL :: Lens' (Dialog a_aPc8) (Maybe String)
+ Brick.Widgets.Dialog: dialogTitleL :: forall a_a1545. Lens' (Dialog a_a1545) (Maybe String)
- Brick.Widgets.Dialog: dialogWidthL :: Lens' (Dialog a_aPc8) Int
+ Brick.Widgets.Dialog: dialogWidthL :: forall a_a1545. Lens' (Dialog a_a1545) Int
- Brick.Widgets.Edit: editContentsL :: Lens' (Editor n_aQRZ) (TextZipper String)
+ Brick.Widgets.Edit: editContentsL :: forall n_a16WI. Lens' (Editor n_a16WI) (TextZipper String)
- Brick.Widgets.Edit: editDrawContentsL :: Lens' (Editor n_aQRZ) ([String] -> Widget n_aQRZ)
+ Brick.Widgets.Edit: editDrawContentsL :: forall n_a16WI. Lens' (Editor n_a16WI) ([String] -> Widget n_a16WI)
- Brick.Widgets.List: listElementsL :: Lens (List n_aVFe e_aVFf) (List n_aVFe e_aVMq) (Vector e_aVFf) (Vector e_aVMq)
+ Brick.Widgets.List: listElementsL :: forall n_a1f4A e_a1f4B e_a1fc7. Lens (List n_a1f4A e_a1f4B) (List n_a1f4A e_a1fc7) (Vector e_a1f4B) (Vector e_a1fc7)
- Brick.Widgets.List: listItemHeightL :: Lens' (List n_aVFe e_aVFf) Int
+ Brick.Widgets.List: listItemHeightL :: forall n_a1f4A e_a1f4B. Lens' (List n_a1f4A e_a1f4B) Int
- Brick.Widgets.List: listNameL :: Lens (List n_aVFe e_aVFf) (List n_aVMr e_aVFf) n_aVFe n_aVMr
+ Brick.Widgets.List: listNameL :: forall n_a1f4A e_a1f4B n_a1fc8. Lens (List n_a1f4A e_a1f4B) (List n_a1fc8 e_a1f4B) n_a1f4A n_a1fc8
- Brick.Widgets.List: listSelectedL :: Lens' (List n_aVFe e_aVFf) (Maybe Int)
+ Brick.Widgets.List: listSelectedL :: forall n_a1f4A e_a1f4B. Lens' (List n_a1f4A e_a1f4B) (Maybe Int)

Files

CHANGELOG.md view
@@ -2,6 +2,24 @@ Brick changelog --------------- +0.8+---++API changes:+ * Center: added layer-friendly centering functions centerLayer,+   hCenterLayer, and vCenterLayer.++Functionality changes:+ * Dialog now uses new layer-friendly centering functions. This makes it+   possible to overlay a Dialog on top of your UI when you use a Dialog+   rendering as a separate layer.+ * Updated the LayerDemo to demonstrate a centered layer.+ * The renderer now uses a default Vty Picture background+   of spaces with the default attribute, rather than using+   ClearBackground (the Vty default). This is to compensate for an+   unexpected attribute behavior in Vty when ClearBackgrounds (see+   https://github.com/coreyoconnor/vty/issues/95)+ 0.7 --- @@ -34,8 +52,7 @@    The Editor uses the following attributes now:    * When not focused, the widget is rendered with editAttr.    * When focused, the widget is rendered with editFocusedAttr.- * The Dialog's name type parameter, constructor parameter, and lens-   were removed.+ * The Dialog's name constructor parameter and lens were removed.  * The 'viewport' function was modified to raise a runtime exception if    the widget name it receives is used more than once during the    rendering of a single frame.
brick.cabal view
@@ -1,5 +1,5 @@ name:                brick-version:             0.7+version:             0.8 synopsis:            A declarative terminal user interface library description:   Write terminal applications painlessly with 'brick'! You write an@@ -10,7 +10,7 @@   >   > import Brick   >-  > ui :: Widget+  > ui :: Widget n   > ui = str "Hello, world!"   >   > main :: IO ()
docs/guide.rst view
@@ -473,7 +473,7 @@   name clashes could arise if two widgets used the same name. But those   clashes would not be easy to observe. - String names are not amenable to safe refactoring since an "invalid"-  name could be used and silently fail to cuause the desired behavior at+  name could be used and silently fail to cause the desired behavior at   runtime. - String names are not amenable to compile-time checking when being   matched; a custom type allows the user to do compile-time checking of@@ -485,7 +485,7 @@ Although requiring the user to provide a custom name type means that more work must be done to manage the set of possible names, this is work that should have been done up front anyway: ``String`` names could be-allocated ad-hoc but never centrally managed, resulting in troulbesome+allocated ad-hoc but never centrally managed, resulting in troublesome runtime problems.  A Note of Caution@@ -493,7 +493,7 @@  **NOTE: Unique names for all named widgets are required to ensure that the renderer correctly tracks widget states during application-execution.** If you assign the same name two, say, two viewports, they+execution.** If you assign the same name to, say, two viewports, they will both use the same viewport scrolling state! So unless you want that and know what you are doing, use a unique name for every widget that needs one.@@ -571,7 +571,7 @@ characters ("``|``") one column wide. The vertical border widget is designed to take up however many rows it was given, but rendering the box layout algorithm has to be careful about rendering such ``Greedy``-widgets because the won't leave room for anything else. Since the box+widgets because they won't leave room for anything else. Since the box widget cannot know the sizes of its sub-widgets until they are rendered, the ``Fixed`` widgets get rendered and their sizes are used to determine how much space is left for ``Greedy`` widgets.
programs/LayerDemo.hs view
@@ -12,6 +12,7 @@ import Brick.Types (rowL, columnL, Widget) import qualified Brick.Main as M import qualified Brick.Widgets.Border as B+import qualified Brick.Widgets.Center as C import Brick.Widgets.Core   ( translateBy   , str@@ -26,7 +27,9 @@  drawUi :: St -> [Widget ()] drawUi st =-    [ topLayer st+    [ C.centerLayer $+      B.border $ str "This layer is centered but other\nlayers are visible underneath it."+    , topLayer st     , bottomLayer st     ] 
src/Brick/Widgets/Center.hs view
@@ -3,12 +3,15 @@   ( -- * Centering horizontally     hCenter   , hCenterWith+  , hCenterLayer   -- * Centering vertically   , vCenter   , vCenterWith+  , vCenterLayer   -- * Centering both horizontally and vertically   , center   , centerWith+  , centerLayer   -- * Centering about an arbitrary origin   , centerAbout   )@@ -16,7 +19,8 @@  import Lens.Micro ((^.), (&), (.~), to) import Data.Maybe (fromMaybe)-import Graphics.Vty (imageWidth, imageHeight, horizCat, charFill, vertCat)+import Graphics.Vty (imageWidth, imageHeight, horizCat, charFill, vertCat,+                    translateX, translateY)  import Brick.Types import Brick.Widgets.Core@@ -26,6 +30,25 @@ hCenter :: Widget n -> Widget n hCenter = hCenterWith Nothing +-- | Center the specified widget horizontally using a Vty image+-- translation. Consumes all available horizontal space. Unlike hCenter,+-- this does not fill the surrounding space so it is suitable for use+-- as a layer. Layers underneath this widget will be visible in regions+-- surrounding the centered widget.+hCenterLayer :: Widget n -> Widget n+hCenterLayer p =+    Widget Greedy (vSize p) $ do+        result <- render p+        c <- getContext+        let rWidth = result^.imageL.to imageWidth+            leftPaddingAmount = max 0 $ (c^.availWidthL - rWidth) `div` 2+            paddedImage = translateX leftPaddingAmount $ result^.imageL+            off = Location (leftPaddingAmount, 0)+        if leftPaddingAmount == 0 then+            return result else+            return $ addResultOffset off+                   $ result & imageL .~ paddedImage+ -- | Center the specified widget horizontally. Consumes all available -- horizontal space. Uses the specified character to fill in the space -- to either side of the centered widget (defaults to space).@@ -56,6 +79,25 @@ vCenter :: Widget n -> Widget n vCenter = vCenterWith Nothing +-- | Center the specified widget vertically using a Vty image+-- translation. Consumes all available vertical space. Unlike vCenter,+-- this does not fill the surrounding space so it is suitable for use+-- as a layer. Layers underneath this widget will be visible in regions+-- surrounding the centered widget.+vCenterLayer :: Widget n -> Widget n+vCenterLayer p =+    Widget (hSize p) Greedy $ do+        result <- render p+        c <- getContext+        let rHeight = result^.imageL.to imageHeight+            topPaddingAmount = max 0 $ (c^.availHeightL - rHeight) `div` 2+            paddedImage = translateY topPaddingAmount $ result^.imageL+            off = Location (0, topPaddingAmount)+        if topPaddingAmount == 0 then+            return result else+            return $ addResultOffset off+                   $ result & imageL .~ paddedImage+ -- | Center a widget vertically. Consumes all vertical space. Uses the -- specified character to fill in the space above and below the centered -- widget (defaults to space).@@ -92,6 +134,14 @@ -- to fill in the space around the centered widget (defaults to space). centerWith :: Maybe Char -> Widget n -> Widget n centerWith c = vCenterWith c . hCenterWith c++-- | Center a widget both vertically and horizontally using a Vty image+-- translation. Consumes all available vertical and horizontal space.+-- Unlike center, this does not fill in the surrounding space with a+-- character so it is usable as a layer. Any widget underneath this one+-- will be visible in the region surrounding the centered widget.+centerLayer :: Widget n -> Widget n+centerLayer = vCenterLayer . hCenterLayer  -- | Center the widget horizontally and vertically about the specified -- origin.
src/Brick/Widgets/Dialog.hs view
@@ -101,7 +101,10 @@ buttonSelectedAttr :: AttrName buttonSelectedAttr = buttonAttr <> "selected" --- | Render a dialog with the specified body widget.+-- | Render a dialog with the specified body widget. This renders the+-- dialog as a layer, which makes this suitable as a top-level layer in+-- your rendering function to be rendered on top of the rest of your+-- interface. renderDialog :: Dialog a -> Widget n -> Widget n renderDialog d body =     let buttonPadding = str "   "@@ -113,7 +116,7 @@                          mkButton <$> (zip [0..] (d^.dialogButtonsL))          doBorder = maybe border borderWithLabel (str <$> d^.dialogTitleL)-    in center $+    in centerLayer $        withDefAttr dialogAttr $        hLimit (d^.dialogWidthL) $        doBorder $
src/Brick/Widgets/Internal.hs view
@@ -26,13 +26,16 @@             -> ([CursorLocation n] -> Maybe (CursorLocation n))             -> RenderState n             -> (RenderState n, V.Picture, Maybe (CursorLocation n))-renderFinal aMap layerRenders sz chooseCursor rs = (newRS, pic, theCursor)+renderFinal aMap layerRenders sz chooseCursor rs = (newRS, picWithBg, theCursor)     where         (layerResults, !newRS) = flip runState rs $ sequence $             (\p -> runReaderT p ctx) <$>             (render <$> cropToContext <$> layerRenders)         ctx = Context def (fst sz) (snd sz) def aMap         pic = V.picForLayers $ uncurry V.resize sz <$> (^.imageL) <$> layerResults+        -- picWithBg is a workaround for runaway attributes.+        -- See https://github.com/coreyoconnor/vty/issues/95+        picWithBg = pic { V.picBackground = V.Background ' ' V.defAttr }         layerCursors = (^.cursorsL) <$> layerResults         theCursor = chooseCursor $ concat layerCursors