sscan-0.1: UI.hs
{-
sscan --- text UI for scanning with SANE
Copyright (C) 2017 Sean Whitton
This file is part of sscan.
sscan is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
sscan is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with sscan. If not, see <http://www.gnu.org/licenses/>.
-}
module UI (runTheApp) where
import qualified Graphics.Vty as V
import Lens.Micro ((&), (.~), (^.))
import Brick.AttrMap
import Brick.Main
import Brick.Types
import Brick.Widgets.Border as B
import Brick.Widgets.Center as C
import Brick.Widgets.Core
import Brick.Widgets.DefnList
import Presets
import Types.Preset
import Types.State
drawUI :: St -> [Widget ()]
drawUI st = [ui]
where
ui = vBox [ hBorderWithLabel (str "[ Status ]")
, vLimit 3 $ C.center $ status
, hBorderWithLabel (str "[ Current settings ]")
, vLimit 8 $ C.center $ settingsBox
, hBorderWithLabel (str "[ Presets ]")
, vLimit (2 + length presets) $ C.center $ presetsBox
, hBorderWithLabel (str "[ Actions ]")
, vLimit 6 $ C.center $ actionsBox
]
status = str $ maybe
"Ready to scan first page"
(\(ScanSess _ p _) -> "Scanned " ++ show p ++ " pages")
(st^.stScanSess)
settingsBox = defnList AlignRight Nothing
[ ("run OCRmyPDF", if st^.stOCR then "yes" else "no")
, ("colour data", show $ st^.stColour)
, ("page size", show $ st^.stPaper)
, ("DPI", show $ st^.stDPI)
, ("output format", show $ st^.stOutFormat)
, ("output dir", st^.stOutdir)
]
presetsBox = defnList AlignLeft
(Just $ V.withStyle V.currentAttr V.bold)
(map (\(Preset k desc _) -> ([k], desc)) presets)
actionsBox = defnList AlignLeft
(Just $ V.withStyle V.currentAttr V.bold) $
(if st^.stOutFormat == PDF
then (ifScanSess st
[ ("SPC", "scan next page")
, ("RET", "scan final page")
, ("q", "declare most recent scanned page was the final page")
, ("ESC", "abort/restart scanning this document")
]
[ ("SPC", "scan first page of multi-page document")
, ("RET", "scan single page document")
, ("q", "quit sscan")
]
)
else [ ("SPC|RET", "scan page")
, ("q", "quit sscan")
]
)
handleQ :: St -> EventM () (Next St)
handleQ st = halt $ ifScanSess st
(setScanSessCommand Finalise st)
(resetScanSess st) -- misnomer: this causes sscan to exit
handleRET :: St -> EventM () (Next St)
handleRET st = halt $ setScanSessCommand FinalPage st
handleSPC :: St -> EventM () (Next St)
handleSPC st = halt $ setScanSessCommand
(case st^.stOutFormat of
PDF -> NextPage
PNG -> FinalPage)
st
handleESC :: St -> EventM () (Next St)
handleESC st = ifScanSess st
(halt $ setScanSessCommand Abort st)
(continue st)
handleHotKey :: St -> Char -> EventM () (Next St)
handleHotKey st 'q' = handleQ st
handleHotKey st ' ' = handleSPC st
handleHotKey st 'o' = continue $ updateSt st
(\s -> s & stOCR .~ (not $ st^.stOCR))
handleHotKey st 'c' = continue $ updateSt st
(\s -> s & stColour .~ (cycleColour $ st^.stColour))
handleHotKey st 'p' = continue $ updateSt st
(\s -> s & stPaper .~ (cyclePaper $ st^.stPaper))
handleHotKey st c = continue $ updateSt st $
case lookupPreset c of
Just (Preset _ _ f) -> f
_ -> id
appEvent :: St -> BrickEvent () e -> EventM () (Next St)
appEvent st (VtyEvent e) =
case e of
V.EvKey (V.KEnter) [] -> handleRET st
V.EvKey (V.KEsc) [] -> handleESC st
V.EvKey (V.KChar c) [] -> handleHotKey st c
_ -> continue st
appEvent st _ = continue st
theApp :: App St e ()
theApp =
App { appDraw = drawUI
, appChooseCursor = neverShowCursor
, appHandleEvent = appEvent
, appStartEvent = return
, appAttrMap = const $ attrMap V.defAttr []
}
runTheApp :: St -> IO St
runTheApp = defaultMain theApp