module TextUI.ItemField.BrickHelper ( getEventWidgetLocation , BChan, newBChan, writeBChan, readBChan , defaultConfig ) where import Brick.Main (lookupViewport, lookupExtent, clickedExtent) import Brick.Types (EventM, Location(..), locationRowL, locationColumnL, Extent(..), Viewport(..)) import Brick.Widgets.Core (Named(..)) import Data.Monoid ((<>)) import Lens.Micro ((^.)) import Brick.BChan (BChan, newBChan, writeBChan, readBChan) import Graphics.Vty (defaultConfig) -- | When processing a global EvMouseDown VtyEvent, the coordinates of -- the mouse event on the screen must be mapped to a specific location -- in a Widget. The `lookupExtent` function will return the "extent" -- of the Widget (i.e. where it was drawn and how big it is) but this -- only indicates that the widget was clicked and does not identify -- the actual location within the widget where the click occurred. -- -- The `getEventWidgetLocation` function translates the mouse event -- coordinates to a specific location within the widget in the -- widget's local reference frame, taking into account any scrolling -- that has occurred within a viewport that wraps that widget. -- -- drawUI st = reportExtent (getName st) $ -- viewport (getName st) Vertical $ -- Widget Fixed Fixed $ ... -- -- handleEvent event st = -- case event of -- EvMouseDown col row button _mods -> -- do wcoords <- getEventWidgetLocation fieldw col row -- case wcoords of -- Nothing -> return fieldw -- Just l -> ... -- getEventWidgetLocation :: (Named a n, Ord n) => a -> Int -> Int -> EventM n (Maybe Location) getEventWidgetLocation widget screenCol screenRow = do mExtent <- Brick.Main.lookupExtent (getName widget) case mExtent of Nothing -> return Nothing Just e@(Extent _ upperLeft _ _) -> if Brick.Main.clickedExtent (screenCol, screenRow) e then let widgetRow = screenRow - upperLeft^.locationRowL widgetCol = screenCol - upperLeft^.locationColumnL widgetLoc = Location (widgetCol, widgetRow) in do mView <- Brick.Main.lookupViewport (getName widget) case mView of Nothing -> return $ Just widgetLoc Just (VP left top _) -> return $ Just $ widgetLoc <> Location (left, top) else return Nothing -- brick now uses bounded channels (Brick.BChan.BChan for event communications instead of Control.Concurrent.Chan unbounded channels -- Brick.List now has listModify for modifying the selected element -- hBox and vBox use more efficient DList data struct