module VCSGui.Common.GtkHelper (
openGladeFile
, getWindowFromGlade
, getActionFromGlade
, getLabelFromGlade
, getTextEntryFromGlade
, getTextViewFromGlade
, getComboBoxFromGlade
, getCheckButtonFromGlade
, getButtonFromGlade
, getTreeViewFromGlade
, getTreeViewFromGladeCustomStore
, addColumnToTreeView
, addColumnToTreeView'
, addTextColumnToTreeView
, addTextColumnToTreeView'
, getName
, getItem
, get
, set
, closeWin
, registerClose
, registerCloseAction
, registerQuit
, registerQuitAction
, WindowItem
, ActionItem
, LabelItem
, TextEntryItem
, TextViewItem
, ComboBoxItem
, CheckButtonItem
, TreeViewItem
, ButtonItem
) where
import qualified Graphics.UI.Gtk as Gtk
import System.Directory
import Control.Monad.Trans(liftIO)
import System.IO (hPutStrLn, stderr)
import VCSGui.Common.Helpers (emptyListToNothing)
type WindowItem = (String, Gtk.Window, ())
type ActionItem = (String, Gtk.Action, ())
type LabelItem = (String, Gtk.Label, (IO (Maybe String), String -> IO ()))
type TextEntryItem = (String, Gtk.Entry, (IO (Maybe String), String -> IO ()))
type ComboBoxItem = (String, Gtk.ComboBox, (IO (Maybe String), [String] -> IO ()))
type TextViewItem = (String, Gtk.TextView, (IO (Maybe String), String -> IO ()))
type TreeViewItem a = (String, (Gtk.ListStore a, Gtk.TreeView), (IO (Maybe [a]), [a] -> IO ()))
type CheckButtonItem = (String, Gtk.CheckButton, (IO Bool, Bool -> IO()))
type ButtonItem = (String, Gtk.Button, (IO String, String -> IO()))
getName :: (String, a, b) -> String
getName (n, _, _) = n
getItem :: (String, a, b) -> a
getItem (_, item, _) = item
get :: (String, a, (b, c)) -> b
get (_, _, (getter, _)) = getter
set :: (String, a, (b, c)) -> c
set (_,_, (_, setter)) = setter
openGladeFile :: FilePath
-> IO Gtk.Builder
openGladeFile fn = do
builder <- Gtk.builderNew
Gtk.builderAddFromFile builder fn
return builder
getWindowFromGlade :: Gtk.Builder
-> String
-> IO WindowItem
getWindowFromGlade builder name = do
(a, b) <- wrapWidget builder Gtk.castToWindow name
return (a, b, ())
getActionFromGlade :: Gtk.Builder
-> String
-> IO ActionItem
getActionFromGlade builder name = do
(a, b) <- wrapWidget builder Gtk.castToAction name
return (a, b, ())
getLabelFromGlade :: Gtk.Builder
-> String
-> IO LabelItem
getLabelFromGlade builder name = do
(_, entry) <- wrapWidget builder Gtk.castToLabel name
let getter = error "don't call get on a gtk label!" :: IO (Maybe String)
setter val = Gtk.labelSetText entry val :: IO ()
return (name, entry, (getter, setter))
getButtonFromGlade :: Gtk.Builder
-> String
-> IO ButtonItem
getButtonFromGlade builder name = do
(_,btn) <- wrapWidget builder Gtk.castToButton name
let getter = Gtk.buttonGetLabel btn :: IO String
setter val = Gtk.buttonSetLabel btn val
return (name, btn, (getter,setter))
getTextEntryFromGlade :: Gtk.Builder
-> String
-> IO TextEntryItem
getTextEntryFromGlade builder name = do
(_, entry) <- wrapWidget builder Gtk.castToEntry name
let getter = fmap emptyListToNothing $ Gtk.entryGetText entry :: IO (Maybe String)
setter val = Gtk.entrySetText entry val :: IO ()
return (name, entry, (getter, setter))
getComboBoxFromGlade :: Gtk.Builder
-> String
-> IO ComboBoxItem
getComboBoxFromGlade builder name = do
(_, combo) <- wrapWidget builder Gtk.castToComboBox name
Gtk.comboBoxSetModelText combo
let getter = Gtk.comboBoxGetActiveText combo :: IO (Maybe String)
setter entries = do
store <- Gtk.comboBoxGetModelText combo
Gtk.listStoreClear store
mapM_ (Gtk.listStoreAppend store) entries
return ()
return (name, combo, (getter, setter))
getTextViewFromGlade :: Gtk.Builder
-> String
-> IO TextViewItem
getTextViewFromGlade builder name = do
(_, entry) <- wrapWidget builder Gtk.castToTextView name
buffer <- Gtk.textViewGetBuffer entry
let getter = getLongText buffer :: IO (Maybe String)
setter = (\text -> Gtk.textBufferSetText buffer text) :: String -> IO ()
return (name, entry, (getter, setter))
where
getLongText buffer = do
start <- Gtk.textBufferGetStartIter buffer
end <- Gtk.textBufferGetEndIter buffer
isEmpty <- (Gtk.textIterEqual start end)
if isEmpty then return Nothing else do
s <- Gtk.textBufferGetText buffer start end True
return $ Just s
getCheckButtonFromGlade :: Gtk.Builder
-> String
-> IO CheckButtonItem
getCheckButtonFromGlade builder name = do
(_,bt) <- wrapWidget builder Gtk.castToCheckButton name
let getter = Gtk.toggleButtonGetActive bt
setter = (\bool -> Gtk.toggleButtonSetActive bt bool) :: Bool -> IO()
return (name,bt, (getter,setter))
getTreeViewFromGlade :: Gtk.Builder
-> String
-> [a]
-> IO (TreeViewItem a)
getTreeViewFromGlade builder name rows = do
(_, tView) <- wrapWidget builder Gtk.castToTreeView name
entry@(store, treeView) <- createStoreForTreeView tView rows
let getter = getFromListStore entry
setter = setToListStore entry
return (name, (store, treeView), (getter, setter))
getTreeViewFromGladeCustomStore :: Gtk.Builder
-> String
-> (Gtk.TreeView -> IO (Gtk.ListStore a))
-> IO (TreeViewItem a)
getTreeViewFromGladeCustomStore builder name setupListStore = do
(_, tView) <- wrapWidget builder Gtk.castToTreeView name
store <- setupListStore tView
Gtk.treeViewSetModel tView store
let getter = getFromListStore (store, tView)
setter = setToListStore (store, tView)
return (name, (store, tView), (getter, setter))
createStoreForTreeView :: Gtk.TreeView
-> [a]
-> IO (Gtk.ListStore a, Gtk.TreeView)
createStoreForTreeView listView rows = do
listStore <- Gtk.listStoreNew rows
Gtk.treeViewSetModel listView listStore
return (listStore, listView)
getFromListStore :: (Gtk.ListStore a, Gtk.TreeView)
-> IO (Maybe [a])
getFromListStore (store, _) = do
list <- Gtk.listStoreToList store
if null list
then return Nothing
else return $ Just list
setToListStore :: (Gtk.ListStore a, Gtk.TreeView)
-> [a]
-> IO ()
setToListStore (store, view) newList = do
Gtk.listStoreClear store
mapM_ (Gtk.listStoreAppend store) newList
return ()
closeWin :: WindowItem -> IO ()
closeWin win = (Gtk.widgetHide (getItem win))
registerClose :: WindowItem -> IO ()
registerClose win = Gtk.on (getItem win) Gtk.deleteEvent (liftIO (closeWin win) >> return False) >> return ()
registerCloseAction :: ActionItem -> WindowItem -> IO ()
registerCloseAction act win = Gtk.on (getItem act) Gtk.actionActivated (liftIO (closeWin win)) >> return ()
registerQuit :: WindowItem -> IO ()
registerQuit win = Gtk.on (getItem win) Gtk.deleteEvent (liftIO $ Gtk.mainQuit >> return False) >> return ()
registerQuitAction :: ActionItem -> IO ()
registerQuitAction act = Gtk.on (getItem act) Gtk.actionActivated (liftIO (Gtk.mainQuit)) >> return ()
registerQuitWithCustomFun :: WindowItem
-> IO ()
-> IO ()
registerQuitWithCustomFun win fun = Gtk.on (getItem win) Gtk.deleteEvent (liftIO $ Gtk.mainQuit >> return False) >> return ()
addColumnToTreeView :: Gtk.CellRendererClass r =>
TreeViewItem a
-> r
-> String
-> (a -> [Gtk.AttrOp r])
-> IO ()
addColumnToTreeView (_, item, _) = do
addColumnToTreeView' item
addColumnToTreeView' :: Gtk.CellRendererClass r =>
(Gtk.ListStore a, Gtk.TreeView)
-> r
-> String
-> (a -> [Gtk.AttrOp r])
-> IO ()
addColumnToTreeView' (listStore, listView) renderer title value2attributes = do
newCol <- Gtk.treeViewColumnNew
Gtk.set newCol [Gtk.treeViewColumnTitle Gtk.:= title]
Gtk.treeViewAppendColumn listView newCol
Gtk.treeViewColumnPackStart newCol renderer True
Gtk.cellLayoutSetAttributes newCol renderer listStore value2attributes
addTextColumnToTreeView :: TreeViewItem a
-> String
-> (a -> [Gtk.AttrOp Gtk.CellRendererText])
-> IO ()
addTextColumnToTreeView tree title map = do
r <- Gtk.cellRendererTextNew
addColumnToTreeView tree r title map
addTextColumnToTreeView' :: (Gtk.ListStore a, Gtk.TreeView)
-> String
-> (a -> [Gtk.AttrOp Gtk.CellRendererText])
-> IO ()
addTextColumnToTreeView' item title map = do
r <- Gtk.cellRendererTextNew
addColumnToTreeView' item r title map
wrapWidget :: Gtk.GObjectClass objClass =>
Gtk.Builder
-> (Gtk.GObject -> objClass)
-> String -> IO (String, objClass)
wrapWidget builder cast name = do
hPutStrLn stderr $ " cast " ++ name
gobj <- Gtk.builderGetObject builder cast name
return (name, gobj)