Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Context Menu improvements; Select menu, Edit menu #1102

Merged
merged 42 commits into from
Sep 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
9c1d168
Allow menu to be multi-layered, move frontwardLayer + title to defaul…
dfordivam Jul 6, 2024
a119d37
FieldInput can optionally create an overlay, which will receive all V…
dfordivam Jul 6, 2024
ebb834a
Add SelectField
dfordivam Jul 10, 2024
1951209
compileHLSHandler pass events to overlay
dfordivam Jul 10, 2024
8dd944d
Use selectField in CompileHLS Target GHCs
dfordivam Jul 10, 2024
463912b
provide installedGHCs
dfordivam Jul 10, 2024
09bee3d
Reduce layer size
dfordivam Jul 12, 2024
f91be28
Make the select menu list scrollable
dfordivam Jul 12, 2024
bc5356f
Minor fix to help message
dfordivam Jul 12, 2024
51f1d3d
Pass key events to overlay in compileGHCHandler
dfordivam Jul 12, 2024
ea893cc
Use selectField for Build system selection
dfordivam Jul 12, 2024
4a1306e
Edit input overlay support
dfordivam Jul 12, 2024
0dbc97a
Pass exitKey to createEditableField
dfordivam Jul 12, 2024
0108866
Factor out core logic from menu handlers, fix advanceInstallHandler C…
dfordivam Jul 12, 2024
33ee7fb
Also allow Enter to close the edit text overlay
dfordivam Jul 12, 2024
089dead
Specify that user need to press Enter to edit
dfordivam Jul 12, 2024
dd4dad6
Pass fieldLabel to inputRender
dfordivam Jul 12, 2024
85a3e2f
Remove label from createSelectInput
dfordivam Jul 12, 2024
fbb53cc
Indicate "Press Enter to select"
dfordivam Jul 12, 2024
0f8fefa
Show the help msg over edit field, and error below
dfordivam Jul 12, 2024
44e8f7e
Filter out cross compilers for HLS target GHCs, Bootstrap, and Hadria…
dfordivam Jul 12, 2024
5ba6c37
Use selectField in bootstrap-ghc, to select from installed GHCs
dfordivam Jul 12, 2024
92fc08c
Use selectField in hadrian-ghc
dfordivam Jul 12, 2024
e6e046e
Wrap text of Edit text field's help message
dfordivam Jul 19, 2024
691feca
Move target GHCs field first, as it is a required field
dfordivam Jul 19, 2024
5e1f281
Allow multi line help message for buttons
dfordivam Jul 19, 2024
25ee8e4
Specify the required fields in the top help message
dfordivam Jul 19, 2024
ec56135
Include the overwrite patterns in help message
dfordivam Jul 19, 2024
b339668
Make HadrianGhcEditBox resourceId unique to avoid possible conflicts
dfordivam Jul 19, 2024
8e87c12
Always include editable fields for bootstrap-ghc and hadrian-ghc
dfordivam Jul 19, 2024
2bad5ce
Add editable field support with select input
dfordivam Jul 31, 2024
fdacec4
Use the select field with editable field in bootstrap-ghc and hadrian…
dfordivam Jul 31, 2024
7a877e9
Set default status of target-ghc's field to error
dfordivam Jul 31, 2024
fadd123
Change help msg color to yellow
dfordivam Aug 7, 2024
b4e8719
Use bQuit key in tutorial menu
dfordivam Aug 7, 2024
d8ade25
Use bQuit key in key info menu
dfordivam Aug 7, 2024
2666e70
Use bQuit key in advance options menus
dfordivam Aug 7, 2024
9ae87c5
Remove exitKey from editable input, only use Enter to go back
dfordivam Aug 7, 2024
f26b5c7
Change editable input fields key handling in select field
dfordivam Aug 7, 2024
6eb3c80
Use a new MenuKeyBindings data type, to capture menu navigation keybi…
dfordivam Aug 8, 2024
6d48956
minor code reformat
dfordivam Sep 26, 2024
00cf4a5
Merge remote-tracking branch 'origin/master' into dn-cmenu-overlay-1
dfordivam Sep 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib-opt/GHCup/OptParse/Compile.hs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ ghcCompileOpts =
( long "hadrian-ghc"
<> metavar "HADRIAN_GHC"
<> help
"The GHC version (or full path) to GHC that will be used to compile hadrian (must be installed)"
"The GHC version (or full path) that will be used to compile hadrian (must be installed)"
<> (completer $ versionCompleter [] GHC)
))
<*> optional
Expand Down
5 changes: 3 additions & 2 deletions lib-tui/GHCup/Brick/Actions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import qualified GHCup.Brick.Widgets.Menus.Context as ContextMenu
import GHCup.Brick.Widgets.Navigation (BrickInternalState)
import qualified GHCup.Brick.Widgets.Menus.AdvanceInstall as AdvanceInstall
import qualified GHCup.Brick.Widgets.Menus.CompileGHC as CompileGHC
import GHCup.Brick.Widgets.Menu (MenuKeyBindings(..))

