ghcprofview-0.1.0.1: src/Gui/TreeWidget.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MonoLocalBinds #-}
module Gui.TreeWidget where
import Control.Monad
import qualified Data.Text as T
import Data.Int
import Data.GI.Base.GType
import Data.GI.Base.GValue
import Data.GI.Base.Signals
import GI.Gtk
import Types
data ColumnType =
TextColumn
| PercentColumn
deriving (Eq, Show)
data Column a = Column {
columnTitle :: T.Text
, columnGType :: GType
, columnType :: ColumnType
, columnData :: a -> IO GValue
}
newtype TreeWidgetConfig a = TreeWidgetConfig {
twcColumns :: [Column a]
}
mkTreeStore :: forall a t . IsTree t a => TreeWidgetConfig a -> t -> IO TreeStore
mkTreeStore cfg tree = do
let columns = twcColumns cfg
let gtypes = map columnGType columns
store <- treeStoreNew gtypes
fill store Nothing tree
return store
where
fill :: TreeStore -> Maybe TreeIter -> t -> IO ()
fill store root node = do
let cc = treeRoot node
item <- treeStoreInsert store root (negate 1)
forM_ (zip [0..] (twcColumns cfg)) $ \(i, column) ->
treeStoreSetValue store item i =<< columnData column cc
forM_ (treeChildren node) $ fill store (Just item)
mkTreeView :: forall t a . IsTree t a => TreeWidgetConfig a -> t -> IO TreeView
mkTreeView cfg@(TreeWidgetConfig columns) tree = do
srcStore <- mkTreeStore cfg tree
store <- treeModelSortNewWithModel srcStore
view <- treeViewNewWithModel store
treeViewSetHeadersVisible view True
forM_ (zip [0..] columns) $ \(i, column) ->
addColumn view i (columnType column) (columnTitle column)
return view
where
addColumn :: TreeView
-> Int32
-> ColumnType
-> T.Text
-> IO SignalHandlerId
addColumn view i ctype title = do
column <- treeViewColumnNew
treeViewColumnSetTitle column title
withRenderer ctype $ \renderer -> do
treeViewColumnPackStart column renderer True
let propName = getPropName ctype
treeViewColumnAddAttribute column renderer propName i
set column [ #resizable := True ]
treeViewColumnSetSizing column TreeViewColumnSizingFixed
treeViewColumnSetSortColumnId column i
treeViewAppendColumn view column
button <- treeViewColumnGetButton column
on button #buttonPressEvent $ \ev -> do
button <- get ev #button
if button == 3
then do
menu <- mkColumnsMenu view
menuPopupAtPointer menu Nothing
return True
else return False
withRenderer :: forall x. ColumnType -> (forall r. IsCellRenderer r => r -> IO Int32) -> IO Int32
withRenderer TextColumn f = cellRendererTextNew >>= f
withRenderer PercentColumn f = cellRendererProgressNew >>= f
getPropName TextColumn = "text"
getPropName PercentColumn = "value"
mkColumnsMenu :: TreeView -> IO Menu
mkColumnsMenu tree = do
menu <- menuNew
columns <- treeViewGetColumns tree
forM_ (zip [0..] columns) $ \(i, column) -> do
title <- treeViewColumnGetTitle column
item <- checkMenuItemNewWithLabel title
menuShellAppend menu item
widgetShow item
visible <- treeViewColumnGetVisible column
checkMenuItemSetActive item visible
on item #activate $ do
treeViewColumnSetVisible column (not visible)
return menu