ui: refactor, simplify, flatten screen types
This commit is contained in:
parent
e6b1d2d5a7
commit
8bda78a447
@ -5,12 +5,11 @@
|
|||||||
|
|
||||||
module Hledger.UI.AccountsScreen
|
module Hledger.UI.AccountsScreen
|
||||||
(accountsScreen
|
(accountsScreen
|
||||||
,initAccountsScreen
|
,asInit
|
||||||
,asSetSelectedAccount
|
,asSetSelectedAccount
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
import Lens.Micro ((^.))
|
|
||||||
-- import Control.Monad
|
-- import Control.Monad
|
||||||
import Control.Monad.IO.Class (liftIO)
|
import Control.Monad.IO.Class (liftIO)
|
||||||
-- import Data.Default
|
-- import Data.Default
|
||||||
@ -28,7 +27,7 @@ import Brick.Widgets.List
|
|||||||
import Brick.Widgets.Edit
|
import Brick.Widgets.Edit
|
||||||
import Brick.Widgets.Border (borderAttr)
|
import Brick.Widgets.Border (borderAttr)
|
||||||
-- import Brick.Widgets.Center
|
-- import Brick.Widgets.Center
|
||||||
import Lens.Micro ((.~), (&))
|
import Lens.Micro
|
||||||
|
|
||||||
import Hledger
|
import Hledger
|
||||||
import Hledger.Cli hiding (progname,prognameandversion,green)
|
import Hledger.Cli hiding (progname,prognameandversion,green)
|
||||||
@ -42,24 +41,20 @@ import Hledger.UI.ErrorScreen
|
|||||||
|
|
||||||
accountsScreen :: Screen
|
accountsScreen :: Screen
|
||||||
accountsScreen = AccountsScreen{
|
accountsScreen = AccountsScreen{
|
||||||
_asState = AccountsScreenState{_asItems=list "accounts" V.empty 1
|
sInit = asInit
|
||||||
,_asSelectedAccount=""
|
,sDraw = asDraw
|
||||||
}
|
,sHandle = asHandle
|
||||||
,sInitFn = initAccountsScreen
|
,_asList = list "accounts" V.empty 1
|
||||||
,sDrawFn = drawAccountsScreen
|
,_asSelectedAccount = ""
|
||||||
,sHandleFn = handleAccountsScreen
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asSetSelectedAccount a s@AccountsScreen{} = s & asState . asSelectedAccount .~ a
|
asInit :: Day -> Bool -> AppState -> AppState
|
||||||
asSetSelectedAccount _ s = s
|
asInit d reset st@AppState{
|
||||||
|
|
||||||
initAccountsScreen :: Day -> Bool -> AppState -> AppState
|
|
||||||
initAccountsScreen d reset st@AppState{
|
|
||||||
aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}},
|
aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}},
|
||||||
ajournal=j,
|
ajournal=j,
|
||||||
aScreen=s@AccountsScreen{}
|
aScreen=s@AccountsScreen{}
|
||||||
} =
|
} =
|
||||||
st{aopts=uopts', aScreen=s & asState . asItems .~ newitems'}
|
st{aopts=uopts', aScreen=s & asList .~ newitems'}
|
||||||
where
|
where
|
||||||
newitems = list (Name "accounts") (V.fromList displayitems) 1
|
newitems = list (Name "accounts") (V.fromList displayitems) 1
|
||||||
|
|
||||||
@ -67,7 +62,7 @@ initAccountsScreen d reset st@AppState{
|
|||||||
-- (may need to move to the next leaf account when entering flat mode)
|
-- (may need to move to the next leaf account when entering flat mode)
|
||||||
newitems' = listMoveTo selidx newitems
|
newitems' = listMoveTo selidx newitems
|
||||||
where
|
where
|
||||||
selidx = case (reset, listSelectedElement $ s ^. asState . asItems) of
|
selidx = case (reset, listSelectedElement $ s ^. asList) of
|
||||||
(True, _) -> 0
|
(True, _) -> 0
|
||||||
(_, Nothing) -> 0
|
(_, Nothing) -> 0
|
||||||
(_, Just (_,AccountsScreenItem{asItemAccountName=a})) -> fromMaybe (fromMaybe 0 mprefixmatch) mexactmatch
|
(_, Just (_,AccountsScreenItem{asItemAccountName=a})) -> fromMaybe (fromMaybe 0 mprefixmatch) mexactmatch
|
||||||
@ -104,10 +99,10 @@ initAccountsScreen d reset st@AppState{
|
|||||||
displayitems = map displayitem items
|
displayitems = map displayitem items
|
||||||
|
|
||||||
|
|
||||||
initAccountsScreen _ _ _ = error "init function called with wrong screen type, should not happen"
|
asInit _ _ _ = error "init function called with wrong screen type, should not happen"
|
||||||
|
|
||||||
drawAccountsScreen :: AppState -> [Widget]
|
asDraw :: AppState -> [Widget]
|
||||||
drawAccountsScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}
|
asDraw AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}
|
||||||
,ajournal=j
|
,ajournal=j
|
||||||
,aScreen=s@AccountsScreen{}
|
,aScreen=s@AccountsScreen{}
|
||||||
,aMinibuffer=mbuf} =
|
,aMinibuffer=mbuf} =
|
||||||
@ -142,10 +137,10 @@ drawAccountsScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}
|
|||||||
fs -> str " with " <+> withAttr (borderAttr <> "query") (str $ intercalate ", " fs) <+> str " txns"
|
fs -> str " with " <+> withAttr (borderAttr <> "query") (str $ intercalate ", " fs) <+> str " txns"
|
||||||
nonzero | empty_ ropts = str ""
|
nonzero | empty_ ropts = str ""
|
||||||
| otherwise = withAttr (borderAttr <> "query") (str " nonzero")
|
| otherwise = withAttr (borderAttr <> "query") (str " nonzero")
|
||||||
cur = str (case s ^. asState . asItems ^. listSelectedL of -- XXX second ^. required here but not below..
|
cur = str (case s ^. asList ^. listSelectedL of -- XXX second ^. required here but not below..
|
||||||
Nothing -> "-"
|
Nothing -> "-"
|
||||||
Just i -> show (i + 1))
|
Just i -> show (i + 1))
|
||||||
total = str $ show $ V.length $ s ^. asState . asItems . listElementsL
|
total = str $ show $ V.length $ s ^. asList . listElementsL
|
||||||
|
|
||||||
bottomlabel = borderKeysStr [
|
bottomlabel = borderKeysStr [
|
||||||
-- ("up/down/pgup/pgdown/home/end", "move")
|
-- ("up/down/pgup/pgdown/home/end", "move")
|
||||||
@ -174,7 +169,7 @@ drawAccountsScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}
|
|||||||
-- ltrace "availwidth" $
|
-- ltrace "availwidth" $
|
||||||
c^.availWidthL
|
c^.availWidthL
|
||||||
- 2 -- XXX due to margin ? shouldn't be necessary (cf UIUtils)
|
- 2 -- XXX due to margin ? shouldn't be necessary (cf UIUtils)
|
||||||
displayitems = s ^. asState . asItems . listElementsL
|
displayitems = s ^. asList . listElementsL
|
||||||
maxacctwidthseen =
|
maxacctwidthseen =
|
||||||
-- ltrace "maxacctwidthseen" $
|
-- ltrace "maxacctwidthseen" $
|
||||||
V.maximum $
|
V.maximum $
|
||||||
@ -202,12 +197,12 @@ drawAccountsScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}
|
|||||||
|
|
||||||
colwidths = (acctwidth, balwidth)
|
colwidths = (acctwidth, balwidth)
|
||||||
|
|
||||||
render $ defaultLayout toplabel bottomarea $ renderList (s ^. asState . asItems) (drawAccountsItem colwidths)
|
render $ defaultLayout toplabel bottomarea $ renderList (s ^. asList) (asDrawItem colwidths)
|
||||||
|
|
||||||
drawAccountsScreen _ = error "draw function called with wrong screen type, should not happen"
|
asDraw _ = error "draw function called with wrong screen type, should not happen"
|
||||||
|
|
||||||
drawAccountsItem :: (Int,Int) -> Bool -> AccountsScreenItem -> Widget
|
asDrawItem :: (Int,Int) -> Bool -> AccountsScreenItem -> Widget
|
||||||
drawAccountsItem (acctwidth, balwidth) selected AccountsScreenItem{..} =
|
asDrawItem (acctwidth, balwidth) selected AccountsScreenItem{..} =
|
||||||
Widget Greedy Fixed $ do
|
Widget Greedy Fixed $ do
|
||||||
-- c <- getContext
|
-- c <- getContext
|
||||||
-- let showitem = intercalate "\n" . balanceReportItemAsText defreportopts fmt
|
-- let showitem = intercalate "\n" . balanceReportItemAsText defreportopts fmt
|
||||||
@ -233,8 +228,8 @@ drawAccountsItem (acctwidth, balwidth) selected AccountsScreenItem{..} =
|
|||||||
sel | selected = (<> "selected")
|
sel | selected = (<> "selected")
|
||||||
| otherwise = id
|
| otherwise = id
|
||||||
|
|
||||||
handleAccountsScreen :: AppState -> Vty.Event -> EventM (Next AppState)
|
asHandle :: AppState -> Vty.Event -> EventM (Next AppState)
|
||||||
handleAccountsScreen st@AppState{
|
asHandle st'@AppState{
|
||||||
aScreen=scr@AccountsScreen{..}
|
aScreen=scr@AccountsScreen{..}
|
||||||
,aopts=UIOpts{cliopts_=copts}
|
,aopts=UIOpts{cliopts_=copts}
|
||||||
,ajournal=j
|
,ajournal=j
|
||||||
@ -245,55 +240,52 @@ handleAccountsScreen st@AppState{
|
|||||||
-- let h = c^.availHeightL
|
-- let h = c^.availHeightL
|
||||||
-- moveSel n l = listMoveBy n l
|
-- moveSel n l = listMoveBy n l
|
||||||
|
|
||||||
-- before we go anywhere, remember the currently selected account.
|
-- save the currently selected account, in case we leave this screen and lose the selection
|
||||||
-- (This is preserved across screen changes, unlike List's selection state)
|
|
||||||
let
|
let
|
||||||
selacct = case listSelectedElement $ scr ^. asState . asItems of
|
selacct = case listSelectedElement $ scr ^. asList of
|
||||||
Just (_, AccountsScreenItem{..}) -> asItemAccountName
|
Just (_, AccountsScreenItem{..}) -> asItemAccountName
|
||||||
Nothing -> scr ^. asState . asSelectedAccount
|
Nothing -> scr ^. asSelectedAccount
|
||||||
st' = st{aScreen=scr & asState . asSelectedAccount .~ selacct}
|
st = st'{aScreen=scr & asSelectedAccount .~ selacct}
|
||||||
|
|
||||||
case mbuf of
|
case mbuf of
|
||||||
Nothing ->
|
Nothing ->
|
||||||
|
|
||||||
case ev of
|
case ev of
|
||||||
Vty.EvKey (Vty.KChar 'q') [] -> halt st'
|
Vty.EvKey (Vty.KChar 'q') [] -> halt st
|
||||||
-- Vty.EvKey (Vty.KChar 'l') [Vty.MCtrl] -> do
|
-- Vty.EvKey (Vty.KChar 'l') [Vty.MCtrl] -> do
|
||||||
Vty.EvKey Vty.KEsc [] -> continue $ resetScreens d st'
|
Vty.EvKey Vty.KEsc [] -> continue $ resetScreens d st
|
||||||
Vty.EvKey (Vty.KChar 'g') [] -> liftIO (stReloadJournalIfChanged copts d j st') >>= continue
|
Vty.EvKey (Vty.KChar 'g') [] -> liftIO (stReloadJournalIfChanged copts d j st) >>= continue
|
||||||
Vty.EvKey (Vty.KChar '-') [] -> continue $ regenerateScreens j d $ decDepth st'
|
Vty.EvKey (Vty.KChar '-') [] -> continue $ regenerateScreens j d $ decDepth st
|
||||||
Vty.EvKey (Vty.KChar '+') [] -> continue $ regenerateScreens j d $ incDepth st'
|
Vty.EvKey (Vty.KChar '+') [] -> continue $ regenerateScreens j d $ incDepth st
|
||||||
Vty.EvKey (Vty.KChar '=') [] -> continue $ regenerateScreens j d $ incDepth st'
|
Vty.EvKey (Vty.KChar '=') [] -> continue $ regenerateScreens j d $ incDepth st
|
||||||
Vty.EvKey (Vty.KChar '1') [] -> continue $ regenerateScreens j d $ setDepth 1 st'
|
Vty.EvKey (Vty.KChar '1') [] -> continue $ regenerateScreens j d $ setDepth 1 st
|
||||||
Vty.EvKey (Vty.KChar '2') [] -> continue $ regenerateScreens j d $ setDepth 2 st'
|
Vty.EvKey (Vty.KChar '2') [] -> continue $ regenerateScreens j d $ setDepth 2 st
|
||||||
Vty.EvKey (Vty.KChar '3') [] -> continue $ regenerateScreens j d $ setDepth 3 st'
|
Vty.EvKey (Vty.KChar '3') [] -> continue $ regenerateScreens j d $ setDepth 3 st
|
||||||
Vty.EvKey (Vty.KChar '4') [] -> continue $ regenerateScreens j d $ setDepth 4 st'
|
Vty.EvKey (Vty.KChar '4') [] -> continue $ regenerateScreens j d $ setDepth 4 st
|
||||||
Vty.EvKey (Vty.KChar '5') [] -> continue $ regenerateScreens j d $ setDepth 5 st'
|
Vty.EvKey (Vty.KChar '5') [] -> continue $ regenerateScreens j d $ setDepth 5 st
|
||||||
Vty.EvKey (Vty.KChar '6') [] -> continue $ regenerateScreens j d $ setDepth 6 st'
|
Vty.EvKey (Vty.KChar '6') [] -> continue $ regenerateScreens j d $ setDepth 6 st
|
||||||
Vty.EvKey (Vty.KChar '7') [] -> continue $ regenerateScreens j d $ setDepth 7 st'
|
Vty.EvKey (Vty.KChar '7') [] -> continue $ regenerateScreens j d $ setDepth 7 st
|
||||||
Vty.EvKey (Vty.KChar '8') [] -> continue $ regenerateScreens j d $ setDepth 8 st'
|
Vty.EvKey (Vty.KChar '8') [] -> continue $ regenerateScreens j d $ setDepth 8 st
|
||||||
Vty.EvKey (Vty.KChar '9') [] -> continue $ regenerateScreens j d $ setDepth 9 st'
|
Vty.EvKey (Vty.KChar '9') [] -> continue $ regenerateScreens j d $ setDepth 9 st
|
||||||
Vty.EvKey (Vty.KChar '0') [] -> continue $ regenerateScreens j d $ setDepth 0 st'
|
Vty.EvKey (Vty.KChar '0') [] -> continue $ regenerateScreens j d $ setDepth 0 st
|
||||||
Vty.EvKey (Vty.KChar 'F') [] -> continue $ regenerateScreens j d $ stToggleFlat st'
|
Vty.EvKey (Vty.KChar 'F') [] -> continue $ regenerateScreens j d $ stToggleFlat st
|
||||||
Vty.EvKey (Vty.KChar 'E') [] -> scrollTop >> (continue $ regenerateScreens j d $ stToggleEmpty st')
|
Vty.EvKey (Vty.KChar 'E') [] -> scrollTop >> (continue $ regenerateScreens j d $ stToggleEmpty st)
|
||||||
Vty.EvKey (Vty.KChar 'C') [] -> scrollTop >> (continue $ regenerateScreens j d $ stToggleCleared st')
|
Vty.EvKey (Vty.KChar 'C') [] -> scrollTop >> (continue $ regenerateScreens j d $ stToggleCleared st)
|
||||||
Vty.EvKey (Vty.KChar 'U') [] -> scrollTop >> (continue $ regenerateScreens j d $ stToggleUncleared st')
|
Vty.EvKey (Vty.KChar 'U') [] -> scrollTop >> (continue $ regenerateScreens j d $ stToggleUncleared st)
|
||||||
Vty.EvKey (Vty.KChar 'R') [] -> scrollTop >> (continue $ regenerateScreens j d $ stToggleReal st')
|
Vty.EvKey (Vty.KChar 'R') [] -> scrollTop >> (continue $ regenerateScreens j d $ stToggleReal st)
|
||||||
Vty.EvKey k [] | k `elem` [Vty.KChar '/'] -> continue $ regenerateScreens j d $ stShowMinibuffer st'
|
Vty.EvKey k [] | k `elem` [Vty.KChar '/'] -> continue $ regenerateScreens j d $ stShowMinibuffer st
|
||||||
Vty.EvKey k [] | k `elem` [Vty.KBS, Vty.KDel] -> (continue $ regenerateScreens j d $ stResetFilter st')
|
Vty.EvKey k [] | k `elem` [Vty.KBS, Vty.KDel] -> (continue $ regenerateScreens j d $ stResetFilter st)
|
||||||
Vty.EvKey (Vty.KLeft) [] -> continue $ popScreen st'
|
Vty.EvKey (Vty.KLeft) [] -> continue $ popScreen st
|
||||||
Vty.EvKey (k) [] | k `elem` [Vty.KRight, Vty.KEnter] -> do
|
Vty.EvKey (k) [] | k `elem` [Vty.KRight, Vty.KEnter] -> scrollTopRegister >> continue (screenEnter d scr st)
|
||||||
let
|
where
|
||||||
scr = rsSetCurrentAccount selacct registerScreen
|
scr = rsSetAccount selacct registerScreen
|
||||||
st'' = screenEnter d scr st'
|
|
||||||
scrollTopRegister
|
|
||||||
continue st''
|
|
||||||
|
|
||||||
-- fall through to the list's event handler (handles up/down)
|
-- fall through to the list's event handler (handles up/down)
|
||||||
ev -> do
|
ev -> do
|
||||||
newitems <- handleEvent ev (scr ^. asState . asItems)
|
newitems <- handleEvent ev (scr ^. asList)
|
||||||
continue $ st'{aScreen=scr & asState . asItems .~ newitems
|
continue $ st'{aScreen=scr & asList .~ newitems
|
||||||
& asState . asSelectedAccount .~ selacct}
|
& asSelectedAccount .~ selacct
|
||||||
|
}
|
||||||
-- continue =<< handleEventLensed st' someLens ev
|
-- continue =<< handleEventLensed st' someLens ev
|
||||||
|
|
||||||
Just ed ->
|
Just ed ->
|
||||||
@ -313,42 +305,8 @@ handleAccountsScreen st@AppState{
|
|||||||
scrollTop = vScrollToBeginning $ viewportScroll "accounts"
|
scrollTop = vScrollToBeginning $ viewportScroll "accounts"
|
||||||
scrollTopRegister = vScrollToBeginning $ viewportScroll "register"
|
scrollTopRegister = vScrollToBeginning $ viewportScroll "register"
|
||||||
|
|
||||||
handleAccountsScreen _ _ = error "event handler called with wrong screen type, should not happen"
|
asHandle _ _ = error "event handler called with wrong screen type, should not happen"
|
||||||
|
|
||||||
-- | Get the maximum account depth in the current journal.
|
asSetSelectedAccount a s@AccountsScreen{} = s & asSelectedAccount .~ a
|
||||||
maxDepth :: AppState -> Int
|
asSetSelectedAccount _ s = s
|
||||||
maxDepth AppState{ajournal=j} = maximum $ map accountNameLevel $ journalAccountNames j
|
|
||||||
|
|
||||||
-- | Decrement the current depth limit towards 0. If there was no depth limit,
|
|
||||||
-- set it to one less than the maximum account depth.
|
|
||||||
decDepth :: AppState -> AppState
|
|
||||||
decDepth st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts@ReportOpts{..}}}}
|
|
||||||
= st{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=dec depth_}}}}
|
|
||||||
where
|
|
||||||
dec (Just d) = Just $ max 0 (d-1)
|
|
||||||
dec Nothing = Just $ maxDepth st - 1
|
|
||||||
|
|
||||||
-- | Increment the current depth limit. If this makes it equal to the
|
|
||||||
-- the maximum account depth, remove the depth limit.
|
|
||||||
incDepth :: AppState -> AppState
|
|
||||||
incDepth st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts@ReportOpts{..}}}}
|
|
||||||
= st{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=inc depth_}}}}
|
|
||||||
where
|
|
||||||
inc (Just d) | d < (maxDepth st - 1) = Just $ d+1
|
|
||||||
inc _ = Nothing
|
|
||||||
|
|
||||||
-- | Set the current depth limit to the specified depth, which should
|
|
||||||
-- be a positive number. If it is zero, or equal to or greater than the
|
|
||||||
-- current maximum account depth, the depth limit will be removed.
|
|
||||||
-- (Slight inconsistency here: zero is currently a valid display depth
|
|
||||||
-- which can be reached using the - key. But we need a key to remove
|
|
||||||
-- the depth limit, and 0 is it.)
|
|
||||||
setDepth :: Int -> AppState -> AppState
|
|
||||||
setDepth depth st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}}
|
|
||||||
= st{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=mdepth'}}}}
|
|
||||||
where
|
|
||||||
mdepth' | depth < 0 = depth_ ropts
|
|
||||||
| depth == 0 = Nothing
|
|
||||||
| depth >= maxDepth st = Nothing
|
|
||||||
| otherwise = Just depth
|
|
||||||
|
|
||||||
|
|||||||
@ -30,19 +30,19 @@ import Hledger.UI.UIUtils
|
|||||||
|
|
||||||
errorScreen :: Screen
|
errorScreen :: Screen
|
||||||
errorScreen = ErrorScreen{
|
errorScreen = ErrorScreen{
|
||||||
esState = ErrorScreenState{esError=""}
|
sInit = esInit
|
||||||
,sInitFn = initErrorScreen
|
,sDraw = esDraw
|
||||||
,sDrawFn = drawErrorScreen
|
,sHandle = esHandle
|
||||||
,sHandleFn = handleErrorScreen
|
,esError = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
initErrorScreen :: Day -> Bool -> AppState -> AppState
|
esInit :: Day -> Bool -> AppState -> AppState
|
||||||
initErrorScreen _ _ st@AppState{aScreen=ErrorScreen{}} = st
|
esInit _ _ st@AppState{aScreen=ErrorScreen{}} = st
|
||||||
initErrorScreen _ _ _ = error "init function called with wrong screen type, should not happen"
|
esInit _ _ _ = error "init function called with wrong screen type, should not happen"
|
||||||
|
|
||||||
drawErrorScreen :: AppState -> [Widget]
|
esDraw :: AppState -> [Widget]
|
||||||
drawErrorScreen AppState{ -- aopts=_uopts@UIOpts{cliopts_=_copts@CliOpts{reportopts_=_ropts@ReportOpts{query_=querystr}}},
|
esDraw AppState{ -- aopts=_uopts@UIOpts{cliopts_=_copts@CliOpts{reportopts_=_ropts@ReportOpts{query_=querystr}}},
|
||||||
aScreen=ErrorScreen{esState=ErrorScreenState{..}}} = [ui]
|
aScreen=ErrorScreen{..}} = [ui]
|
||||||
where
|
where
|
||||||
toplabel = withAttr ("border" <> "bold") (str "Oops. Please fix this problem then press g to reload")
|
toplabel = withAttr ("border" <> "bold") (str "Oops. Please fix this problem then press g to reload")
|
||||||
-- <+> str " transactions"
|
-- <+> str " transactions"
|
||||||
@ -77,7 +77,7 @@ drawErrorScreen AppState{ -- aopts=_uopts@UIOpts{cliopts_=_copts@CliOpts{reporto
|
|||||||
|
|
||||||
render $ defaultLayout toplabel bottomlabel $ withAttr "error" $ str $ esError
|
render $ defaultLayout toplabel bottomlabel $ withAttr "error" $ str $ esError
|
||||||
|
|
||||||
drawErrorScreen _ = error "draw function called with wrong screen type, should not happen"
|
esDraw _ = error "draw function called with wrong screen type, should not happen"
|
||||||
|
|
||||||
-- drawErrorItem :: (Int,Int,Int,Int,Int) -> Bool -> (String,String,String,String,String) -> Widget
|
-- drawErrorItem :: (Int,Int,Int,Int,Int) -> Bool -> (String,String,String,String,String) -> Widget
|
||||||
-- drawErrorItem (datewidth,descwidth,acctswidth,changewidth,balwidth) selected (date,desc,accts,change,bal) =
|
-- drawErrorItem (datewidth,descwidth,acctswidth,changewidth,balwidth) selected (date,desc,accts,change,bal) =
|
||||||
@ -100,9 +100,9 @@ drawErrorScreen _ = error "draw function called with wrong screen type, should n
|
|||||||
-- sel | selected = (<> "selected")
|
-- sel | selected = (<> "selected")
|
||||||
-- | otherwise = id
|
-- | otherwise = id
|
||||||
|
|
||||||
handleErrorScreen :: AppState -> Vty.Event -> EventM (Next AppState)
|
esHandle :: AppState -> Vty.Event -> EventM (Next AppState)
|
||||||
handleErrorScreen st@AppState{
|
esHandle st@AppState{
|
||||||
aScreen=s@ErrorScreen{esState=_err}
|
aScreen=s@ErrorScreen{}
|
||||||
,aopts=UIOpts{cliopts_=copts}
|
,aopts=UIOpts{cliopts_=copts}
|
||||||
,ajournal=j
|
,ajournal=j
|
||||||
} e = do
|
} e = do
|
||||||
@ -114,7 +114,7 @@ handleErrorScreen st@AppState{
|
|||||||
Vty.EvKey (Vty.KChar 'g') [] -> do
|
Vty.EvKey (Vty.KChar 'g') [] -> do
|
||||||
(ej, _) <- liftIO $ journalReloadIfChanged copts d j
|
(ej, _) <- liftIO $ journalReloadIfChanged copts d j
|
||||||
case ej of
|
case ej of
|
||||||
Left err -> continue st{aScreen=s{esState=ErrorScreenState{esError=err}}} -- show latest parse error
|
Left err -> continue st{aScreen=s{esError=err}} -- show latest parse error
|
||||||
Right j' -> continue $ regenerateScreens j' d $ popScreen st -- return to previous screen, and reload it
|
Right j' -> continue $ regenerateScreens j' d $ popScreen st -- return to previous screen, and reload it
|
||||||
|
|
||||||
-- Vty.EvKey (Vty.KLeft) [] -> continue $ popScreen st
|
-- Vty.EvKey (Vty.KLeft) [] -> continue $ popScreen st
|
||||||
@ -124,7 +124,7 @@ handleErrorScreen st@AppState{
|
|||||||
-- is' <- handleEvent ev is
|
-- is' <- handleEvent ev is
|
||||||
-- continue st{aScreen=s{rsState=is'}}
|
-- continue st{aScreen=s{rsState=is'}}
|
||||||
-- continue =<< handleEventLensed st someLens e
|
-- continue =<< handleEventLensed st someLens e
|
||||||
handleErrorScreen _ _ = error "event handler called with wrong screen type, should not happen"
|
esHandle _ _ = error "event handler called with wrong screen type, should not happen"
|
||||||
|
|
||||||
-- If journal file(s) have changed, reload the journal and regenerate all screens.
|
-- If journal file(s) have changed, reload the journal and regenerate all screens.
|
||||||
-- This is here so it can reference the error screen.
|
-- This is here so it can reference the error screen.
|
||||||
@ -133,5 +133,5 @@ stReloadJournalIfChanged copts d j st = do
|
|||||||
(ej, _) <- journalReloadIfChanged copts d j
|
(ej, _) <- journalReloadIfChanged copts d j
|
||||||
return $ case ej of
|
return $ case ej of
|
||||||
Right j' -> regenerateScreens j' d st
|
Right j' -> regenerateScreens j' d st
|
||||||
Left err -> screenEnter d errorScreen{esState=ErrorScreenState{esError=err}} st
|
Left err -> screenEnter d errorScreen{esError=err} st
|
||||||
|
|
||||||
|
|||||||
@ -101,7 +101,7 @@ runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} j = do
|
|||||||
-- with --register, start on the register screen, and also put
|
-- with --register, start on the register screen, and also put
|
||||||
-- the accounts screen on the prev screens stack so you can exit
|
-- the accounts screen on the prev screens stack so you can exit
|
||||||
-- to that as usual.
|
-- to that as usual.
|
||||||
Just apat -> (rsSetCurrentAccount acct registerScreen, [ascr'])
|
Just apat -> (rsSetAccount acct registerScreen, [ascr'])
|
||||||
where
|
where
|
||||||
acct = headDef
|
acct = headDef
|
||||||
(error' $ "--register "++apat++" did not match any account")
|
(error' $ "--register "++apat++" did not match any account")
|
||||||
@ -109,7 +109,7 @@ runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} j = do
|
|||||||
-- Initialising the accounts screen is awkward, requiring
|
-- Initialising the accounts screen is awkward, requiring
|
||||||
-- another temporary AppState value..
|
-- another temporary AppState value..
|
||||||
ascr' = aScreen $
|
ascr' = aScreen $
|
||||||
initAccountsScreen d True $
|
asInit d True $
|
||||||
AppState{
|
AppState{
|
||||||
aopts=uopts'
|
aopts=uopts'
|
||||||
,ajournal=j
|
,ajournal=j
|
||||||
@ -118,7 +118,7 @@ runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} j = do
|
|||||||
,aMinibuffer=Nothing
|
,aMinibuffer=Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
st = (sInitFn scr) d True
|
st = (sInit scr) d True
|
||||||
AppState{
|
AppState{
|
||||||
aopts=uopts'
|
aopts=uopts'
|
||||||
,ajournal=j
|
,ajournal=j
|
||||||
@ -133,8 +133,8 @@ runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} j = do
|
|||||||
, appStartEvent = return
|
, appStartEvent = return
|
||||||
, appAttrMap = const theme
|
, appAttrMap = const theme
|
||||||
, appChooseCursor = showFirstCursor
|
, appChooseCursor = showFirstCursor
|
||||||
, appHandleEvent = \st ev -> sHandleFn (aScreen st) st ev
|
, appHandleEvent = \st ev -> sHandle (aScreen st) st ev
|
||||||
, appDraw = \st -> sDrawFn (aScreen st) st
|
, appDraw = \st -> sDraw (aScreen st) st
|
||||||
-- XXX bizarro. removing the st arg and parameter above,
|
-- XXX bizarro. removing the st arg and parameter above,
|
||||||
-- which according to GHCI does not change the type,
|
-- which according to GHCI does not change the type,
|
||||||
-- causes "Exception: draw function called with wrong screen type"
|
-- causes "Exception: draw function called with wrong screen type"
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
module Hledger.UI.RegisterScreen
|
module Hledger.UI.RegisterScreen
|
||||||
(registerScreen
|
(registerScreen
|
||||||
,rsSetCurrentAccount
|
,rsSetAccount
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
@ -37,20 +37,19 @@ import Hledger.UI.ErrorScreen
|
|||||||
|
|
||||||
registerScreen :: Screen
|
registerScreen :: Screen
|
||||||
registerScreen = RegisterScreen{
|
registerScreen = RegisterScreen{
|
||||||
rsState = RegisterScreenState{rsItems=list "register" V.empty 1
|
sInit = rsInit
|
||||||
,rsSelectedAccount=""
|
,sDraw = rsDraw
|
||||||
}
|
,sHandle = rsHandle
|
||||||
,sInitFn = initRegisterScreen
|
,rsList = list "register" V.empty 1
|
||||||
,sDrawFn = drawRegisterScreen
|
,rsAccount = ""
|
||||||
,sHandleFn = handleRegisterScreen
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rsSetCurrentAccount a scr@RegisterScreen{..} = scr{rsState=rsState{rsSelectedAccount=a}}
|
rsSetAccount a scr@RegisterScreen{} = scr{rsAccount=a}
|
||||||
rsSetCurrentAccount _ scr = scr
|
rsSetAccount _ scr = scr
|
||||||
|
|
||||||
initRegisterScreen :: Day -> Bool -> AppState -> AppState
|
rsInit :: Day -> Bool -> AppState -> AppState
|
||||||
initRegisterScreen d reset st@AppState{aopts=opts, ajournal=j, aScreen=s@RegisterScreen{rsState=rsState@RegisterScreenState{..}}} =
|
rsInit d reset st@AppState{aopts=opts, ajournal=j, aScreen=s@RegisterScreen{..}} =
|
||||||
st{aScreen=s{rsState=rsState{rsItems=newitems'}}}
|
st{aScreen=s{rsList=newitems'}}
|
||||||
where
|
where
|
||||||
-- gather arguments and queries
|
-- gather arguments and queries
|
||||||
ropts = (reportopts_ $ cliopts_ opts)
|
ropts = (reportopts_ $ cliopts_ opts)
|
||||||
@ -59,7 +58,7 @@ initRegisterScreen d reset st@AppState{aopts=opts, ajournal=j, aScreen=s@Registe
|
|||||||
balancetype_=HistoricalBalance
|
balancetype_=HistoricalBalance
|
||||||
}
|
}
|
||||||
-- XXX temp
|
-- XXX temp
|
||||||
thisacctq = Acct $ accountNameToAccountRegex rsSelectedAccount -- includes subs
|
thisacctq = Acct $ accountNameToAccountRegex rsAccount -- includes subs
|
||||||
q = filterQuery (not . queryIsDepth) $ queryFromOpts d ropts
|
q = filterQuery (not . queryIsDepth) $ queryFromOpts d ropts
|
||||||
|
|
||||||
(_label,items) = accountTransactionsReport ropts j q thisacctq
|
(_label,items) = accountTransactionsReport ropts j q thisacctq
|
||||||
@ -89,22 +88,22 @@ initRegisterScreen d reset st@AppState{aopts=opts, ajournal=j, aScreen=s@Registe
|
|||||||
-- (eg after toggling nonzero mode), otherwise select the last element.
|
-- (eg after toggling nonzero mode), otherwise select the last element.
|
||||||
newitems' = listMoveTo newselidx newitems
|
newitems' = listMoveTo newselidx newitems
|
||||||
where
|
where
|
||||||
newselidx = case (reset, listSelectedElement rsItems) of
|
newselidx = case (reset, listSelectedElement rsList) of
|
||||||
(True, _) -> 0
|
(True, _) -> 0
|
||||||
(_, Nothing) -> endidx
|
(_, Nothing) -> endidx
|
||||||
(_, Just (_,RegisterScreenItem{rsItemTransaction=Transaction{tindex=ti}}))
|
(_, Just (_,RegisterScreenItem{rsItemTransaction=Transaction{tindex=ti}}))
|
||||||
-> fromMaybe endidx $ findIndex ((==ti) . tindex . rsItemTransaction) displayitems
|
-> fromMaybe endidx $ findIndex ((==ti) . tindex . rsItemTransaction) displayitems
|
||||||
endidx = length displayitems
|
endidx = length displayitems
|
||||||
|
|
||||||
initRegisterScreen _ _ _ = error "init function called with wrong screen type, should not happen"
|
rsInit _ _ _ = error "init function called with wrong screen type, should not happen"
|
||||||
|
|
||||||
drawRegisterScreen :: AppState -> [Widget]
|
rsDraw :: AppState -> [Widget]
|
||||||
drawRegisterScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}
|
rsDraw AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}
|
||||||
,aScreen=RegisterScreen{rsState=RegisterScreenState{..}}
|
,aScreen=RegisterScreen{..}
|
||||||
,aMinibuffer=mbuf}
|
,aMinibuffer=mbuf}
|
||||||
= [ui]
|
= [ui]
|
||||||
where
|
where
|
||||||
toplabel = withAttr ("border" <> "bold") (str $ T.unpack rsSelectedAccount)
|
toplabel = withAttr ("border" <> "bold") (str $ T.unpack rsAccount)
|
||||||
<+> togglefilters
|
<+> togglefilters
|
||||||
<+> str " transactions"
|
<+> str " transactions"
|
||||||
<+> borderQueryStr (query_ ropts)
|
<+> borderQueryStr (query_ ropts)
|
||||||
@ -124,11 +123,11 @@ drawRegisterScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}
|
|||||||
] of
|
] of
|
||||||
[] -> str ""
|
[] -> str ""
|
||||||
fs -> withAttr (borderAttr <> "query") (str $ " " ++ intercalate ", " fs)
|
fs -> withAttr (borderAttr <> "query") (str $ " " ++ intercalate ", " fs)
|
||||||
cur = str $ case rsItems ^. listSelectedL of
|
cur = str $ case rsList ^. listSelectedL of
|
||||||
Nothing -> "-"
|
Nothing -> "-"
|
||||||
Just i -> show (i + 1)
|
Just i -> show (i + 1)
|
||||||
total = str $ show $ length displayitems
|
total = str $ show $ length displayitems
|
||||||
displayitems = V.toList $ rsItems ^. listElementsL
|
displayitems = V.toList $ rsList ^. listElementsL
|
||||||
|
|
||||||
-- query = query_ $ reportopts_ $ cliopts_ opts
|
-- query = query_ $ reportopts_ $ cliopts_ opts
|
||||||
|
|
||||||
@ -196,12 +195,12 @@ drawRegisterScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}
|
|||||||
Nothing -> bottomlabel
|
Nothing -> bottomlabel
|
||||||
Just ed -> minibuffer ed
|
Just ed -> minibuffer ed
|
||||||
|
|
||||||
render $ defaultLayout toplabel bottomarea $ renderList rsItems (drawRegisterItem colwidths)
|
render $ defaultLayout toplabel bottomarea $ renderList rsList (rsDrawItem colwidths)
|
||||||
|
|
||||||
drawRegisterScreen _ = error "draw function called with wrong screen type, should not happen"
|
rsDraw _ = error "draw function called with wrong screen type, should not happen"
|
||||||
|
|
||||||
drawRegisterItem :: (Int,Int,Int,Int,Int) -> Bool -> RegisterScreenItem -> Widget
|
rsDrawItem :: (Int,Int,Int,Int,Int) -> Bool -> RegisterScreenItem -> Widget
|
||||||
drawRegisterItem (datewidth,descwidth,acctswidth,changewidth,balwidth) selected RegisterScreenItem{..} =
|
rsDrawItem (datewidth,descwidth,acctswidth,changewidth,balwidth) selected RegisterScreenItem{..} =
|
||||||
Widget Greedy Fixed $ do
|
Widget Greedy Fixed $ do
|
||||||
render $
|
render $
|
||||||
str (fitString (Just datewidth) (Just datewidth) True True rsItemDate) <+>
|
str (fitString (Just datewidth) (Just datewidth) True True rsItemDate) <+>
|
||||||
@ -221,9 +220,9 @@ drawRegisterItem (datewidth,descwidth,acctswidth,changewidth,balwidth) selected
|
|||||||
sel | selected = (<> "selected")
|
sel | selected = (<> "selected")
|
||||||
| otherwise = id
|
| otherwise = id
|
||||||
|
|
||||||
handleRegisterScreen :: AppState -> Vty.Event -> EventM (Next AppState)
|
rsHandle :: AppState -> Vty.Event -> EventM (Next AppState)
|
||||||
handleRegisterScreen st@AppState{
|
rsHandle st@AppState{
|
||||||
aScreen=s@RegisterScreen{rsState=rsState@RegisterScreenState{..}}
|
aScreen=s@RegisterScreen{..}
|
||||||
,aopts=UIOpts{cliopts_=copts}
|
,aopts=UIOpts{cliopts_=copts}
|
||||||
,ajournal=j
|
,ajournal=j
|
||||||
,aMinibuffer=mbuf
|
,aMinibuffer=mbuf
|
||||||
@ -245,22 +244,22 @@ handleRegisterScreen st@AppState{
|
|||||||
Vty.EvKey (Vty.KLeft) [] -> continue $ popScreen st
|
Vty.EvKey (Vty.KLeft) [] -> continue $ popScreen st
|
||||||
|
|
||||||
Vty.EvKey (k) [] | k `elem` [Vty.KRight, Vty.KEnter] -> do
|
Vty.EvKey (k) [] | k `elem` [Vty.KRight, Vty.KEnter] -> do
|
||||||
case listSelectedElement rsItems of
|
case listSelectedElement rsList of
|
||||||
Just (_, RegisterScreenItem{rsItemTransaction=t}) ->
|
Just (_, RegisterScreenItem{rsItemTransaction=t}) ->
|
||||||
let
|
let
|
||||||
ts = map rsItemTransaction $ V.toList $ listElements rsItems
|
ts = map rsItemTransaction $ V.toList $ listElements rsList
|
||||||
numberedts = zip [1..] ts
|
numberedts = zip [1..] ts
|
||||||
i = fromIntegral $ maybe 0 (+1) $ elemIndex t ts -- XXX
|
i = fromIntegral $ maybe 0 (+1) $ elemIndex t ts -- XXX
|
||||||
in
|
in
|
||||||
continue $ screenEnter d transactionScreen{tsState=TransactionScreenState{tsTransaction=(i,t)
|
continue $ screenEnter d transactionScreen{tsTransaction=(i,t)
|
||||||
,tsTransactions=numberedts
|
,tsTransactions=numberedts
|
||||||
,tsSelectedAccount=rsSelectedAccount}} st
|
,tsAccount=rsAccount} st
|
||||||
Nothing -> continue st
|
Nothing -> continue st
|
||||||
|
|
||||||
-- fall through to the list's event handler (handles [pg]up/down)
|
-- fall through to the list's event handler (handles [pg]up/down)
|
||||||
ev -> do
|
ev -> do
|
||||||
newitems <- handleEvent ev rsItems
|
newitems <- handleEvent ev rsList
|
||||||
continue st{aScreen=s{rsState=rsState{rsItems=newitems}}}
|
continue st{aScreen=s{rsList=newitems}}
|
||||||
-- continue =<< handleEventLensed st someLens ev
|
-- continue =<< handleEventLensed st someLens ev
|
||||||
|
|
||||||
Just ed ->
|
Just ed ->
|
||||||
@ -275,4 +274,5 @@ handleRegisterScreen st@AppState{
|
|||||||
-- Encourage a more stable scroll position when toggling list items (cf AccountsScreen.hs)
|
-- Encourage a more stable scroll position when toggling list items (cf AccountsScreen.hs)
|
||||||
scrollTop = vScrollToBeginning $ viewportScroll "register"
|
scrollTop = vScrollToBeginning $ viewportScroll "register"
|
||||||
|
|
||||||
handleRegisterScreen _ _ = error "event handler called with wrong screen type, should not happen"
|
rsHandle _ _ = error "event handler called with wrong screen type, should not happen"
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
module Hledger.UI.TransactionScreen
|
module Hledger.UI.TransactionScreen
|
||||||
(transactionScreen
|
(transactionScreen
|
||||||
|
,rsSelect
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
@ -37,26 +38,26 @@ import Hledger.UI.ErrorScreen
|
|||||||
|
|
||||||
transactionScreen :: Screen
|
transactionScreen :: Screen
|
||||||
transactionScreen = TransactionScreen{
|
transactionScreen = TransactionScreen{
|
||||||
tsState = TransactionScreenState{tsTransaction=(1,nulltransaction)
|
sInit = tsInit
|
||||||
,tsTransactions=[(1,nulltransaction)]
|
,sDraw = tsDraw
|
||||||
,tsSelectedAccount=""}
|
,sHandle = tsHandle
|
||||||
,sInitFn = initTransactionScreen
|
,tsTransaction = (1,nulltransaction)
|
||||||
,sDrawFn = drawTransactionScreen
|
,tsTransactions = [(1,nulltransaction)]
|
||||||
,sHandleFn = handleTransactionScreen
|
,tsAccount = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
initTransactionScreen :: Day -> Bool -> AppState -> AppState
|
tsInit :: Day -> Bool -> AppState -> AppState
|
||||||
initTransactionScreen _d _reset st@AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=_ropts}}
|
tsInit _d _reset st@AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=_ropts}}
|
||||||
,ajournal=_j
|
,ajournal=_j
|
||||||
,aScreen=TransactionScreen{..}} = st
|
,aScreen=TransactionScreen{..}} = st
|
||||||
initTransactionScreen _ _ _ = error "init function called with wrong screen type, should not happen"
|
tsInit _ _ _ = error "init function called with wrong screen type, should not happen"
|
||||||
|
|
||||||
drawTransactionScreen :: AppState -> [Widget]
|
tsDraw :: AppState -> [Widget]
|
||||||
drawTransactionScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}
|
tsDraw AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}
|
||||||
,aScreen=TransactionScreen{
|
,aScreen=TransactionScreen{
|
||||||
tsState=TransactionScreenState{tsTransaction=(i,t)
|
tsTransaction=(i,t)
|
||||||
,tsTransactions=nts
|
,tsTransactions=nts
|
||||||
,tsSelectedAccount=acct}}} =
|
,tsAccount=acct}} =
|
||||||
[ui]
|
[ui]
|
||||||
where
|
where
|
||||||
-- datedesc = show (tdate t) ++ " " ++ tdescription t
|
-- datedesc = show (tdate t) ++ " " ++ tdescription t
|
||||||
@ -96,13 +97,13 @@ drawTransactionScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}
|
|||||||
-- (if real_ ropts then filterTransactionPostings (Real True) else id) -- filter postings by --real
|
-- (if real_ ropts then filterTransactionPostings (Real True) else id) -- filter postings by --real
|
||||||
t
|
t
|
||||||
|
|
||||||
drawTransactionScreen _ = error "draw function called with wrong screen type, should not happen"
|
tsDraw _ = error "draw function called with wrong screen type, should not happen"
|
||||||
|
|
||||||
handleTransactionScreen :: AppState -> Vty.Event -> EventM (Next AppState)
|
tsHandle :: AppState -> Vty.Event -> EventM (Next AppState)
|
||||||
handleTransactionScreen
|
tsHandle
|
||||||
st@AppState{aScreen=s@TransactionScreen{tsState=tsState@TransactionScreenState{tsTransaction=(i,t)
|
st@AppState{aScreen=s@TransactionScreen{tsTransaction=(i,t)
|
||||||
,tsTransactions=nts
|
,tsTransactions=nts
|
||||||
,tsSelectedAccount=acct}}
|
,tsAccount=acct}
|
||||||
,aopts=UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
|
,aopts=UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
|
||||||
,ajournal=j
|
,ajournal=j
|
||||||
}
|
}
|
||||||
@ -121,7 +122,7 @@ handleTransactionScreen
|
|||||||
case ej of
|
case ej of
|
||||||
Right j' -> do
|
Right j' -> do
|
||||||
-- got to redo the register screen's transactions report, to get the latest transactions list for this screen
|
-- got to redo the register screen's transactions report, to get the latest transactions list for this screen
|
||||||
-- XXX duplicates initRegisterScreen
|
-- XXX duplicates rsInit
|
||||||
let
|
let
|
||||||
ropts' = ropts {depth_=Nothing
|
ropts' = ropts {depth_=Nothing
|
||||||
,balancetype_=HistoricalBalance
|
,balancetype_=HistoricalBalance
|
||||||
@ -138,31 +139,31 @@ handleTransactionScreen
|
|||||||
Nothing | null numberedts -> (0,nulltransaction)
|
Nothing | null numberedts -> (0,nulltransaction)
|
||||||
| i > fst (last numberedts) -> last numberedts
|
| i > fst (last numberedts) -> last numberedts
|
||||||
| otherwise -> head numberedts
|
| otherwise -> head numberedts
|
||||||
st' = st{aScreen=s{tsState=TransactionScreenState{tsTransaction=(i',t')
|
st' = st{aScreen=s{tsTransaction=(i',t')
|
||||||
,tsTransactions=numberedts
|
,tsTransactions=numberedts
|
||||||
,tsSelectedAccount=acct}}}
|
,tsAccount=acct}}
|
||||||
continue $ regenerateScreens j' d st'
|
continue $ regenerateScreens j' d st'
|
||||||
|
|
||||||
Left err -> continue $ screenEnter d errorScreen{esState=ErrorScreenState{esError=err}} st
|
Left err -> continue $ screenEnter d errorScreen{esError=err} st
|
||||||
|
|
||||||
-- if allowing toggling here, we should refresh the txn list from the parent register screen
|
-- if allowing toggling here, we should refresh the txn list from the parent register screen
|
||||||
-- Vty.EvKey (Vty.KChar 'E') [] -> continue $ regenerateScreens j d $ stToggleEmpty st
|
-- Vty.EvKey (Vty.KChar 'E') [] -> continue $ regenerateScreens j d $ stToggleEmpty st
|
||||||
-- Vty.EvKey (Vty.KChar 'C') [] -> continue $ regenerateScreens j d $ stToggleCleared st
|
-- Vty.EvKey (Vty.KChar 'C') [] -> continue $ regenerateScreens j d $ stToggleCleared st
|
||||||
-- Vty.EvKey (Vty.KChar 'R') [] -> continue $ regenerateScreens j d $ stToggleReal st
|
-- Vty.EvKey (Vty.KChar 'R') [] -> continue $ regenerateScreens j d $ stToggleReal st
|
||||||
|
|
||||||
Vty.EvKey (Vty.KUp) [] -> continue $ regenerateScreens j d st{aScreen=s{tsState=tsState{tsTransaction=(iprev,tprev)}}}
|
Vty.EvKey (Vty.KUp) [] -> continue $ regenerateScreens j d st{aScreen=s{tsTransaction=(iprev,tprev)}}
|
||||||
Vty.EvKey (Vty.KDown) [] -> continue $ regenerateScreens j d st{aScreen=s{tsState=tsState{tsTransaction=(inext,tnext)}}}
|
Vty.EvKey (Vty.KDown) [] -> continue $ regenerateScreens j d st{aScreen=s{tsTransaction=(inext,tnext)}}
|
||||||
|
|
||||||
Vty.EvKey (Vty.KLeft) [] -> continue st''
|
Vty.EvKey (Vty.KLeft) [] -> continue st''
|
||||||
where
|
where
|
||||||
st'@AppState{aScreen=scr} = popScreen st
|
st'@AppState{aScreen=scr} = popScreen st
|
||||||
st'' = st'{aScreen=rsSetSelectedTransaction (fromIntegral i) scr}
|
st'' = st'{aScreen=rsSelect (fromIntegral i) scr}
|
||||||
|
|
||||||
_ev -> continue st
|
_ev -> continue st
|
||||||
|
|
||||||
handleTransactionScreen _ _ = error "event handler called with wrong screen type, should not happen"
|
tsHandle _ _ = error "event handler called with wrong screen type, should not happen"
|
||||||
|
|
||||||
rsSetSelectedTransaction i scr@RegisterScreen{rsState=rsState@RegisterScreenState{..}} = scr{rsState=rsState{rsItems=l'}}
|
|
||||||
where l' = listMoveTo (i-1) rsItems
|
|
||||||
rsSetSelectedTransaction _ scr = scr
|
|
||||||
|
|
||||||
|
-- | Select the nth item on the register screen.
|
||||||
|
rsSelect i scr@RegisterScreen{..} = scr{rsList=l'}
|
||||||
|
where l' = listMoveTo (i-1) rsList
|
||||||
|
rsSelect _ scr = scr
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
{- |
|
{- |
|
||||||
Overview:
|
Overview:
|
||||||
hledger-ui's AppState holds the active screen and any previously visited screens.
|
hledger-ui's AppState holds the currently active screen and any previously visited
|
||||||
Screens have their own render state, render function, event handler,
|
screens (and their states).
|
||||||
and app state update function (which can update the whole AppState).
|
The brick App delegates all event-handling and rendering
|
||||||
A brick App delegates event-handling and rendering to our AppState's active screen.
|
to the AppState's active screen.
|
||||||
|
Screens have their own screen state, render function, event handler, and app state
|
||||||
|
update function, so they have full control.
|
||||||
|
|
||||||
@
|
@
|
||||||
Brick.defaultMain brickapp st
|
Brick.defaultMain brickapp st
|
||||||
@ -14,15 +16,15 @@ Brick.defaultMain brickapp st
|
|||||||
, appStartEvent = return
|
, appStartEvent = return
|
||||||
, appAttrMap = const theme
|
, appAttrMap = const theme
|
||||||
, appChooseCursor = showFirstCursor
|
, appChooseCursor = showFirstCursor
|
||||||
, appHandleEvent = \st ev -> sHandleFn (aScreen st) st ev
|
, appHandleEvent = \st ev -> sHandle (aScreen st) st ev
|
||||||
, appDraw = \st -> sDrawFn (aScreen st) st
|
, appDraw = \st -> sDraw (aScreen st) st
|
||||||
}
|
}
|
||||||
st :: AppState
|
st :: AppState
|
||||||
st = (sInitFn scr) d
|
st = (sInit s) d
|
||||||
AppState{
|
AppState{
|
||||||
aopts=uopts'
|
aopts=uopts'
|
||||||
,ajournal=j
|
,ajournal=j
|
||||||
,aScreen=scr
|
,aScreen=s
|
||||||
,aPrevScreens=prevscrs
|
,aPrevScreens=prevscrs
|
||||||
,aMinibuffer=Nothing
|
,aMinibuffer=Nothing
|
||||||
}
|
}
|
||||||
@ -51,63 +53,57 @@ import Text.Show.Functions ()
|
|||||||
import Hledger
|
import Hledger
|
||||||
import Hledger.UI.UIOptions
|
import Hledger.UI.UIOptions
|
||||||
|
|
||||||
|
instance Show (List a) where show _ = "<List>"
|
||||||
|
instance Show Editor where show _ = "<Editor>"
|
||||||
|
|
||||||
-- | hledger-ui's application state. This holds one or more stateful screens.
|
-- | hledger-ui's application state. This holds one or more stateful screens.
|
||||||
data AppState = AppState {
|
data AppState = AppState {
|
||||||
aopts :: UIOpts -- ^ the command-line options and query arguments currently in effect
|
aopts :: UIOpts -- ^ the command-line options and query arguments currently in effect
|
||||||
,ajournal :: Journal -- ^ the journal being viewed
|
,ajournal :: Journal -- ^ the journal being viewed
|
||||||
,aScreen :: Screen -- ^ the currently active screen
|
,aScreen :: Screen -- ^ the currently active screen
|
||||||
,aPrevScreens :: [Screen] -- ^ previously visited screens, most recent first
|
,aPrevScreens :: [Screen] -- ^ previously visited screens, most recent first
|
||||||
,aMinibuffer :: Maybe Editor -- ^ a compact editor used for data entry, when active
|
,aMinibuffer :: Maybe Editor -- ^ a compact editor, when active, used for data entry on all screens
|
||||||
} deriving (Show)
|
} deriving (Show)
|
||||||
|
|
||||||
-- | Types of screen available within hledger-ui. Each has its own
|
-- | hledger-ui screen types & instances.
|
||||||
-- specific state type, and generic initialisation, event handling
|
-- Each screen type has generically named initialisation, draw, and event handling functions,
|
||||||
-- and rendering functions.
|
-- and zero or more uniquely named screen state fields, which hold the data for a particular
|
||||||
--
|
-- instance of this screen. The latter create partial functions, so take care.
|
||||||
-- Screen types are pattern-matched by their constructor and their
|
|
||||||
-- state field, which must have a unique name. This type causes
|
|
||||||
-- partial functions, so take care.
|
|
||||||
data Screen =
|
data Screen =
|
||||||
AccountsScreen {
|
AccountsScreen {
|
||||||
_asState :: AccountsScreenState
|
sInit :: Day -> Bool -> AppState -> AppState -- ^ function to update the screen's state
|
||||||
,sInitFn :: Day -> Bool -> AppState -> AppState -- ^ function to generate the screen's state on entry or change
|
,sDraw :: AppState -> [Widget] -- ^ brick renderer for this screen
|
||||||
,sDrawFn :: AppState -> [Widget] -- ^ brick renderer for this screen
|
,sHandle :: AppState -> Vty.Event -> EventM (Next AppState) -- ^ brick event handler for this screen
|
||||||
,sHandleFn :: AppState -> Vty.Event -> EventM (Next AppState) -- ^ brick event handler for this screen
|
-- state fields. These ones have lenses:
|
||||||
|
,_asList :: List AccountsScreenItem -- ^ list widget showing account names & balances
|
||||||
|
,_asSelectedAccount :: AccountName -- ^ a backup of the account name from the list widget's selected item (or "")
|
||||||
}
|
}
|
||||||
| RegisterScreen {
|
| RegisterScreen {
|
||||||
rsState :: RegisterScreenState
|
sInit :: Day -> Bool -> AppState -> AppState
|
||||||
,sInitFn :: Day -> Bool -> AppState -> AppState
|
,sDraw :: AppState -> [Widget]
|
||||||
,sDrawFn :: AppState -> [Widget]
|
,sHandle :: AppState -> Vty.Event -> EventM (Next AppState)
|
||||||
,sHandleFn :: AppState -> Vty.Event -> EventM (Next AppState)
|
--
|
||||||
|
,rsList :: List RegisterScreenItem -- ^ list widget showing transactions affecting this account
|
||||||
|
,rsAccount :: AccountName -- ^ the account this register is for
|
||||||
}
|
}
|
||||||
| TransactionScreen {
|
| TransactionScreen {
|
||||||
tsState :: TransactionScreenState
|
sInit :: Day -> Bool -> AppState -> AppState
|
||||||
,sInitFn :: Day -> Bool -> AppState -> AppState
|
,sDraw :: AppState -> [Widget]
|
||||||
,sDrawFn :: AppState -> [Widget]
|
,sHandle :: AppState -> Vty.Event -> EventM (Next AppState)
|
||||||
,sHandleFn :: AppState -> Vty.Event -> EventM (Next AppState)
|
--
|
||||||
|
,tsTransaction :: NumberedTransaction -- ^ the transaction we are currently viewing, and its position in the list
|
||||||
|
,tsTransactions :: [NumberedTransaction] -- ^ list of transactions we can step through
|
||||||
|
,tsAccount :: AccountName -- ^ the account whose register we entered this screen from
|
||||||
}
|
}
|
||||||
| ErrorScreen {
|
| ErrorScreen {
|
||||||
esState :: ErrorScreenState
|
sInit :: Day -> Bool -> AppState -> AppState
|
||||||
,sInitFn :: Day -> Bool -> AppState -> AppState
|
,sDraw :: AppState -> [Widget]
|
||||||
,sDrawFn :: AppState -> [Widget]
|
,sHandle :: AppState -> Vty.Event -> EventM (Next AppState)
|
||||||
,sHandleFn :: AppState -> Vty.Event -> EventM (Next AppState)
|
--
|
||||||
|
,esError :: String -- ^ error message to show
|
||||||
}
|
}
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
instance Show (List a) where show _ = "<List>"
|
|
||||||
instance Show Editor where show _ = "<Editor>"
|
|
||||||
|
|
||||||
instance Monoid (List a)
|
|
||||||
where
|
|
||||||
mempty = list "" V.empty 1
|
|
||||||
mappend a b = a & listElementsL .~ (a^.listElementsL <> b^.listElementsL)
|
|
||||||
|
|
||||||
-- | Render state for this type of screen.
|
|
||||||
data AccountsScreenState = AccountsScreenState {
|
|
||||||
_asItems :: List AccountsScreenItem -- ^ list of account names & balances
|
|
||||||
,_asSelectedAccount :: AccountName -- ^ full name of the currently selected account (or "")
|
|
||||||
} deriving (Show)
|
|
||||||
|
|
||||||
-- | An item in the accounts screen's list of accounts and balances.
|
-- | An item in the accounts screen's list of accounts and balances.
|
||||||
data AccountsScreenItem = AccountsScreenItem {
|
data AccountsScreenItem = AccountsScreenItem {
|
||||||
asItemIndentLevel :: Int -- ^ indent level
|
asItemIndentLevel :: Int -- ^ indent level
|
||||||
@ -116,12 +112,6 @@ data AccountsScreenItem = AccountsScreenItem {
|
|||||||
,asItemRenderedAmounts :: [String] -- ^ rendered amounts
|
,asItemRenderedAmounts :: [String] -- ^ rendered amounts
|
||||||
}
|
}
|
||||||
|
|
||||||
-- | Render state for this type of screen.
|
|
||||||
data RegisterScreenState = RegisterScreenState {
|
|
||||||
rsItems :: List RegisterScreenItem -- ^ list of transactions affecting this account
|
|
||||||
,rsSelectedAccount :: AccountName -- ^ full name of the account we are showing a register for
|
|
||||||
} deriving (Show)
|
|
||||||
|
|
||||||
-- | An item in the register screen's list of transactions in the current account.
|
-- | An item in the register screen's list of transactions in the current account.
|
||||||
data RegisterScreenItem = RegisterScreenItem {
|
data RegisterScreenItem = RegisterScreenItem {
|
||||||
rsItemDate :: String -- ^ date
|
rsItemDate :: String -- ^ date
|
||||||
@ -132,26 +122,15 @@ data RegisterScreenItem = RegisterScreenItem {
|
|||||||
,rsItemTransaction :: Transaction -- ^ the full transaction
|
,rsItemTransaction :: Transaction -- ^ the full transaction
|
||||||
}
|
}
|
||||||
|
|
||||||
-- | Render state for this type of screen.
|
|
||||||
data TransactionScreenState = TransactionScreenState {
|
|
||||||
tsTransaction :: NumberedTransaction -- ^ the transaction we are currently viewing, and its position in the list
|
|
||||||
,tsTransactions :: [NumberedTransaction] -- ^ the list of transactions we can step through
|
|
||||||
,tsSelectedAccount :: AccountName -- ^ the account whose register we entered this screen from
|
|
||||||
} deriving (Show)
|
|
||||||
|
|
||||||
type NumberedTransaction = (Integer, Transaction)
|
type NumberedTransaction = (Integer, Transaction)
|
||||||
|
|
||||||
-- | Render state for this type of screen.
|
-- needed for lenses
|
||||||
data ErrorScreenState = ErrorScreenState {
|
instance Monoid (List a)
|
||||||
esError :: String -- ^ error message to show
|
where
|
||||||
} deriving (Show)
|
mempty = list "" V.empty 1
|
||||||
|
mappend l1 l2 = l1 & listElementsL .~ (l1^.listElementsL <> l2^.listElementsL)
|
||||||
|
|
||||||
-- makeLenses ''AccountsScreenState
|
|
||||||
concat <$> mapM makeLenses [
|
concat <$> mapM makeLenses [
|
||||||
''AccountsScreenState
|
''Screen
|
||||||
-- ,''RegisterScreenState
|
|
||||||
-- ,''TransactionScreenState
|
|
||||||
-- ,''ErrorScreenState
|
|
||||||
,''Screen
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -1,33 +1,36 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
|
|
||||||
module Hledger.UI.UIUtils (
|
module Hledger.UI.UIUtils
|
||||||
pushScreen
|
-- (
|
||||||
,popScreen
|
-- pushScreen
|
||||||
,resetScreens
|
-- ,popScreen
|
||||||
,screenEnter
|
-- ,resetScreens
|
||||||
,regenerateScreens
|
-- ,screenEnter
|
||||||
,getViewportSize
|
-- ,regenerateScreens
|
||||||
-- ,margin
|
-- ,getViewportSize
|
||||||
,withBorderAttr
|
-- -- ,margin
|
||||||
,topBottomBorderWithLabel
|
-- ,withBorderAttr
|
||||||
,topBottomBorderWithLabels
|
-- ,topBottomBorderWithLabel
|
||||||
,defaultLayout
|
-- ,topBottomBorderWithLabels
|
||||||
,borderQueryStr
|
-- ,defaultLayout
|
||||||
,borderDepthStr
|
-- ,borderQueryStr
|
||||||
,borderKeysStr
|
-- ,borderDepthStr
|
||||||
,minibuffer
|
-- ,borderKeysStr
|
||||||
--
|
-- ,minibuffer
|
||||||
,stToggleCleared
|
-- --
|
||||||
,stTogglePending
|
-- ,stToggleCleared
|
||||||
,stToggleUncleared
|
-- ,stTogglePending
|
||||||
,stToggleEmpty
|
-- ,stToggleUncleared
|
||||||
,stToggleFlat
|
-- ,stToggleEmpty
|
||||||
,stToggleReal
|
-- ,stToggleFlat
|
||||||
,stFilter
|
-- ,stToggleReal
|
||||||
,stResetFilter
|
-- ,stFilter
|
||||||
,stShowMinibuffer
|
-- ,stResetFilter
|
||||||
,stHideMinibuffer
|
-- ,stShowMinibuffer
|
||||||
) where
|
-- ,stHideMinibuffer
|
||||||
|
-- )
|
||||||
|
where
|
||||||
|
|
||||||
import Lens.Micro ((^.))
|
import Lens.Micro ((^.))
|
||||||
-- import Control.Monad
|
-- import Control.Monad
|
||||||
@ -44,13 +47,10 @@ import Brick.Widgets.Border
|
|||||||
import Brick.Widgets.Border.Style
|
import Brick.Widgets.Border.Style
|
||||||
import Graphics.Vty as Vty
|
import Graphics.Vty as Vty
|
||||||
|
|
||||||
import Hledger.UI.UITypes
|
import Hledger
|
||||||
import Hledger.Data.Types (Journal)
|
|
||||||
import Hledger.UI.UIOptions
|
|
||||||
import Hledger.Cli.CliOptions
|
import Hledger.Cli.CliOptions
|
||||||
import Hledger.Reports.ReportOptions
|
import Hledger.UI.UITypes
|
||||||
import Hledger.Utils (applyN)
|
import Hledger.UI.UIOptions
|
||||||
-- import Hledger.Utils.Debug
|
|
||||||
|
|
||||||
-- | Toggle between showing only cleared items or all items.
|
-- | Toggle between showing only cleared items or all items.
|
||||||
stToggleCleared :: AppState -> AppState
|
stToggleCleared :: AppState -> AppState
|
||||||
@ -116,6 +116,43 @@ stResetDepth :: AppState -> AppState
|
|||||||
stResetDepth st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
|
stResetDepth st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
|
||||||
st{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=Nothing}}}}
|
st{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=Nothing}}}}
|
||||||
|
|
||||||
|
-- | Get the maximum account depth in the current journal.
|
||||||
|
maxDepth :: AppState -> Int
|
||||||
|
maxDepth AppState{ajournal=j} = maximum $ map accountNameLevel $ journalAccountNames j
|
||||||
|
|
||||||
|
-- | Decrement the current depth limit towards 0. If there was no depth limit,
|
||||||
|
-- set it to one less than the maximum account depth.
|
||||||
|
decDepth :: AppState -> AppState
|
||||||
|
decDepth st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts@ReportOpts{..}}}}
|
||||||
|
= st{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=dec depth_}}}}
|
||||||
|
where
|
||||||
|
dec (Just d) = Just $ max 0 (d-1)
|
||||||
|
dec Nothing = Just $ maxDepth st - 1
|
||||||
|
|
||||||
|
-- | Increment the current depth limit. If this makes it equal to the
|
||||||
|
-- the maximum account depth, remove the depth limit.
|
||||||
|
incDepth :: AppState -> AppState
|
||||||
|
incDepth st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts@ReportOpts{..}}}}
|
||||||
|
= st{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=inc depth_}}}}
|
||||||
|
where
|
||||||
|
inc (Just d) | d < (maxDepth st - 1) = Just $ d+1
|
||||||
|
inc _ = Nothing
|
||||||
|
|
||||||
|
-- | Set the current depth limit to the specified depth, which should
|
||||||
|
-- be a positive number. If it is zero, or equal to or greater than the
|
||||||
|
-- current maximum account depth, the depth limit will be removed.
|
||||||
|
-- (Slight inconsistency here: zero is currently a valid display depth
|
||||||
|
-- which can be reached using the - key. But we need a key to remove
|
||||||
|
-- the depth limit, and 0 is it.)
|
||||||
|
setDepth :: Int -> AppState -> AppState
|
||||||
|
setDepth depth st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}}
|
||||||
|
= st{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=mdepth'}}}}
|
||||||
|
where
|
||||||
|
mdepth' | depth < 0 = depth_ ropts
|
||||||
|
| depth == 0 = Nothing
|
||||||
|
| depth >= maxDepth st = Nothing
|
||||||
|
| otherwise = Just depth
|
||||||
|
|
||||||
-- | Enable the minibuffer, setting its content to the current query with the cursor at the end.
|
-- | Enable the minibuffer, setting its content to the current query with the cursor at the end.
|
||||||
stShowMinibuffer st = st{aMinibuffer=Just e}
|
stShowMinibuffer st = st{aMinibuffer=Just e}
|
||||||
where
|
where
|
||||||
@ -129,14 +166,14 @@ stHideMinibuffer st = st{aMinibuffer=Nothing}
|
|||||||
regenerateScreens :: Journal -> Day -> AppState -> AppState
|
regenerateScreens :: Journal -> Day -> AppState -> AppState
|
||||||
regenerateScreens j d st@AppState{aScreen=s,aPrevScreens=ss} =
|
regenerateScreens j d st@AppState{aScreen=s,aPrevScreens=ss} =
|
||||||
-- XXX clumsy due to entanglement of AppState and Screen.
|
-- XXX clumsy due to entanglement of AppState and Screen.
|
||||||
-- sInitFn operates only on an appstate's current screen, so
|
-- sInit operates only on an appstate's current screen, so
|
||||||
-- remove all the screens from the appstate and then add them back
|
-- remove all the screens from the appstate and then add them back
|
||||||
-- one at a time, regenerating as we go.
|
-- one at a time, regenerating as we go.
|
||||||
let
|
let
|
||||||
first:rest = reverse $ s:ss :: [Screen]
|
first:rest = reverse $ s:ss :: [Screen]
|
||||||
st0 = st{ajournal=j, aScreen=first, aPrevScreens=[]} :: AppState
|
st0 = st{ajournal=j, aScreen=first, aPrevScreens=[]} :: AppState
|
||||||
st1 = (sInitFn first) d False st0 :: AppState
|
st1 = (sInit first) d False st0 :: AppState
|
||||||
st2 = foldl' (\st s -> (sInitFn s) d False $ pushScreen s st) st1 rest :: AppState
|
st2 = foldl' (\st s -> (sInit s) d False $ pushScreen s st) st1 rest :: AppState
|
||||||
in
|
in
|
||||||
st2
|
st2
|
||||||
|
|
||||||
@ -151,7 +188,7 @@ popScreen st = st
|
|||||||
|
|
||||||
resetScreens :: Day -> AppState -> AppState
|
resetScreens :: Day -> AppState -> AppState
|
||||||
resetScreens d st@AppState{aScreen=s,aPrevScreens=ss} =
|
resetScreens d st@AppState{aScreen=s,aPrevScreens=ss} =
|
||||||
(sInitFn topscreen) d True $ stResetDepth $ stResetFilter $ stHideMinibuffer st{aScreen=topscreen, aPrevScreens=[]}
|
(sInit topscreen) d True $ stResetDepth $ stResetFilter $ stHideMinibuffer st{aScreen=topscreen, aPrevScreens=[]}
|
||||||
where
|
where
|
||||||
topscreen = case ss of _:_ -> last ss
|
topscreen = case ss of _:_ -> last ss
|
||||||
[] -> s
|
[] -> s
|
||||||
@ -162,7 +199,7 @@ resetScreens d st@AppState{aScreen=s,aPrevScreens=ss} =
|
|||||||
-- | Enter a new screen, saving the old screen & state in the
|
-- | Enter a new screen, saving the old screen & state in the
|
||||||
-- navigation history and initialising the new screen's state.
|
-- navigation history and initialising the new screen's state.
|
||||||
screenEnter :: Day -> Screen -> AppState -> AppState
|
screenEnter :: Day -> Screen -> AppState -> AppState
|
||||||
screenEnter d scr st = (sInitFn scr) d True $
|
screenEnter d scr st = (sInit scr) d True $
|
||||||
pushScreen scr
|
pushScreen scr
|
||||||
st
|
st
|
||||||
|
|
||||||
@ -230,7 +267,7 @@ _topBottomBorderWithLabel2 label = \wrapped ->
|
|||||||
-- thickness, using the current background colour or the specified
|
-- thickness, using the current background colour or the specified
|
||||||
-- colour.
|
-- colour.
|
||||||
-- XXX May disrupt border style of inner widgets.
|
-- XXX May disrupt border style of inner widgets.
|
||||||
-- XXX Should reduce the available size visible to inner widget, but doesn't seem to (cf drawRegisterScreen2).
|
-- XXX Should reduce the available size visible to inner widget, but doesn't seem to (cf rsDraw2).
|
||||||
margin :: Int -> Int -> Maybe Color -> Widget -> Widget
|
margin :: Int -> Int -> Maybe Color -> Widget -> Widget
|
||||||
margin h v mcolour = \w ->
|
margin h v mcolour = \w ->
|
||||||
Widget Greedy Greedy $ do
|
Widget Greedy Greedy $ do
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user