import qualified Brick
import qualified Brick.Widgets.List as L
Expand Down Expand Up @@ -714,14 +715,14 @@ keyHandlers KeyBindings {..} =
where
createMenuforTool = do
e <- use (appState % to sectionListSelectedElement)
let exitKey = KeyCombination (Vty.KChar 'c') [Vty.MCtrl]
case e of
Nothing -> pure ()
Just (_, r) -> do
-- Create new ContextMenu, but maintain the state of Install/Compile
-- menus. This is especially useful in case the user made a typo and
-- would like to retry the action.
contextMenu .= ContextMenu.create r exitKey
contextMenu .= ContextMenu.create r
(MenuKeyBindings { mKbUp = bUp, mKbDown = bDown, mKbQuit = bQuit})
-- Set mode to context
mode .= ContextPanel
pure ()
Expand Down
89 changes: 42 additions & 47 deletions lib-tui/GHCup/Brick/App.hs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ import qualified GHCup.Brick.Widgets.Tutorial as Tutorial
import qualified GHCup.Brick.Widgets.Menu as Menu
import qualified GHCup.Brick.Widgets.Menus.AdvanceInstall as AdvanceInstall

import GHCup.Types (AppState (AppState, keyBindings), KeyCombination (KeyCombination))
import GHCup.List (ListResult)
import GHCup.Types (AppState (AppState, keyBindings), KeyCombination (KeyCombination), KeyBindings (..))

