leksah-0.16.2.2: src/IDE/Pane/Breakpoints.hs
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE OverloadedStrings #-}
-----------------------------------------------------------------------------
--
-- Module : IDE.Pane.Breakpoints
-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie
-- License : GPL
--
-- Maintainer : maintainer@leksah.org
-- Stability : provisional
-- Portability :
--
-- | A pane to display the set breakpoints
--
-----------------------------------------------------------------------------
module IDE.Pane.Breakpoints (
IDEBreakpoints
, BreakpointsState
, showBreakpoints
, fillBreakpointList
, selectBreak
) where
import Prelude ()
import Prelude.Compat
import Data.Typeable (Typeable(..))
import IDE.Core.State
import IDE.Debug
(debugShowBreakpoints,
debugDeleteBreakpoint,
debugDeleteAllBreakpoints)
import IDE.LogRef (showSourceSpan)
import Data.List (elemIndex)
import Control.Monad.IO.Class (MonadIO(..))
import IDE.Utils.GUIUtils (treeViewContextMenu, __)
import qualified Data.Text as T (words, unpack)
import qualified Data.Foldable as F (toList)
import qualified Data.Sequence as Seq (elemIndexL)
import GI.Gtk.Objects.ScrolledWindow
(scrolledWindowSetPolicy, scrolledWindowSetShadowType,
scrolledWindowNew, ScrolledWindow(..))
import GI.Gtk.Objects.TreeView
(onTreeViewRowActivated, treeViewGetSelection,
treeViewSetHeadersVisible, treeViewAppendColumn, treeViewSetModel,
treeViewNew, TreeView(..))
import Data.GI.Gtk.ModelView.ForestStore
(forestStoreGetValue, ForestStore(..),
forestStoreInsert, forestStoreClear, forestStoreNew)
import GI.Gtk.Objects.Widget (afterWidgetFocusInEvent, toWidget)
import GI.Gtk.Objects.CellRendererText
(setCellRendererTextText, cellRendererTextNew)
import GI.Gtk.Objects.TreeViewColumn
(TreeViewColumn(..), treeViewColumnSetReorderable,
treeViewColumnSetResizable, treeViewColumnSetSizing,
treeViewColumnSetTitle, treeViewColumnNew)
import GI.Gtk.Enums
(PolicyType(..), ShadowType(..), SelectionMode(..),
TreeViewColumnSizing(..))
import GI.Gtk.Interfaces.CellLayout (cellLayoutPackStart)
import Data.GI.Gtk.ModelView.CellLayout
(cellLayoutSetDataFunction)
import GI.Gtk.Objects.TreeSelection
(treeSelectionSelectPath, treeSelectionUnselectAll,
treeSelectionSetMode)
import GI.Gtk.Objects.Adjustment (noAdjustment)
import GI.Gtk.Objects.Container (containerAdd)
import GI.Gtk.Objects.Menu (Menu(..))
import GI.Gtk.Objects.SeparatorMenuItem (separatorMenuItemNew, SeparatorMenuItem(..))
import GI.Gtk.Objects.MenuShell (menuShellAppend)
import GI.Gtk.Structs.TreePath
(TreePath(..))
import Control.Monad.Reader (MonadReader(..))
import GI.Gtk.Objects.MenuItem
(toMenuItem, onMenuItemActivate, menuItemNewWithLabel)
import Data.GI.Gtk.ModelView.Types
(treeSelectionGetSelectedRows', treePathNewFromIndices')
-- | Represents the Breakpoints pane
data IDEBreakpoints = IDEBreakpoints {
scrolledView :: ScrolledWindow
, treeView :: TreeView
, breakpoints :: ForestStore LogRef
} deriving Typeable
-- | The additional state used when recovering the pane
data BreakpointsState = BreakpointsState
deriving(Eq,Ord,Read,Show,Typeable)
instance Pane IDEBreakpoints IDEM
where
primPaneName _ = __ "Breakpoints"
getAddedIndex _ = 0
getTopWidget = liftIO . toWidget . scrolledView
paneId b = "*Breakpoints"
instance RecoverablePane IDEBreakpoints BreakpointsState IDEM where
saveState p = return (Just BreakpointsState)
recoverState pp BreakpointsState = do
nb <- getNotebook pp
buildPane pp nb builder
builder pp nb windows = do
ideR <- ask
breakpoints <- forestStoreNew []
treeView <- treeViewNew
treeViewSetModel treeView (Just breakpoints)
rendererA <- cellRendererTextNew
colA <- treeViewColumnNew
treeViewColumnSetTitle colA (__ "Location")
treeViewColumnSetSizing colA TreeViewColumnSizingAutosize
treeViewColumnSetResizable colA True
treeViewColumnSetReorderable colA True
treeViewAppendColumn treeView colA
cellLayoutPackStart colA rendererA False
cellLayoutSetDataFunction colA rendererA breakpoints
$ \row -> setCellRendererTextText rendererA $ showSourceSpan row
rendererB <- cellRendererTextNew
colB <- treeViewColumnNew
treeViewColumnSetTitle colB (__ "Breakpoints")
treeViewColumnSetSizing colB TreeViewColumnSizingAutosize
treeViewColumnSetResizable colB True
treeViewColumnSetReorderable colB True
treeViewAppendColumn treeView colB
cellLayoutPackStart colB rendererB False
cellLayoutSetDataFunction colB rendererB breakpoints
$ setCellRendererTextText rendererB . refDescription
treeViewSetHeadersVisible treeView True
selB <- treeViewGetSelection treeView
treeSelectionSetMode selB SelectionModeSingle
scrolledView <- scrolledWindowNew noAdjustment noAdjustment
scrolledWindowSetShadowType scrolledView ShadowTypeIn
containerAdd scrolledView treeView
scrolledWindowSetPolicy scrolledView PolicyTypeAutomatic PolicyTypeAutomatic
let pane = IDEBreakpoints scrolledView treeView breakpoints
cid1 <- onIDE afterWidgetFocusInEvent treeView $ do
liftIDE $ makeActive pane
return True
cids2 <- treeViewContextMenu treeView $ breakpointsContextMenu ideR breakpoints treeView
cid4 <- ConnectC treeView <$> onTreeViewRowActivated treeView (breakpointsSelect ideR breakpoints)
return (Just pane, [cid1, cid4] ++ cids2)
-- | Get the Breakpoints pane
getBreakpoints :: IDEM IDEBreakpoints
getBreakpoints = forceGetPane (Right "*Breakpoints")
-- | Display the Breakpoints pane
showBreakpoints :: IDEAction
showBreakpoints = do
pane <- getBreakpoints
displayPane pane False
-- | Fill the pane with the breakpoint 'LogRef's from the IDE state
fillBreakpointList :: IDEAction
fillBreakpointList = do
mbBreakpoints <- getPane
case mbBreakpoints of
Nothing -> return ()
Just b -> do
refs <- readIDE breakpointRefs
forestStoreClear (breakpoints b)
emptyPath <- treePathNewFromIndices' []
mapM_ (\ (lr,index) -> forestStoreInsert (breakpoints b) emptyPath index lr)
(zip (F.toList refs) [0..])
-- | Try to get the currently selected breakpoint
getSelectedBreakpoint :: TreeView
-> ForestStore LogRef
-> IO (Maybe LogRef)
getSelectedBreakpoint treeView forestStore = do
treeSelection <- treeViewGetSelection treeView
paths <- treeSelectionGetSelectedRows' treeSelection
case paths of
a:r -> do
val <- forestStoreGetValue forestStore a
return (Just val)
_ -> return Nothing
-- | Select a specific 'LogRef' or none at all
selectBreak :: Maybe LogRef -- If @Nothing@, no breakpoints are selected
-> IDEAction
selectBreak mbLogRef = do
breakRefs' <- readIDE breakpointRefs
breaks <- forceGetPane (Right "*Breakpoints")
selection <- treeViewGetSelection (treeView breaks)
case mbLogRef of
Nothing -> treeSelectionUnselectAll selection
Just lr -> case lr `Seq.elemIndexL` breakRefs' of
Nothing -> return ()
Just ind -> treeSelectionSelectPath selection =<< treePathNewFromIndices' [fromIntegral ind]
-- | Constructs the context menu for the breakpoint
breakpointsContextMenu :: IDERef
-> ForestStore LogRef
-> TreeView
-> Menu
-> IO ()
breakpointsContextMenu ideR store treeView theMenu = do
item1 <- menuItemNewWithLabel (__ "Remove breakpoint")
onMenuItemActivate item1 $ do
sel <- getSelectedBreakpoint treeView store
case sel of
Just ref -> reflectIDE (deleteBreakpoint ref) ideR
otherwise -> sysMessage Normal (__ "Debugger>> breakpointViewPopup: no selection2")
sep1 <- separatorMenuItemNew >>= liftIO . toMenuItem
item2 <- menuItemNewWithLabel (__ "Remove all breakpoints")
onMenuItemActivate item2 $ reflectIDE debugDeleteAllBreakpoints ideR
item3 <- menuItemNewWithLabel (__ "Update")
onMenuItemActivate item3 $ reflectIDE debugShowBreakpoints ideR
mapM_ (menuShellAppend theMenu) [item1, sep1, item2, item3]
-- | Set the current breakpoint to a specific entry
-- pointed to by the supplied 'TreePath'
breakpointsSelect :: IDERef
-> ForestStore LogRef
-> TreePath
-> TreeViewColumn
-> IO ()
breakpointsSelect ideR store path _ = do
ref <- forestStoreGetValue store path
reflectIDE (setCurrentBreak (Just ref)) ideR
-- | Remove a breakpoint from the pane
deleteBreakpoint :: LogRef -> IDEAction
deleteBreakpoint logRef =
case logRefType logRef of
BreakpointRef -> debugDeleteBreakpoint (T.words (refDescription logRef) !! 1) logRef
_ -> sysMessage Normal (__ "Debugger>>deleteBreakpoint: Not a breakpoint")