mirror of
https://github.com/jtdaugherty/brick.git
synced 2024-09-11 15:55:54 +03:00
List: refactor rendering routine to only render the items in view (fixes #7)
- Changes renderList to expect an item height and all rendered items must match this height - Uses vector slicing to efficiently get the sub-list of items to be rendered - Renders 2 * H items at time instead of all N, where H is the height of the list's viewport
This commit is contained in:
parent
74aa344564
commit
693abbb345
@ -35,7 +35,7 @@ drawUI l = [ui]
|
||||
box = B.borderWithLabel label $
|
||||
hLimit 25 $
|
||||
vLimit 15 $
|
||||
L.renderList l listDrawElement
|
||||
L.renderList l listDrawElement 1
|
||||
ui = C.vCenter $ vBox [ C.hCenter box
|
||||
, " "
|
||||
, C.hCenter "Press +/- to add/remove list elements."
|
||||
|
@ -86,25 +86,41 @@ list name es =
|
||||
in List es selIndex name
|
||||
|
||||
-- | Turn a list state value into a widget given an item drawing
|
||||
-- function.
|
||||
renderList :: List e -> (Bool -> e -> Widget) -> Widget
|
||||
renderList l drawElem =
|
||||
-- function. The integer specifies the height, in rows, of the widgets
|
||||
-- returned by the item drawing function. All item widgets must be thism
|
||||
-- any rows high.
|
||||
renderList :: List e -> (Bool -> e -> Widget) -> Int -> Widget
|
||||
renderList l drawElem itemHeight =
|
||||
withDefAttr listAttr $
|
||||
viewport (l^.listNameL) Vertical $
|
||||
vBox $
|
||||
drawListElements l drawElem
|
||||
drawListElements l drawElem itemHeight
|
||||
|
||||
drawListElements :: List e -> (Bool -> e -> Widget) -> [Widget]
|
||||
drawListElements l drawElem = V.toList drawnElements
|
||||
where
|
||||
es = l^.listElementsL
|
||||
drawnElements = (flip V.imap) es $ \i e ->
|
||||
let isSelected = Just i == l^.listSelectedL
|
||||
elemWidget = drawElem isSelected e
|
||||
makeVisible = if isSelected
|
||||
then (visible . withDefAttr listSelectedAttr)
|
||||
else id
|
||||
in makeVisible elemWidget
|
||||
drawListElements :: List e -> (Bool -> e -> Widget) -> Int -> Widget
|
||||
drawListElements l drawElem itemHeight =
|
||||
Widget Fixed Fixed $ do
|
||||
c <- getContext
|
||||
|
||||
let es = V.slice start num (l^.listElementsL)
|
||||
idx = case l^.listSelectedL of
|
||||
Nothing -> 0
|
||||
Just i -> i
|
||||
|
||||
start = max 0 $ idx - numPerHeight + 1
|
||||
num = min (numPerHeight * 2) (V.length (l^.listElementsL) - start)
|
||||
numPerHeight = (c^.availHeightL) `div` itemHeight
|
||||
|
||||
off = start * itemHeight
|
||||
|
||||
drawnElements = (flip V.imap) es $ \i e ->
|
||||
let isSelected = Just (i + start) == l^.listSelectedL
|
||||
elemWidget = drawElem isSelected e
|
||||
makeVisible = if isSelected
|
||||
then (visible . withDefAttr listSelectedAttr)
|
||||
else id
|
||||
in makeVisible elemWidget
|
||||
|
||||
render $ viewport (l^.listNameL) Vertical $
|
||||
translateBy (Location (0, off)) $
|
||||
vBox $ V.toList drawnElements
|
||||
|
||||
-- | Insert an item into a list at the specified position.
|
||||
listInsert :: Int
|
||||
|
Loading…
Reference in New Issue
Block a user