import qualified Brick.Focus as F
import Brick (
Expand All @@ -48,7 +49,7 @@ import Brick (
)
import qualified Brick
import Control.Monad.Reader (
MonadIO (liftIO),
MonadIO (liftIO), ReaderT,
void,
)
import Data.IORef (readIORef)
Expand All @@ -59,6 +60,7 @@ import qualified Graphics.Vty as Vty

import qualified Data.Text as T

import Optics (Lens')
import Optics.Getter (to)
import Optics.Operators ((^.))
import Optics.Optic ((%))
Expand Down Expand Up @@ -91,26 +93,31 @@ drawUI dimAttrs st =
navg = Navigation.draw dimAttrs (st ^. appState) <=> footer
in case st ^. mode of
Navigation -> [navg]
Tutorial -> [Tutorial.draw, navg]
Tutorial -> [Tutorial.draw (bQuit $ st ^. appKeys), navg]
KeyInfo -> [KeyInfo.draw (st ^. appKeys), navg]
ContextPanel -> [ContextMenu.draw (st ^. contextMenu), navg]
AdvanceInstallPanel -> [AdvanceInstall.draw (st ^. advanceInstallMenu), navg]
CompileGHCPanel -> [CompileGHC.draw (st ^. compileGHCMenu), navg]
CompileHLSPanel -> [CompileHLS.draw (st ^. compileHLSMenu), navg]
AdvanceInstallPanel -> AdvanceInstall.draw (st ^. advanceInstallMenu) ++ [navg]
CompileGHCPanel -> CompileGHC.draw (st ^. compileGHCMenu) ++ [navg]
CompileHLSPanel -> CompileHLS.draw (st ^. compileHLSMenu) ++ [navg]

-- | On q, go back to navigation.
-- On Enter, to go to tutorial
keyInfoHandler :: BrickEvent Name e -> EventM Name BrickState ()
keyInfoHandler ev = case ev of
VtyEvent (Vty.EvKey (Vty.KChar 'c') [Vty.MCtrl]) -> mode .= Navigation
VtyEvent (Vty.EvKey Vty.KEnter _ ) -> mode .= Tutorial
_ -> pure ()
keyInfoHandler ev = do
AppState { keyBindings = kb } <- liftIO $ readIORef Actions.settings'
case ev of
VtyEvent (Vty.EvKey Vty.KEnter _ ) -> mode .= Tutorial
VtyEvent (Vty.EvKey key mods)
| bQuit kb == KeyCombination key mods -> mode .= Navigation
_ -> pure ()

-- | On q, go back to navigation. Else, do nothing
tutorialHandler :: BrickEvent Name e -> EventM Name BrickState ()
tutorialHandler ev =
tutorialHandler ev = do
AppState { keyBindings = kb } <- liftIO $ readIORef Actions.settings'
case ev of
VtyEvent (Vty.EvKey (Vty.KChar 'c') [Vty.MCtrl]) -> mode .= Navigation
VtyEvent (Vty.EvKey key mods)
| bQuit kb == KeyCombination key mods -> mode .= Navigation
_ -> pure ()

-- | Tab/Arrows to navigate.
Expand All @@ -128,7 +135,7 @@ contextMenuHandler :: BrickEvent Name e -> EventM Name BrickState ()
contextMenuHandler ev = do
ctx <- use contextMenu
let focusedElement = ctx ^. Menu.menuFocusRingL % to F.focusGetCurrent
(KeyCombination exitKey mods) = ctx ^. Menu.menuExitKeyL
(KeyCombination exitKey mods) = ctx ^. Menu.menuKeyBindingsL % Menu.mKbQuitL
case (ev, focusedElement) of
(_ , Nothing) -> pure ()
(VtyEvent (Vty.EvKey k m), Just n) | k == exitKey && m == mods -> mode .= Navigation
Expand All @@ -138,47 +145,35 @@ contextMenuHandler ev = do
_ -> Common.zoom contextMenu $ ContextMenu.handler ev
--
advanceInstallHandler :: BrickEvent Name e -> EventM Name BrickState ()
advanceInstallHandler ev = do
ctx <- use advanceInstallMenu
let focusedElement = ctx ^. Menu.menuFocusRingL % to F.focusGetCurrent
(KeyCombination exitKey mods) = ctx ^. Menu.menuExitKeyL
case (ev, focusedElement) of
(_ , Nothing) -> pure ()
(VtyEvent (Vty.EvKey k m), Just n) | k == exitKey && m == mods -> mode .= ContextPanel
(VtyEvent (Vty.EvKey Vty.KEnter []), Just (MenuElement Common.OkButton)) -> do
let iopts = ctx ^. Menu.menuStateL
when (Menu.isValidMenu ctx) $
Actions.withIOAction $ Actions.installWithOptions iopts
_ -> Common.zoom advanceInstallMenu $ AdvanceInstall.handler ev
advanceInstallHandler = menuWithOverlayHandler advanceInstallMenu Actions.installWithOptions AdvanceInstall.handler

compileGHCHandler :: BrickEvent Name e -> EventM Name BrickState ()
compileGHCHandler ev = do
ctx <- use compileGHCMenu
let focusedElement = ctx ^. Menu.menuFocusRingL % to F.focusGetCurrent
(KeyCombination exitKey mods) = ctx ^. Menu.menuExitKeyL
case (ev, focusedElement) of
(_ , Nothing) -> pure ()
(VtyEvent (Vty.EvKey k m), Just n) | k == exitKey && m == mods -> mode .= ContextPanel
(VtyEvent (Vty.EvKey Vty.KEnter []), Just (MenuElement Common.OkButton)) -> do
let iopts = ctx ^. Menu.menuStateL
when (Menu.isValidMenu ctx)
(Actions.withIOAction $ Actions.compileGHC iopts)
_ -> Common.zoom compileGHCMenu $ CompileGHC.handler ev

compileGHCHandler = menuWithOverlayHandler compileGHCMenu Actions.compileGHC CompileGHC.handler

compileHLSHandler :: BrickEvent Name e -> EventM Name BrickState ()
compileHLSHandler ev = do
ctx <- use compileHLSMenu
compileHLSHandler = menuWithOverlayHandler compileHLSMenu Actions.compileHLS CompileHLS.handler

-- | Passes all events to innerHandler if an overlay is opened
-- else handles the exitKey and Enter key for the Menu's "OkButton"
menuWithOverlayHandler :: Lens' BrickState (Menu.Menu t Name)
-> (t -> ((Int, ListResult) -> ReaderT AppState IO (Either String a)))
-> (BrickEvent Name e -> EventM Name (Menu.Menu t Name) ())
-> BrickEvent Name e
-> EventM Name BrickState ()
menuWithOverlayHandler accessor action innerHandler ev = do
ctx <- use accessor
let focusedElement = ctx ^. Menu.menuFocusRingL % to F.focusGetCurrent
(KeyCombination exitKey mods) = ctx ^. Menu.menuExitKeyL
case (ev, focusedElement) of
(_ , Nothing) -> pure ()
(VtyEvent (Vty.EvKey k m), Just n) | k == exitKey && m == mods -> mode .= ContextPanel
(VtyEvent (Vty.EvKey Vty.KEnter []), Just (MenuElement Common.OkButton)) -> do
focusedField = (\n -> find (\x -> Brick.getName x == n) $ ctx ^. Menu.menuFieldsL) =<< focusedElement
(KeyCombination exitKey mods) = ctx ^. Menu.menuKeyBindingsL % Menu.mKbQuitL
case (ev, focusedElement, Menu.drawFieldOverlay =<< focusedField) of
(_ , Nothing, _) -> pure ()
(_ , _, Just _) -> Common.zoom accessor $ innerHandler ev
(VtyEvent (Vty.EvKey k m), Just n, _) | k == exitKey && m == mods -> mode .= ContextPanel
(VtyEvent (Vty.EvKey Vty.KEnter []), Just (MenuElement Common.OkButton), _) -> do
let iopts = ctx ^. Menu.menuStateL
when (Menu.isValidMenu ctx)
(Actions.withIOAction $ Actions.compileHLS iopts)
_ -> Common.zoom compileHLSMenu $ CompileHLS.handler ev
(Actions.withIOAction $ action iopts)
_ -> Common.zoom accessor $ innerHandler ev

eventHandler :: BrickEvent Name e -> EventM Name BrickState ()
eventHandler ev = do
Expand Down
2 changes: 1 addition & 1 deletion lib-tui/GHCup/Brick/Attributes.hs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ defaultAttributes no_color = Brick.attrMap
, (dayAttr , Vty.defAttr `withForeColor` Vty.brightCyan)
, (helpAttr , Vty.defAttr `withStyle` Vty.italic)
, (hoorayAttr , Vty.defAttr `withForeColor` Vty.brightWhite)
, (helpMsgAttr , Vty.defAttr `withForeColor` Vty.brightBlack)
, (helpMsgAttr , Vty.defAttr `withForeColor` Vty.yellow)
, (errMsgAttr , Vty.defAttr `withForeColor` Vty.red)
]
where
Expand Down
8 changes: 7 additions & 1 deletion lib-tui/GHCup/Brick/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ module GHCup.Brick.Common (
, BuildFlavourEditBox, BuildSystemEditBox, OkButton, AdvanceInstallButton
, CompileGHCButton, CompileHLSButton, CabalProjectEditBox
, CabalProjectLocalEditBox, UpdateCabalCheckBox, GitRefEditBox
, BootstrapGhcSelectBox, HadrianGhcSelectBox
) ) where

