1 patch for repository ham...@code.haskell.org:/srv/code/yi: Sun Apr 4 22:35:55 NZST 2010 Hamish Mackenzie <hamish.k.macken...@googlemail.com> * More progress on Yi.UI.Pango.Control
-- Yi development mailing list yi-devel@googlegroups.com http://groups.google.com/group/yi-devel
To unsubscribe, reply using "remove me" as the subject.
New patches: [More progress on Yi.UI.Pango.Control Hamish Mackenzie <hamish.k.macken...@googlemail.com>**20100404103555 Ignore-this: 212c8aec438a6a0742f2690242f352a4 ] hunk ./src/Yi/Core.hs 43 -- * Misc , runAction , withSyntax + , focusAllSyntax ) where hunk ./src/Yi/UI/Pango.hs 9 -- | This module defines a user interface implemented using gtk2hs and -- pango for direct text rendering. -module Yi.UI.Pango (start) where +module Yi.UI.Pango (start, processEvent) where import Prelude (filter, map, round, FilePath, (/)) hunk ./src/Yi/UI/Pango/Control.hs 1 -{-# LANGUAGE RecordWildCards, ScopedTypeVariables, MultiParamTypeClasses, DeriveDataTypeable, StandaloneDeriving, GeneralizedNewtypeDeriving #-} +{-# LANGUAGE RecordWildCards, ScopedTypeVariables, MultiParamTypeClasses, DeriveDataTypeable, + StandaloneDeriving, GeneralizedNewtypeDeriving #-} ----------------------------------------------------------------------------- -- -- Module : Yi.UI.Pango.Control hunk ./src/Yi/UI/Pango/Control.hs 19 , Buffer(..) , View(..) , Iter(..) -, newControl +, startControl , runControl hunk ./src/Yi/UI/Pango/Control.hs 21 +, controlIO +, liftYi +, getControl , newBuffer , newView , getBuffer hunk ./src/Yi/UI/Pango/Control.hs 35 import Prelude (map) -import Data.List (drop, zip, take) +import Data.Maybe (maybe, fromJust) +import Data.IORef +import Data.List (drop, zip, take, length) +import Data.Prototype import qualified Data.Rope as Rope hunk ./src/Yi/UI/Pango/Control.hs 40 -import Yi hiding(withBuffer) -import Yi.Window +import qualified Data.Map as Map +import Yi.Prelude +import Yi.Core (startEditor, focusAllSyntax) +import Yi.Buffer +import Yi.Config +import Yi.Window as Yi import Yi.Editor hunk ./src/Yi/UI/Pango/Control.hs 47 +import Yi.Event +import Yi.Keymap hiding(withBuffer) import Yi.Monad import Yi.Style import Yi.UI.Utils hunk ./src/Yi/UI/Pango/Control.hs 52 -import Graphics.UI.Gtk as Gtk hiding(Point, Region) -import Control.Monad.Reader -import Control.Monad.State +import Graphics.UI.Gtk as Gtk hiding(Action, Point, Region, get) +import qualified Graphics.UI.Gtk.Gdk.Events as Gdk.Events +import System.Glib.GError +import Control.Monad.Reader (liftIO, ask, asks, MonadReader(..)) +import Control.Monad.State (liftM, ap, get, put, modify) import Control.Monad.Writer (MonadIO(..)) hunk ./src/Yi/UI/Pango/Control.hs 58 -import Control.Concurrent (newMVar, modifyMVar, MVar(..)) +import Control.Concurrent (newMVar, modifyMVar, MVar(..), newEmptyMVar, putMVar, readMVar, isEmptyMVar) import Data.Typeable hunk ./src/Yi/UI/Pango/Control.hs 60 -import qualified Data.List.PointedList as PL (insertRight) +import qualified Data.List.PointedList as PL (insertRight, withFocus, PointedList(..), singleton) import Yi.Regex import System.FilePath hunk ./src/Yi/UI/Pango/Control.hs 63 +import qualified Yi.UI.Common as Common +import Yi.UI.Pango (processEvent) data Control = Control hunk ./src/Yi/UI/Pango/Control.hs 67 - { config :: Config - , editor :: MVar Editor + { controlYi :: Yi + , tabCache :: IORef [TabInfo] + , views :: IORef (Map.Map WindowRef View) } hunk ./src/Yi/UI/Pango/Control.hs 71 +-- { config :: Config +-- , editor :: Editor +-- , input :: Event -> IO () +-- , output :: Action -> IO () +-- } hunk ./src/Yi/UI/Pango/Control.hs 77 -newtype ControlM a = ControlM { runControl' :: ReaderT Control IO a } - deriving (Monad, MonadReader Control, MonadIO, Typeable, Functor) +data TabInfo = TabInfo + { coreTab :: PL.PointedList Yi.Window +-- , page :: VBox + } + +instance Show TabInfo where + show t = show (coreTab t) + +--type ControlM = YiM +newtype ControlM a = ControlM { runControl'' :: ReaderT Control IO a } + deriving (Monad, MonadIO, MonadReader Control, Typeable, Functor, Applicative) + +-- Helper functions to avoid issues with mismatching monad libraries +controlIO :: IO a -> ControlM a +controlIO = liftIO + +getControl :: ControlM Control +getControl = ask + +liftYi :: YiM a -> ControlM a +liftYi m = do + yi <- asks controlYi + liftIO $ runReaderT (runYiM m) yi + +--instance MonadState Editor ControlM where +-- get = readRef =<< editor <$> ask +-- put v = flip modifyRef (const v) =<< editor <$> ask + +--instance MonadEditor ControlM where +-- askCfg = config <$> ask +-- withEditor f = do +-- r <- asks editor +-- cfg <- asks config +-- liftIO $ controlUnsafeWithEditor cfg r f + +startControl :: Config -> ControlM () -> IO () +startControl config main = do + startEditor (config { startFrontEnd = start main } ) Nothing + +runControl' :: ControlM a -> MVar Control -> IO (Maybe a) +runControl' m yiMVar = do + empty <- isEmptyMVar yiMVar + if empty + then return Nothing + else do + yi <- readMVar yiMVar + result <- runControl m yi + return $ Just result + +-- runControl :: ControlM a -> Yi -> IO a +-- runControl m yi = runReaderT (runYiM m) yi + +runControl :: ControlM a -> Control -> IO a +runControl f s = runReaderT (runControl'' f) s + +-- runControlEditor f yiMVar = yiMVar + +runAction :: Action -> ControlM () +runAction action = do + out <- liftYi $ asks output + liftIO $ out [action] + +-- | Test 2 +mkUI :: IO () -> MVar Control -> Common.UI +mkUI main yiMVar = Common.dummyUI + { Common.main = main + , Common.end = \_ -> runControl' end yiMVar >> return () + , Common.suspend = runControl' suspend yiMVar >> return () + , Common.refresh = \e -> runControl' (refresh e) yiMVar >> return () + , Common.layout = \e -> liftM (maybe e id) $ runControl' (doLayout e) yiMVar + , Common.reloadProject = \f -> runControl' (reloadProject f) yiMVar >> return () + } + +start :: ControlM () -> UIBoot +start main cfg ch outCh ed = catchGError (startNoMsg main cfg ch outCh ed) (\(GError _dom _code msg) -> fail msg) + +makeControl :: MVar Control -> YiM () +makeControl controlMVar = do + controlYi <- ask + tabCache <- liftIO $ newIORef [] + views <- liftIO $ newIORef Map.empty + liftIO $ putMVar controlMVar Control{..} + +startNoMsg :: ControlM () -> UIBoot +startNoMsg main config input output ed = do + control <- newEmptyMVar + let wrappedMain = do + output [makeAction $ makeControl control] + runControl' main control >> return () + return (mkUI wrappedMain control) + +end :: ControlM () +end = do + liftIO $ putStrLn "Yi Control End" + liftIO $ mainQuit + +suspend :: ControlM () +suspend = do + liftIO $ putStrLn "Yi Control Suspend" + return () + +refresh :: Editor -> ControlM () +refresh e = do + --contextId <- statusbarGetContextId (uiStatusbar ui) "global" + --statusbarPop (uiStatusbar ui) contextId + --statusbarPush (uiStatusbar ui) contextId $ intercalate " " $ statusLine e + + updateCache e -- The cursor may have changed since doLayout + viewsRef <- asks views + vs <- liftIO $ readRef viewsRef + forM_ (Map.elems vs) $ \v -> do + let b = findBufferWith (viewFBufRef v) e + -- when (not $ null $ b ^. pendingUpdatesA) $ + do + -- sig <- readIORef (renderer w) + -- signalDisconnect sig + -- writeRef (renderer w) =<< (textview w `onExpose` render e ui b (wkey (coreWin w))) + liftIO $ widgetQueueDraw (drawArea v) + +doLayout :: Editor -> ControlM Editor +doLayout e = do + liftIO $ putStrLn "Yi Control Do Layout" + updateCache e + cacheRef <- asks tabCache + tabs <- liftIO $ readRef cacheRef + heights <- concat <$> mapM (getHeightsInTab e) tabs + let e' = (tabsA ^: fmap (fmap updateWin)) e + updateWin w = case find (\(ref,_,_) -> (wkey w == ref)) heights of + Nothing -> w + Just (_,h,rgn) -> w { height = h, winRegion = rgn } + + -- Don't leak references to old Windows + let forceWin x w = height w `seq` winRegion w `seq` x + return $ (foldl . foldl) forceWin e' (e' ^. tabsA) + +getHeightsInTab :: Editor -> TabInfo -> ControlM [(WindowRef,Int,Region)] +getHeightsInTab e tab = do + viewsRef <- asks views + vs <- liftIO $ readRef viewsRef + foldlM (\a w -> do + case Map.lookup (wkey w) vs of + Just v -> do + (_, h) <- liftIO $ widgetGetSize $ drawArea v + let lineHeight = ascent (metrics v) + descent (metrics v) + let b0 = findBufferWith (viewFBufRef v) e + rgn <- shownRegion e v b0 + let ret= (windowRef v, round $ fromIntegral h / lineHeight, rgn) + return $ a ++ [ret] + Nothing -> return a) + [] (coreTab tab) + +shownRegion :: Editor -> View -> FBuffer -> ControlM Region +shownRegion e v b = do + (tos, _, bos) <- updatePango e v b (layout v) + return $ mkRegion tos bos + +updatePango :: Editor -> View -> FBuffer -> PangoLayout -> ControlM (Point, Point, Point) +updatePango e v b layout = do + (width', height') <- liftIO $ widgetGetSize $ drawArea v + + font <- liftIO $ layoutGetFontDescription layout + + --oldFont <- layoutGetFontDescription layout + --oldFontStr <- maybe (return Nothing) (fmap Just . fontDescriptionToString) oldFont + --newFontStr <- Just <$> fontDescriptionToString font + --when (oldFontStr /= newFontStr) (layoutSetFontDescription layout (Just font)) + + let win = findWindowWith (windowRef v) e + [width'', height''] = map fromIntegral [width', height'] + lineHeight = ascent (metrics v) + descent (metrics v) + winh = max 1 $ floor (height'' / lineHeight) + + (tos, point, text) = askBuffer win b $ do + from <- getMarkPointB =<< fromMark <$> askMarks + rope <- streamB Forward from + p <- pointB + let content = fst $ Rope.splitAtLine winh rope + -- allow BOS offset to be just after the last line + let addNL = if Rope.countNewLines content == winh + then id + else (++"\n") + return (from, p, addNL $ Rope.toString content) + + config <- liftYi $ askCfg + if configLineWrap $ configUI config + then do oldWidth <- liftIO $ layoutGetWidth layout + when (oldWidth /= Just width'') $ liftIO $ layoutSetWidth layout $ Just width'' + else do (Rectangle px _py pwidth _pheight, _) <- liftIO $ layoutGetPixelExtents layout + liftIO $ widgetSetSizeRequest (drawArea v) (px+pwidth) (-1) + + -- optimize for cursor movement + oldText <- liftIO $ layoutGetText layout + when (oldText /= text) $ liftIO $ layoutSetText layout text + + (_, bosOffset, _) <- liftIO $ layoutXYToIndex layout width'' (fromIntegral winh * lineHeight - 1) + return (tos, point, tos + fromIntegral bosOffset + 1) + +updateCache :: Editor -> ControlM () +updateCache e = do + let tabs = e ^. tabsA + cacheRef <- asks tabCache + cache <- liftIO $ readRef cacheRef + cache' <- syncTabs e (toList $ PL.withFocus tabs) cache + liftIO $ writeRef cacheRef cache' + +syncTabs :: Editor -> [(PL.PointedList Yi.Window, Bool)] -> [TabInfo] -> ControlM [TabInfo] +syncTabs e (tfocused@(t,focused):ts) (c:cs) + | t == coreTab c = + do when focused $ setTabFocus c +-- let vCache = views c + (:) <$> syncTab e c t <*> syncTabs e ts cs + | t `elem` map coreTab cs = + do removeTab c + syncTabs e (tfocused:ts) cs + | otherwise = + do c' <- insertTabBefore e t c + when focused $ setTabFocus c' + return (c':) `ap` syncTabs e ts (c:cs) +syncTabs e ts [] = mapM (\(t,focused) -> do + c' <- insertTab e t + when focused $ setTabFocus c' + return c') ts +syncTabs _ [] cs = mapM_ removeTab cs >> return [] + +syncTab :: Editor -> TabInfo -> PL.PointedList Yi.Window -> ControlM TabInfo +syncTab e tab ws = do + -- TODO Maybe do something here + return tab + +setTabFocus :: TabInfo -> ControlM () +setTabFocus t = do + -- TODO this needs to set the tab focus with callback + -- but only if the tab focus has changed + return () + +askBuffer :: Yi.Window -> FBuffer -> BufferM a -> a +askBuffer w b f = fst $ runBuffer w b f + +setWindowFocus :: Editor -> TabInfo -> View -> ControlM () +setWindowFocus e t v = do + let bufferName = shortIdentString (commonNamePrefix e) $ findBufferWith (viewFBufRef v) e + window = findWindowWith (windowRef v) e + ml = askBuffer window (findBufferWith (viewFBufRef v) e) $ getModeLine (commonNamePrefix e) + +-- TODO +-- update (textview w) widgetIsFocus True +-- update (modeline w) labelText ml +-- update (uiWindow ui) windowTitle $ bufferName ++ " - Yi" +-- update (uiNotebook ui) (notebookChildTabLabel (page t)) (tabAbbrevTitle bufferName) + return () + +removeTab :: TabInfo -> ControlM () +removeTab t = do + -- TODO this needs to close the views in the tab with callback + return () + +removeView :: TabInfo -> View -> ControlM () +removeView tab view = do + -- TODO this needs to close the view with callback + return () + +-- | Make a new tab. +newTab :: Editor -> PL.PointedList Yi.Window -> ControlM TabInfo +newTab e ws = do + let t' = TabInfo { coreTab = ws } +-- cache <- syncWindows e t' (toList $ PL.withFocus ws) [] + return t' -- { views = cache } + +insertTabBefore :: Editor -> PL.PointedList Yi.Window -> TabInfo -> ControlM TabInfo +insertTabBefore e ws c = do + -- Just p <- notebookPageNum (uiNotebook ui) (page c) + -- vb <- vBoxNew False 1 + -- notebookInsertPage (uiNotebook ui) vb "" p + -- widgetShowAll $ vb + t <- newTab e ws + return t hunk ./src/Yi/UI/Pango/Control.hs 354 -instance MonadState Editor ControlM where - get = readRef =<< editor <$> ask - put v = flip modifyRef (const v) =<< editor <$> ask +insertTab :: Editor -> PL.PointedList Yi.Window -> ControlM TabInfo +insertTab e ws = do + -- vb <- vBoxNew False 1 + -- notebookAppendPage (uiNotebook ui) vb "" + -- widgetShowAll $ vb + t <- newTab e ws + return t hunk ./src/Yi/UI/Pango/Control.hs 362 -instance MonadEditor ControlM where - askCfg = config <$> ask - withEditor f = do - r <- asks editor - cfg <- asks config - liftIO $ controlUnsafeWithEditor cfg r f +{- +insertWindowBefore :: Editor -> TabInfo -> Yi.Window -> WinInfo -> IO WinInfo +insertWindowBefore e ui tab w _c = insertWindow e ui tab w + +insertWindowAtEnd :: Editor -> UI -> TabInfo -> Window -> IO WinInfo +insertWindowAtEnd e ui tab w = insertWindow e ui tab w + +insertWindow :: Editor -> UI -> TabInfo -> Window -> IO WinInfo +insertWindow e ui tab win = do + let buf = findBufferWith (bufkey win) e + liftIO $ do w <- newWindow e ui win buf + + set (page tab) $ + [ containerChild := widget w + , boxChildPacking (widget w) := + if isMini (coreWin w) + then PackNatural + else PackGrow + ] + + let ref = (wkey . coreWin) w + textview w `onButtonRelease` handleClick ui ref + textview w `onButtonPress` handleClick ui ref + textview w `onScroll` handleScroll ui ref + textview w `onConfigure` handleConfigure ui ref + widgetShowAll (widget w) + + return w +-} + +reloadProject :: FilePath -> ControlM () +reloadProject _ = return () controlUnsafeWithEditor :: Config -> MVar Editor -> EditorM a -> IO a controlUnsafeWithEditor cfg r f = modifyMVar r $ \e -> do hunk ./src/Yi/UI/Pango/Control.hs 415 , windowRef :: WindowRef , drawArea :: DrawingArea , layout :: PangoLayout + , language :: Language + , metrics :: FontMetrics , scrollWin :: ScrolledWindow hunk ./src/Yi/UI/Pango/Control.hs 418 + , shownTos :: IORef Point + , winMotionSignal :: IORef (Maybe (ConnectId DrawingArea)) } data Iter = Iter hunk ./src/Yi/UI/Pango/Control.hs 427 , point :: Point } -newControl :: Config -> IO Control -newControl config = do - editor <- newMVar emptyEditor - return Control {..} - -runControl :: ControlM a -> Control -> IO a -runControl f s = runReaderT (runControl' f) s - newBuffer :: BufferId -> String -> ControlM Buffer newBuffer id text = do hunk ./src/Yi/UI/Pango/Control.hs 429 - fBufRef <- liftEditor $ stringToNewBuffer id $ Rope.fromString text + fBufRef <- liftYi $ withEditor $ newBufferE id $ Rope.fromString text return Buffer{..} hunk ./src/Yi/UI/Pango/Control.hs 432 -newView :: Buffer -> ControlM View -newView buffer = do +newView :: Buffer -> FontDescription -> ControlM View +newView buffer font = do control <- ask hunk ./src/Yi/UI/Pango/Control.hs 435 - config <- askCfg + config <- liftYi $ askCfg let viewFBufRef = fBufRef buffer hunk ./src/Yi/UI/Pango/Control.hs 437 - window <- fmap (\w -> w{height=50, winRegion = mkRegion (Point 0) (Point 2000)}) $ liftEditor $ newWindowE False viewFBufRef - let windowRef = wkey window - liftEditor $ modA windowsA (PL.insertRight window) + newWindow <- fmap (\w -> w{height=50, winRegion = mkRegion (Point 0) (Point 2000)}) $ liftYi $ withEditor $ newWindowE False viewFBufRef + let windowRef = wkey newWindow + liftYi $ withEditor $ do + modA windowsA (PL.insertRight newWindow) + e <- get + put $ focusAllSyntax e drawArea <- liftIO $ drawingAreaNew hunk ./src/Yi/UI/Pango/Control.hs 444 + liftIO $ widgetModifyBg drawArea StateNormal $ mkCol False $ Yi.Style.background $ baseAttributes $ configStyle $ configUI config context <- liftIO $ widgetCreatePangoContext drawArea layout <- liftIO $ layoutEmpty context hunk ./src/Yi/UI/Pango/Control.hs 447 - liftIO $ layoutSetText layout "Test" + liftIO $ layoutSetFontDescription layout (Just font) + language <- liftIO $ contextGetLanguage context + metrics <- liftIO $ contextGetMetrics context font language + liftIO $ layoutSetText layout "" + + scrollWin <- liftIO $ scrolledWindowNew Nothing Nothing + liftIO $ do + scrolledWindowAddWithViewport scrollWin drawArea + scrolledWindowSetPolicy scrollWin PolicyAutomatic PolicyNever + + initialTos <- liftYi $ withEditor $ withGivenBufferAndWindow0 newWindow viewFBufRef $ + getMarkPointB =<< fromMark <$> askMarks + shownTos <- liftIO $ newIORef initialTos + winMotionSignal <- liftIO $ newIORef Nothing + + let view = View {..} + + liftIO $ Gtk.widgetAddEvents drawArea [KeyPressMask] + liftIO $ Gtk.set drawArea [Gtk.widgetCanFocus := True] + + liftIO $ drawArea `Gtk.onKeyPress` \event -> do + putStrLn $ "Yi Control Key Press = " ++ show event + runControl (do + runAction $ makeAction $ do + focusWindowE windowRef + switchToBufferE viewFBufRef) control + result <- processEvent (input $ controlYi control) event + widgetQueueDraw drawArea + return result + + liftIO $ drawArea `Gtk.onButtonPress` \event -> do + widgetGrabFocus drawArea + runControl (handleClick view event) control + + liftIO $ drawArea `Gtk.onButtonRelease` \event -> do + runControl (handleClick view event) control + + liftIO $ drawArea `Gtk.onScroll` \event -> do + runControl (handleScroll view event) control liftIO $ drawArea `Gtk.onExpose` \event -> do hunk ./src/Yi/UI/Pango/Control.hs 488 - (text, allAttrs, debug) <- runControl (liftEditor $ do + (text, allAttrs, debug, tos, rel, point, inserting) <- runControl (liftYi $ withEditor $ do + window <- (findWindowWith windowRef) <$> get modA buffersA (fmap (clearSyntax . clearHighlight)) let winh = height window let tos = max 0 (regionStart (winRegion window)) hunk ./src/Yi/UI/Pango/Control.hs 494 let bos = regionEnd (winRegion window) + let rel p = fromIntegral (p - tos) withGivenBufferAndWindow0 window viewFBufRef $ do hunk ./src/Yi/UI/Pango/Control.hs 497 - -- tos <- getMarkPointB =<< fromMark <$> askMarks - rope <- streamB Forward tos - point <- pointB + -- tos <- getMarkPointB =<< fromMark <$> askMarks + rope <- streamB Forward tos + point <- pointB + inserting <- getA insertingA + + modeNm <- gets (withMode0 modeName) + -- let (tos, point, text, picture) = do runBu -- from <- getMarkPointB =<< fromMark <$> askMarks -- rope <- streamB Forward from hunk ./src/Yi/UI/Pango/Control.hs 523 -- add color attributes. let strokes = [(start',s,end') | ((start', s), end') <- zip picture (drop 1 (map fst picture) ++ [bos]), s /= emptyAttributes] - rel p = fromIntegral (p - tos) allAttrs = concat $ do (p1, Attributes fg bg _rv bd itlc udrl, p2) <- strokes return $ [ AttrForeground (rel p1) (rel p2) (mkCol True fg) hunk ./src/Yi/UI/Pango/Control.hs 531 , AttrUnderline (rel p1) (rel p2) (if udrl then UnderlineSingle else UnderlineNone) , AttrWeight (rel p1) (rel p2) (if bd then WeightBold else WeightNormal) ] - return (text, allAttrs, (picture, strokes))) control + return (text, allAttrs, (picture, strokes, modeNm, window, tos, bos, winh), tos, rel, point, inserting)) control hunk ./src/Yi/UI/Pango/Control.hs 533 - putStrLn $ "Setting Layout Attributes " ++ show debug + -- putStrLn $ "Setting Layout Attributes " ++ show debug layoutSetAttributes layout allAttrs hunk ./src/Yi/UI/Pango/Control.hs 535 - putStrLn "Done Stting Layout Attributes" + -- putStrLn "Done Stting Layout Attributes" dw <- widgetGetDrawWindow drawArea gc <- gcNew dw oldText <- layoutGetText layout hunk ./src/Yi/UI/Pango/Control.hs 541 when (text /= oldText) $ layoutSetText layout text drawLayout dw gc 0 0 layout + liftIO $ writeRef shownTos tos + + -- paint the cursor + (PangoRectangle curx cury curw curh, _) <- layoutGetCursorPos layout (rel point) + PangoRectangle chx chy chw chh <- layoutIndexToPos layout (rel point) + + gcSetValues gc (newGCValues { Gtk.foreground = mkCol True $ Yi.Style.foreground $ baseAttributes $ configStyle $ configUI config }) + if inserting + then do drawLine dw gc (round curx, round cury) (round $ curx + curw, round $ cury + curh) + else do drawRectangle dw gc False (round chx) (round chy) (if chw > 0 then round chw else 8) (round chh) + return True hunk ./src/Yi/UI/Pango/Control.hs 554 - scrollWin <- liftIO $ scrolledWindowNew Nothing Nothing - liftIO $ scrolledWindowAddWithViewport scrollWin drawArea - return View {..} + liftIO $ widgetGrabFocus drawArea + + tabsRef <- asks tabCache + ts <- liftIO $ readRef tabsRef + liftIO $ writeRef tabsRef (TabInfo (PL.singleton newWindow):ts) + + viewsRef <- asks views + vs <- liftIO $ readRef viewsRef + liftIO $ writeRef viewsRef $ Map.insert windowRef view vs + + return view where clearHighlight fb = -- if there were updates, then hide the selection. hunk ./src/Yi/UI/Pango/Control.hs 576 setBufferMode f buffer = do let bufRef = fBufRef buffer -- adjust the mode - tbl <- asks (modeTable . config) - contents <- liftEditor $ withGivenBuffer0 bufRef $ elemsB + tbl <- liftYi $ asks (modeTable . yiConfig) + contents <- liftYi $ withEditor $ withGivenBuffer0 bufRef $ elemsB let header = take 1024 contents hmode = case header =~ "\\-\\*\\- *([^ ]*) *\\-\\*\\-" of AllTextSubmatches [_,m] -> m hunk ./src/Yi/UI/Pango/Control.hs 587 Just (AnyMode emptyMode) case mode of AnyMode newMode -> do - liftIO $ putStrLn $ show (f, header, modeName newMode) - liftEditor $ withGivenBuffer0 bufRef $ setMode newMode + -- liftIO $ putStrLn $ show (f, modeName newMode) + liftYi $ withEditor $ do + withGivenBuffer0 bufRef $ do + setMode newMode + modify clearSyntax + switchToBufferE bufRef + -- withEditor focusAllSyntax withBuffer :: Buffer -> BufferM a -> ControlM a hunk ./src/Yi/UI/Pango/Control.hs 596 -withBuffer Buffer{fBufRef = b} f = liftEditor $ withGivenBuffer0 b f +withBuffer Buffer{fBufRef = b} f = liftYi $ withEditor $ withGivenBuffer0 b f getBuffer :: View -> Buffer getBuffer view = Buffer {fBufRef = viewFBufRef view} hunk ./src/Yi/UI/Pango/Control.hs 604 setText :: Buffer -> String -> ControlM () setText b text = withBuffer b $ do r <- regionOfB Document + replaceRegionClever r text getText :: Buffer -> Iter -> Iter -> ControlM String hunk ./src/Yi/UI/Pango/Control.hs 618 (fromIntegral y * 256) (fromIntegral z * 256) +handleClick :: View -> Gdk.Events.Event -> ControlM Bool +handleClick view event = do + control <- ask + -- (_tabIdx,winIdx,w) <- getWinInfo ref <$> readIORef (tabCache ui) + + logPutStrLn $ "Click: " ++ show (Gdk.Events.eventX event, + Gdk.Events.eventY event, + Gdk.Events.eventClick event) + + -- retrieve the clicked offset. + (_,layoutIndex,_) <- io $ layoutXYToIndex (layout view) (Gdk.Events.eventX event) (Gdk.Events.eventY event) + tos <- readRef (shownTos view) + let p1 = tos + fromIntegral layoutIndex + + let winRef = windowRef view + + -- maybe focus the window + -- logPutStrLn $ "Clicked inside window: " ++ show view + +-- let focusWindow = do + -- TODO: check that tabIdx is the focus? +-- modA windowsA (fromJust . PL.move winIdx) + + liftIO $ case (Gdk.Events.eventClick event, Gdk.Events.eventButton event) of + (Gdk.Events.SingleClick, Gdk.Events.LeftButton) -> do + cid <- onMotionNotify (drawArea view) False $ \event -> do + runControl (handleMove view p1 event) control + writeRef (winMotionSignal view) $ Just cid + + _ -> do maybe (return ()) signalDisconnect =<< readRef (winMotionSignal view) + writeRef (winMotionSignal view) Nothing + + case (Gdk.Events.eventClick event, Gdk.Events.eventButton event) of + (Gdk.Events.SingleClick, Gdk.Events.LeftButton) -> runAction . makeAction $ do + -- b <- gets $ (bkey . findBufferWith (viewFBufRef view)) + -- focusWindow + window <- (findWindowWith winRef) <$> get + withGivenBufferAndWindow0 window (viewFBufRef view) $ do + moveTo p1 + setVisibleSelection False + -- (Gdk.Events.SingleClick, _) -> runAction focusWindow + (Gdk.Events.ReleaseClick, Gdk.Events.MiddleButton) -> do + disp <- liftIO $ widgetGetDisplay (drawArea view) + cb <- liftIO $ clipboardGetForDisplay disp selectionPrimary + let cbHandler Nothing = return () + cbHandler (Just txt) = runControl (runAction . makeAction $ do + window <- (findWindowWith winRef) <$> get + withGivenBufferAndWindow0 window (viewFBufRef view) $ do + pointB >>= setSelectionMarkPointB + moveTo p1 + insertN txt) control + liftIO $ clipboardRequestText cb cbHandler + _ -> return () + + liftIO $ widgetQueueDraw (drawArea view) + return True + +handleScroll :: View -> Gdk.Events.Event -> ControlM Bool +handleScroll view event = do + let editorAction = do + withBuffer0 $ vimScrollB $ case Gdk.Events.eventDirection event of + Gdk.Events.ScrollUp -> (-1) + Gdk.Events.ScrollDown -> 1 + _ -> 0 -- Left/right scrolling not supported + + runAction $ makeAction editorAction + liftIO $ widgetQueueDraw (drawArea view) + return True + +handleMove :: View -> Point -> Gdk.Events.Event -> ControlM Bool +handleMove view p0 event = do + logPutStrLn $ "Motion: " ++ show (Gdk.Events.eventX event, Gdk.Events.eventY event) + + -- retrieve the clicked offset. + (_,layoutIndex,_) <- liftIO $ layoutXYToIndex (layout view) (Gdk.Events.eventX event) (Gdk.Events.eventY event) + tos <- readRef (shownTos view) + let p1 = tos + fromIntegral layoutIndex + + + let editorAction = do + txt <- withBuffer0 $ do + if p0 /= p1 + then Just <$> do + m <- selMark <$> askMarks + setMarkPointB m p0 + moveTo p1 + setVisibleSelection True + readRegionB =<< getSelectRegionB + else return Nothing + maybe (return ()) setRegE txt + + runAction $ makeAction editorAction + -- drawWindowGetPointer (textview w) -- be ready for next message. + + -- Relies on uiActionCh being synchronous + selection <- liftIO $ newIORef "" + let yiAction = do + txt <- withEditor (withBuffer0 (readRegionB =<< getSelectRegionB)) + :: YiM String + liftIO $ writeIORef selection txt + runAction $ makeAction yiAction + txt <- liftIO $ readIORef selection + + disp <- liftIO $ widgetGetDisplay (drawArea view) + cb <- liftIO $ clipboardGetForDisplay disp selectionPrimary + liftIO $ clipboardSetWithData cb [(targetString,0)] + (\0 -> selectionDataSetText txt >> return ()) (return ()) + + liftIO $ widgetQueueDraw (drawArea view) + return True Context: [IReader.hs: switch M-Del to M-0 gwe...@gmail.com**20100325154110 Ignore-this: 8a220d97977e5db509d7b6b344611ea M-Del doesn't work with urxvt, it seems, and I am doubtful it works in general. But M-0 will work or fail with the other bindings. ] [Cleanup syntax files jeffwhee...@gmail.com**20100326043211 Ignore-this: 714d6df1f570a4de23fb052b04e93944 ] [Significant cleanup, -Wall to Yi.Syntax.Tree jeffwhee...@gmail.com**20100325075221 Ignore-this: a106e842ae56b004edab83cf7dea5f0f ] [Cleanup Yi.Syntax.Tree (replace local function with Control.Arrow's `first`) jeffwhee...@gmail.com**20100325063218 Ignore-this: 1819a1e305d5d52b0fef28b048141dfb ] [Fix documentation formatting (remove broken linkification) jeffwhee...@gmail.com**20100325063013 Ignore-this: 7bcc3f61408f4c6df696f76445aaeee3 ] [-Wall (RecursiveDo -> DoRec, requires 6.12) jeffwhee...@gmail.com**20100325053035 Ignore-this: 36c0c99feadf155016ce86219f5f5580 ] [Display errors in configuration in both cold boot and reload jeffwhee...@gmail.com**20100325031845 Ignore-this: 11b26dd4e1ab79736610723afe8b2cb0 ] [TAG 0.6.2.2 jeffwhee...@gmail.com**20100324171312 Ignore-this: 729a069566b7090ea9de3d2a9038f4c7 ] Patch bundle hash: d07a10cdc3dd17ba973954e39115ddbdabbe7242