simplify rendering for better ux
This commit is contained in:
		
							parent
							
								
									8f4246e716
								
							
						
					
					
						commit
						835352428a
					
				| @ -10,6 +10,7 @@ | ||||
| {-# LANGUAGE FlexibleInstances #-} | ||||
| {-# LANGUAGE MultiParamTypeClasses #-} | ||||
| {-# LANGUAGE TemplateHaskell   #-} | ||||
| {-# LANGUAGE BangPatterns #-} | ||||
| 
 | ||||
| module BrickMain where | ||||
| 
 | ||||
| @ -32,7 +33,6 @@ import Brick | ||||
|       AttrMap, | ||||
|       EventM, | ||||
|       Size(..), | ||||
|       Named(..), | ||||
|       Widget(..),  | ||||
|       ViewportType (Vertical),  | ||||
|       (<+>), | ||||
| @ -62,7 +62,7 @@ import           Data.IORef (IORef, readIORef, newIORef, writeIORef, modifyIORef | ||||
| import           Data.Vector                    ( Vector | ||||
|                                                  | ||||
|                                                 ) | ||||
| import           Data.Versions | ||||
| import           Data.Versions hiding (Lens') | ||||
| import           Haskus.Utils.Variant.Excepts | ||||
| import           Prelude                 hiding ( appendFile ) | ||||
| import           System.Exit | ||||
| @ -114,9 +114,6 @@ makeLensesFor [("sectionListFocusRing", "sectionListFocusRingL"), ("sectionListE | ||||
| 
 | ||||
| type SectionList n e = GenericSectionList n V.Vector e | ||||
| 
 | ||||
| instance Named (GenericSectionList n t e) n where | ||||
|     getName = sectionListName | ||||
| 
 | ||||
| 
 | ||||
| -- | Build a SectionList from nonempty list. If empty we could not defined sectionL lenses.  | ||||
| sectionList :: Foldable t  | ||||
| @ -206,29 +203,33 @@ handleGenericListEvent _ = pure () | ||||
| 
 | ||||
| -- This re-uses Brick.Widget.List.renderList | ||||
| renderSectionList :: (Traversable t, Ord n, Show n, Eq n, L.Splittable t) | ||||
|                   => (Bool -> n -> Widget n)             -- ^ Rendering function for separator between sections. True for selected before section | ||||
|                   -> (Bool -> n -> Widget n -> Widget n) -- ^ Rendering function for the borders. True for selected section | ||||
|                   -> (Bool -> e -> Widget n)             -- ^ Rendering function of the list element, True for the selected element | ||||
|                   => (Bool -> e -> Widget n)             -- ^ Rendering function of the list element, True for the selected element | ||||
|                   -> Bool                                -- ^ Whether the section list has focus | ||||
|                   -> GenericSectionList n t e            -- ^ The section list to render | ||||
|                   -> Widget n | ||||
| renderSectionList render_separator render_border render_elem section_focus (GenericSectionList focus elms sl_name) = | ||||
|   Widget Greedy Greedy $ render $ | ||||
|     Brick.viewport sl_name Vertical $ | ||||
|       V.foldl' (\wacc list -> | ||||
|                   let has_focus_list = is_focused_section list | ||||
|                       list_name = L.listName list | ||||
|                   in   wacc | ||||
|                     <=> render_separator has_focus_list list_name | ||||
|                     <=> inner_widget has_focus_list list_name list | ||||
|               ) | ||||
|               Brick.emptyWidget elms | ||||
|   where | ||||
|     is_focused_section l = section_focus && Just (L.listName l) == F.focusGetCurrent focus | ||||
|     inner_widget has_focus k l =  | ||||
|       let w = render_border has_focus k (Brick.vLimit (length l) $ L.renderList render_elem has_focus l) | ||||
|        in if has_focus then Brick.visible w else w | ||||
| 
 | ||||
| renderSectionList render_elem section_focus (GenericSectionList focus elms sl_name) = | ||||
|     Brick.Widget Brick.Greedy Brick.Greedy $ do | ||||
|         c <- Brick.getContext | ||||
|         let -- A section is focused if the whole thing is focused, and the inner list has focus | ||||
|             section_is_focused l = section_focus && (Just (L.listName l) == F.focusGetCurrent focus) | ||||
|             -- We need to limit the widget size when the length of the list is higher than the size of the terminal | ||||
|             limit = min (Brick.windowHeight c) (Brick.availHeight c) | ||||
|             s_idx = fromMaybe 0 $ V.findIndex section_is_focused elms | ||||
|             render_inner_list has_focus l = Brick.vLimit (length l) $ L.renderList (\b -> render_elem (b && has_focus)) has_focus l | ||||
|             (widget, off) =  | ||||
|                 V.ifoldl' (\wacc i list -> | ||||
|                                 let has_focus_list = section_is_focused list | ||||
|                                     (!acc_widget, !acc_off) = wacc | ||||
|                                     new_widget = if i == 0 then render_inner_list has_focus_list list else hBorder <=> render_inner_list has_focus_list list | ||||
|                                     new_off  | ||||
|                                         | i < s_idx  = 1 + L.listItemHeight list * length list  | ||||
|                                         | i == s_idx = 1 + L.listItemHeight list * fromMaybe 0 (L.listSelected list) | ||||
|                                         | otherwise  = 0 | ||||
|                                 in  (acc_widget <=> new_widget, acc_off + new_off) | ||||
|                                 ) | ||||
|                 (Brick.emptyWidget, 0) | ||||
|                 elms | ||||
|         Brick.render $  Brick.viewport sl_name Brick.Vertical $ Brick.translateBy (Brick.Location (0, min 0 (limit-off))) widget | ||||
| 
 | ||||
| -- | Equivalent to listSelectedElement | ||||
| sectionListSelectedElement :: (Eq n, L.Splittable t, Traversable t, Semigroup (t e)) => GenericSectionList n t e -> Maybe (Int, e) | ||||
| @ -243,7 +244,6 @@ sectionListSelectedElement generic_section_list = do | ||||
| 
 | ||||
| data Name = AllTools       -- The main list widget | ||||
|           | Singular Tool  -- The particular list for each tool | ||||
|           | IODialog       -- The pop up when installing a tool | ||||
|           | TutorialBox    -- The tutorial widget | ||||
|           deriving (Eq, Ord, Show) | ||||
| 
 | ||||
| @ -318,7 +318,7 @@ keyHandlers KeyBindings {..} = | ||||
|     ) | ||||
|   , (bUp, const "Up", appState %= moveCursor 1 Up) | ||||
|   , (bDown, const "Down", appState %= moveCursor 1 Down) | ||||
|   , (Vty.KChar 'x', const "Tutorial", mode .= Tutorial) | ||||
|   , (KeyCombination (Vty.KChar 'x') [], const "Tutorial", mode .= Tutorial) | ||||
|   ] | ||||
|  where | ||||
|   --hideShowHandler' :: (BrickSettings -> Bool) -> (BrickSettings -> Bool) -> m () | ||||
| @ -350,7 +350,7 @@ ui dimAttrs BrickState{ _appSettings = as@BrickSettings{}, ..} | ||||
|   = Brick.padBottom Max | ||||
|       ( Brick.withBorderStyle unicode | ||||
|         $ borderWithLabel (Brick.str "GHCup") | ||||
|           (center (header <=> renderList' _appState)) | ||||
|           (center (header <=> hBorder <=> renderList' _appState)) | ||||
|       ) | ||||
|     <=> footer | ||||
|  where | ||||
| @ -371,14 +371,12 @@ ui dimAttrs BrickState{ _appSettings = as@BrickSettings{}, ..} | ||||
|     let allElements = V.concatMap L.listElements $ sectionListElements bis | ||||
|         minTagSize = V.maximum $ V.map (length . intercalate "," . fmap tagToString . lTag) allElements | ||||
|         minVerSize = V.maximum $ V.map (\ListResult{..} -> T.length $ tVerToText (GHCTargetVersion lCross lVer)) allElements | ||||
|         render_separator _ _ = hBorder | ||||
|         render_border _ _ = id | ||||
|     in Brick.withDefAttr L.listAttr $ renderSectionList render_separator render_border (renderItem minTagSize minVerSize) True bis | ||||
|     in Brick.withDefAttr L.listAttr $ renderSectionList (renderItem minTagSize minVerSize) True bis | ||||
|   renderItem minTagSize minVerSize b listResult@ListResult{lTag = lTag', ..} = | ||||
|     let marks = if | ||||
|           | lSet       -> (Brick.withAttr (Brick.attrName "set") $ str setSign) | ||||
|           | lInstalled -> (Brick.withAttr (Brick.attrName "installed") $ str installedSign) | ||||
|           | otherwise  -> (Brick.withAttr (Brick.attrName "not-installed") $ str notInstalledSign) | ||||
|           | lSet       -> (Brick.withAttr (Brick.attrName "set") $ Brick.str setSign) | ||||
|           | lInstalled -> (Brick.withAttr (Brick.attrName "installed") $ Brick.str installedSign) | ||||
|           | otherwise  -> (Brick.withAttr (Brick.attrName "not-installed") $ Brick.str notInstalledSign) | ||||
|         ver = case lCross of | ||||
|           Nothing -> T.unpack . prettyVer $ lVer | ||||
|           Just c  -> T.unpack (c <> "-" <> prettyVer lVer) | ||||
| @ -529,7 +527,7 @@ navigationHandler ev = do | ||||
|   AppState { keyBindings = kb } <- liftIO $ readIORef settings' | ||||
|   case ev of | ||||
|     inner_event@(VtyEvent (Vty.EvKey key _)) -> | ||||
|       case find (\(key', _, _) -> key' == key) (keyHandlers kb) of | ||||
|       case find (\(key', _, _) -> key' == KeyCombination key []) (keyHandlers kb) of | ||||
|         Nothing -> void $ Brick.zoom (toLensVL appState) $ handleGenericListEvent inner_event | ||||
|         Just (_, _, handler) -> handler | ||||
|     inner_event -> Brick.zoom (toLensVL appState) $ handleGenericListEvent inner_event | ||||
| @ -611,7 +609,7 @@ replaceLR :: (ListResult -> Bool) | ||||
| replaceLR filterF list_result s = | ||||
|   let oldElem = s >>= sectionListSelectedElement -- Maybe (Int, e) | ||||
|       newVec  =  [(Singular $ lTool (head g), V.fromList g) | g <- groupBy ((==) `on` lTool ) (filter filterF list_result)] | ||||
|       newSectionList = sectionList AllTools newVec 0 | ||||
|       newSectionList = sectionList AllTools newVec 1 | ||||
|   in case oldElem of | ||||
|       Just (_, el) -> selectBy (lTool el) (toolEqual el) newSectionList | ||||
|       Nothing -> selectLatest newSectionList | ||||
| @ -631,7 +629,7 @@ filterVisible v e | lInstalled e = True | ||||
|                                   (Nightly `notElem` lTag e) | ||||
| 
 | ||||
| 
 | ||||
| install' :: (MonadReader AppState m, MonadIO m, MonadThrow m, MonadFail m, MonadMask m, MonadUnliftIO m) | ||||
| install' :: (MonadReader AppState m, MonadIO m, MonadThrow m, MonadFail m, MonadMask m, MonadUnliftIO m, Alternative m) | ||||
|          => (Int, ListResult) | ||||
|          -> m (Either String ()) | ||||
| install' (_, ListResult {..}) = do | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Luis Morillo
						Luis Morillo