import GHCup.List ( ListResult )
Expand Down Expand Up @@ -98,7 +99,7 @@ pattern TargetGhcEditBox = ResourceId 6
pattern BootstrapGhcEditBox :: ResourceId
pattern BootstrapGhcEditBox = ResourceId 7
pattern HadrianGhcEditBox :: ResourceId
pattern HadrianGhcEditBox = ResourceId 17
pattern HadrianGhcEditBox = ResourceId 20
pattern JobsEditBox :: ResourceId
pattern JobsEditBox = ResourceId 8
pattern BuildConfigEditBox :: ResourceId
Expand Down Expand Up @@ -126,6 +127,11 @@ pattern UpdateCabalCheckBox = ResourceId 18
pattern GitRefEditBox :: ResourceId
pattern GitRefEditBox = ResourceId 19

pattern BootstrapGhcSelectBox :: ResourceId
pattern BootstrapGhcSelectBox = ResourceId 21
pattern HadrianGhcSelectBox :: ResourceId
pattern HadrianGhcSelectBox = ResourceId 22

-- | Name data type. Uniquely identifies each widget in the TUI.
-- some constructors might end up unused, but still is a good practise
-- to have all of them defined, just in case
Expand Down
2 changes: 1 addition & 1 deletion lib-tui/GHCup/Brick/Widgets/KeyInfo.hs
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,4 @@ draw KeyBindings {..} =
]
]
]
<=> Brick.hBox [Brick.txt "Press c+ctrl to return to Navigation" <+> Brick.padRight Brick.Max (Brick.txt " ") <+> Brick.txt "Press Enter to go to the Tutorial"]
<=> Brick.hBox [Brick.txt "Press " <+> Common.keyToWidget bQuit <+> Brick.txt " to return to Navigation" <+> Brick.padRight Brick.Max (Brick.txt " ") <+> Brick.txt "Press Enter to go to the Tutorial"]
Loading
Loading