yavie-0.0.1: src/gtk/yavie-gtk.hs
module Main ( main ) where
import Yavie
import Yavie.Editor
import Yavie.Keybind
import Yavie.Keybind.Vi
import Graphics.UI.Gtk
import Graphics.UI.Gtk.Gdk.GC
import Graphics.Rendering.Cairo
import Control.Monad ( unless )
myConfig :: YavieConfig IO ( Window, DrawingArea, IMContext, PangoLayout ) ()
myConfig = YavieConfig {
withInitEditor = defaultWithInitEditor ,
initialize = initializeGtk ,
finalize = runGtk ,
displaySize = const $ return ( 60, 19 ) ,
supplyEvent = \ifc pe -> onImContextCommit ifc pe >> onKeyPressEvent ifc pe ,
drawDisplay = onCanvasExposeEvent ,
keybind = defaultKeybind defaultCmdbind ,
romode = defaultRomode ,
getReadOnlyFlag = defaultGetReadOnlyFlag ,
runAction = runIOAction ,
isEventDriven = True
}
runGtk :: ( Window, DrawingArea, IMContext, PangoLayout ) -> IO ()
runGtk ( win, _, _, _ ) = do
widgetShowAll win
mainGUI
onImContextCommit ::
( Window, DrawingArea, IMContext, PangoLayout ) -> ( Event -> IO Bool ) -> IO ()
onImContextCommit ( _, canvas, im, _ ) pe = do
_ <- on im imContextCommit $ \str -> do
mapM_ ( \c -> pe $ EvKey ( KASCII c ) [ ] ) str
widgetQueueDraw canvas
return ()
onKeyPressEvent ::
( Window, DrawingArea, IMContext, PangoLayout ) -> ( Event -> IO Bool ) -> IO ()
onKeyPressEvent ( window, canvas, im, _ ) pe = do
_ <- on window keyPressEvent $ do
imHandled <- imContextFilterKeypress im
if imHandled then return True else do
keyNam <- eventKeyName
keyChar <- fmap keyToChar eventKeyVal
liftIO $ case ( keyChar, keyNam ) of
( Just c, _ ) -> do _ <- pe $ EvKey ( KASCII c ) [ ]
widgetQueueDraw canvas
( _, "Return" ) -> do conti <- pe $ EvKey KEnter [ ]
unless conti mainQuit
widgetQueueDraw canvas
( _, "Escape" ) -> do _ <- pe $ EvKey KEsc [ ]
widgetQueueDraw canvas
_ -> return ()
return True
return ()
onCanvasExposeEvent ::
( Window, DrawingArea, IMContext, PangoLayout ) -> IO ( Editor c ) -> IO ()
onCanvasExposeEvent ( _, canvas, _, lay ) lnsGen = do
_ <- on canvas exposeEvent $ do
win <- eventWindow
gc <- liftIO $ gcNew win
liftIO $ do
dl <- lnsGen
let ins = isBoxCursor dl
crs = cursorPosOfDpy dl
lns = displayLines dl
layoutSetText lay $ unlines lns
PangoRectangle cx cy cw ch <-
layoutIndexToPos lay ( uncurry ( xyToN lns ) crs )
let cw_ = if ins then cw else 0
drawRectangle win gc False ( round cx ) ( round cy ) ( round cw_ ) (round ch )
renderWithDrawable win $ do
moveTo 0 0
showLayout lay
return True
return ()
initializeGtk :: IO ( Window, DrawingArea, IMContext, PangoLayout )
initializeGtk = do
pc <- cairoCreateContext Nothing
-- contextSetTextGravity pc PangoGravityEast
lay <- layoutText pc "おはよう"
_ <- initGUI
window <- windowNew
im <- imMulticontextNew
vbox <- vBoxNew True 1
frame <- frameNew
canvas <- drawingAreaNew
set window [ containerChild := vbox ]
boxPackStart vbox frame PackGrow 0
containerAdd frame canvas
widgetModifyBg canvas StateNormal ( Color 65535 65535 65535 )
_ <- onDestroy window mainQuit
_ <- on window realize $ imContextSetClientWindow im . Just =<<
widgetGetDrawWindow window
_ <- on window focusInEvent $ liftIO ( imContextFocusIn im ) >> return False
return ( window, canvas, im, lay )
main :: IO ()
main = runYavie myConfig
xyToN :: [ String ] -> Int -> Int -> Int
xyToN _ x 0 = if x < 0 then 0 else x
xyToN [ ] _ _ = error "xyToN: cursor y is over"
xyToN ( ln : lns ) x y
| y > 0 = ( length ln + 1 ) + xyToN lns x ( y - 1 )
| otherwise = error "xyToN: cursor y is negative value"