hbro-0.8.0.0: Hbro/Gui.hs
{-# LANGUAGE DoRec #-}
module Hbro.Gui (
initGUI,
showWebInspector,
prompt,
promptIncremental,
toggleVisibility
) where
-- {{{ Imports
import Hbro.Util
import Hbro.Types
import Control.Monad hiding(forM_, mapM_)
import Control.Monad.Trans
import Data.Foldable
import Graphics.Rendering.Pango.Enums
import Graphics.UI.Gtk.Abstract.Container
import Graphics.UI.Gtk.Abstract.Box
import Graphics.UI.Gtk.Abstract.Widget
import Graphics.UI.Gtk.Builder
import Graphics.UI.Gtk.Display.Label
import Graphics.UI.Gtk.Entry.Editable
import Graphics.UI.Gtk.Entry.Entry
import qualified Graphics.UI.Gtk.General.General as GTK
import Graphics.UI.Gtk.Gdk.EventM
import Graphics.UI.Gtk.Layout.HBox
import Graphics.UI.Gtk.Layout.VBox
import Graphics.UI.Gtk.Scrolling.ScrolledWindow
import Graphics.UI.Gtk.WebKit.WebInspector
import Graphics.UI.Gtk.WebKit.WebSettings
import Graphics.UI.Gtk.WebKit.WebView hiding(webViewLoadUri)
import Graphics.UI.Gtk.Windows.Window
import Prelude hiding(mapM_)
import System.Console.CmdArgs (whenNormal, whenLoud)
import System.Glib.Attributes
import System.Glib.Signals
-- }}}
initGUI :: FilePath -> [AttrOp WebSettings] -> IO GUI
initGUI xmlPath settings = do
whenNormal $ putStr ("Loading GUI from " ++ xmlPath ++ "... ")
void GTK.initGUI
-- Load XML
builder <- builderNew
builderAddFromFile builder xmlPath
-- Initialize components
(webView, sWindow) <- initWebView builder settings
(window, wBox) <- initWindow builder webView
promptBar <- initPromptBar builder
statusBar <- initStatusBar builder
inspectorWindow <- initWebInspector webView wBox
-- Show window
widgetShowAll window
widgetHide (mBox promptBar)
whenNormal $ putStrLn "Done."
return $ GUI {
mWindow = window,
mInspectorWindow = inspectorWindow,
mScrollWindow = sWindow,
mWebView = webView,
mPromptBar = promptBar,
mStatusBar = statusBar,
mBuilder = builder
}
initWebView :: Builder -> [AttrOp WebSettings] -> IO (WebView, ScrolledWindow)
initWebView builder settings = do
-- Initialize ScrolledWindows
window <- builderGetObject builder castToScrolledWindow "webViewParent"
scrolledWindowSetPolicy window PolicyNever PolicyNever
-- Initialize WebSettings
webSettings <- webSettingsNew
set webSettings settings
-- Initialize WebView
webView <- webViewNew
set webView [ widgetCanDefault := True ]
webViewSetWebSettings webView webSettings
containerAdd window webView
--
_ <- on webView closeWebView $ GTK.mainQuit >> return False
-- On new window request
_ <- on webView createWebView $ \frame -> do
webFrameGetUri frame >>= (mapM_ (\uri -> do
whenLoud $ putStrLn ("Requesting new window: " ++ show uri ++ "...")
webViewLoadUri webView uri))
return webView
return (webView, window)
initWindow :: Builder -> WebView -> IO (Window, VBox)
initWindow builder webView = do
window <- builderGetObject builder castToWindow "mainWindow"
windowSetDefault window $ Just webView
windowSetDefaultSize window 800 600
widgetModifyBg window StateNormal (Color 0 0 10000)
_ <- onDestroy window GTK.mainQuit
box <- builderGetObject builder castToVBox "windowBox"
return (window, box)
initPromptBar :: Builder -> IO PromptBar
initPromptBar builder = do
label <- builderGetObject builder castToLabel "promptDescription"
labelSetAttributes label [
AttrStyle {paStart = 0, paEnd = -1, paStyle = StyleItalic},
AttrWeight {paStart = 0, paEnd = -1, paWeight = WeightBold}
]
entry <- builderGetObject builder castToEntry "promptEntry"
box <- builderGetObject builder castToHBox "promptBox"
return $ PromptBar box label entry
initStatusBar :: Builder -> IO HBox
initStatusBar builder = builderGetObject builder castToHBox "statusBox"
-- {{{ Web inspector
initWebInspector :: WebView -> VBox -> IO (Window)
initWebInspector webView windowBox = do
inspector <- webViewGetInspector webView
inspectorWindow <- windowNew
set inspectorWindow [ windowTitle := "hbro | Web inspector" ]
_ <- on inspector inspectWebView $ \_ -> do
view <- webViewNew
containerAdd inspectorWindow view
return view
_ <- on inspector showWindow $ do
widgetShowAll inspectorWindow
return True
-- TODO: when does this signal happen ?!
--_ <- on inspector finished $ return ()
-- Attach inspector to browser's main window
_ <- on inspector attachWindow $ do
getWebView <- webInspectorGetWebView inspector
case getWebView of
Just view -> do
widgetHide inspectorWindow
containerRemove inspectorWindow view
widgetSetSizeRequest view (-1) 250
boxPackEnd windowBox view PackNatural 0
widgetShow view
return True
_ -> return False
-- Detach inspector in a distinct window
_ <- on inspector detachWindow $ do
getWebView <- webInspectorGetWebView inspector
_ <- case getWebView of
Just view -> do
containerRemove windowBox view
containerAdd inspectorWindow view
widgetShowAll inspectorWindow
return True
_ -> return False
widgetShowAll inspectorWindow
return True
return inspectorWindow
-- | Show web inspector for current webpage.
showWebInspector :: WebView -> IO ()
showWebInspector webView = do
inspector <- webViewGetInspector webView
webInspectorInspectCoordinates inspector 0 0
-- }}}
-- {{{ Prompt
openPrompt :: PromptBar -> String -> String -> IO ()
openPrompt _promptBar@PromptBar {mBox = promptBox, mDescription = description, mEntry = entry} newDescription defaultText = do
labelSetText description newDescription
entrySetText entry defaultText
widgetShow promptBox
widgetGrabFocus entry
editableSetPosition entry (-1)
-- | Open prompt bar with given description and default value,
-- and register a callback to trigger at validation.
prompt :: String -> String -> (String -> IO ()) -> GUI -> IO ()
prompt l d = prompt' l d False
-- | Same as 'prompt', but callback is triggered for each change in prompt's entry.
promptIncremental :: String -> String -> (String -> IO ()) -> GUI -> IO ()
promptIncremental l d = prompt' l d True
prompt' :: String -> String -> Bool -> (String -> IO ()) -> GUI -> IO ()
prompt' description defaultText incremental callback _gui@GUI {mPromptBar = promptBar, mWebView = webView} = do
openPrompt promptBar description defaultText
-- Register callback
case incremental of
True -> do
id1 <- on entry editableChanged $ entryGetText entry >>= callback
rec id2 <- on entry keyPressEvent $ do
key <- eventKeyName
case key of
"Return" -> liftIO $ do
widgetHide promptBox
signalDisconnect id1
signalDisconnect id2
widgetGrabFocus webView
"Escape" -> liftIO $ do
widgetHide promptBox
signalDisconnect id1
signalDisconnect id2
widgetGrabFocus webView
_ -> return ()
return False
return ()
_ -> do
rec id <- on entry keyPressEvent $ do
key <- eventKeyName
case key of
"Return" -> liftIO $ do
widgetHide promptBox
entryGetText entry >>= callback
signalDisconnect id
widgetGrabFocus webView
"Escape" -> liftIO $ do
widgetHide promptBox
signalDisconnect id
widgetGrabFocus webView
_ -> return ()
return False
return ()
where
promptBox = mBox promptBar
entry = mEntry promptBar
-- }}}
-- {{{ Util
-- | Toggle a widget's visibility (provided for convenience).
toggleVisibility :: WidgetClass a => a -> IO ()
toggleVisibility widget = do
visibility <- get widget widgetVisible
case visibility of
False -> widgetShow widget
_ -> widgetHide widget
-- }}}