cga/Gtk.hs

204 lines
6.3 KiB
Haskell

module Gtk where
import Control.Monad.IO.Class
import Control.Monad
import Defaults
import Diagram
import Diagrams.Prelude
import Diagrams.Backend.Cairo
import Diagrams.Backend.Cairo.Internal
import Graphics.UI.Gtk
import Graphics.UI.Gtk.Glade
import System.Directory
import Util
gladeFile :: FilePath
gladeFile = "gtk2.glade"
-- |Handle the whole GTK gui.
makeGUI :: FilePath -> IO ()
makeGUI startFile = do
homedir <- getHomeDirectory
-- init gui
_ <- initGUI
-- load glade file
Just xml <- xmlNew gladeFile
window <- xmlGetWidget xml castToWindow "window1"
drawButton <- xmlGetWidget xml castToButton "drawButton"
saveButton <- xmlGetWidget xml castToButton "saveButton"
quitButton <- xmlGetWidget xml castToButton "quitButton"
fileButton <- xmlGetWidget xml castToFileChooserButton
"filechooserButton"
da <- xmlGetWidget xml castToDrawingArea "drawingarea"
hscale <- xmlGetWidget xml castToHScale "hscale"
xlDE <- xmlGetWidget xml castToEntry "xlD"
xlUE <- xmlGetWidget xml castToEntry "xlU"
ylDE <- xmlGetWidget xml castToEntry "ylD"
ylUE <- xmlGetWidget xml castToEntry "ylU"
-- adjust properties
if startFile == ""
then do
_ <- fileChooserSetCurrentFolder fileButton homedir
return ()
else do
_ <- fileChooserSetFilename fileButton startFile
return ()
-- callbacks
_ <- onDestroy window mainQuit
_ <- onClicked drawButton $ onClickedDrawButton fileButton
da hscale (xlDE, xlUE) (ylDE, ylUE)
_ <- onClicked saveButton $ onClickedSaveButton fileButton
hscale (xlDE, xlUE) (ylDE, ylUE)
_ <- onClicked quitButton mainQuit
-- hotkeys
_ <- window `on` keyPressEvent $ tryEvent $ do
[Control] <- eventModifier
"q" <- eventKeyName
liftIO mainQuit
_ <- window `on` keyPressEvent $ tryEvent $ do
[Control] <- eventModifier
"s" <- eventKeyName
liftIO $ onClickedSaveButton fileButton
hscale (xlDE, xlUE) (ylDE, ylUE)
_ <- window `on` keyPressEvent $ tryEvent $ do
[Control] <- eventModifier
"d" <- eventKeyName
liftIO $ onClickedDrawButton fileButton da hscale
(xlDE, xlUE) (ylDE, ylUE)
-- draw widgets and start main loop
widgetShowAll window
mainGUI
-- |Callback when the "Draw" Button is clicked.
onClickedDrawButton :: (WidgetClass widget, RangeClass scale)
=> FileChooserButton
-> widget
-> scale
-> (Entry, Entry)
-> (Entry, Entry)
-> IO ()
onClickedDrawButton fcb da scale' dXE dYE = do
filename <- fileChooserGetFilename fcb
case filename of
Just x -> do
cId <- onExpose da (\_ -> drawDiag' x da scale' dXE dYE)
_ <- on fcb fileActivated (signalDisconnect cId)
ret <- drawDiag' x da scale' dXE dYE
unless ret $ showErrorDialog "No valid Mesh file!"
Nothing -> showErrorDialog "No valid Mesh file!"
-- |Callback when the "Save" Button is clicked.
onClickedSaveButton :: RangeClass scale
=> FileChooserButton
-> scale
-> (Entry, Entry)
-> (Entry, Entry)
-> IO ()
onClickedSaveButton fcb scale' dXE dYE = do
filename <- fileChooserGetFilename fcb
case filename of
Just x -> do
ret <- saveDiag' x scale' dXE dYE
unless ret $ showErrorDialog "No valid Mesh file!"
Nothing -> showErrorDialog "No valid Mesh file!"
-- |Pops up an error Dialog with the given String.
showErrorDialog :: String -> IO ()
showErrorDialog str = do
errorDialog <- messageDialogNew Nothing
[DialogDestroyWithParent]
MessageError
ButtonsClose
str
_ <- dialogRun errorDialog
widgetDestroy errorDialog
-- |Draws a Diagram which is built from a given file to
-- the gtk DrawingArea.
drawDiag' :: (WidgetClass widget, RangeClass scale)
=> FilePath
-> widget
-> scale
-> (Entry, Entry)
-> (Entry, Entry)
-> IO Bool
drawDiag' fp da scale' dXE dYE =
if cmpExt "obj" fp
then do
mesh <- readFile fp
dw <- widgetGetDrawWindow da
adjustment <- rangeGetAdjustment scale'
scaleVal <- adjustmentGetValue adjustment
xlD <- entryGetText $ fst dXE
xlU <- entryGetText $ snd dXE
ylD <- entryGetText $ fst dYE
ylU <- entryGetText $ snd dYE
-- clear drawing area
clearDiag da
let xD = (read xlD, read xlU) :: (Double, Double)
yD = (read ylD, read ylU) :: (Double, Double)
(_, r) = renderDia Cairo
(CairoOptions "" (Width 600) SVG False)
(diagFromString (def{t = scaleVal,
dX = xD,
dY = yD})
mesh)
renderWithDrawable dw r
return True
else return False
-- |Saves a Diagram which is built from a given file as an SVG.
saveDiag' :: RangeClass scale
=> FilePath
-> scale
-> (Entry, Entry)
-> (Entry, Entry)
-> IO Bool
saveDiag' fp scale' dXE dYE =
if cmpExt "obj" fp
then do
mesh <- readFile fp
adjustment <- rangeGetAdjustment scale'
scaleVal <- adjustmentGetValue adjustment
xlD <- entryGetText $ fst dXE
xlU <- entryGetText $ snd dXE
ylD <- entryGetText $ fst dYE
ylU <- entryGetText $ snd dYE
let xD = (read xlD, read xlU) :: (Double, Double)
yD = (read ylD, read ylU) :: (Double, Double)
renderCairo "out.svg" (Width 600)
(diagFromString (def{t = scaleVal,
dX = xD,
dY = yD})
mesh)
return True
else return False
-- |Clears the drawing area by painting a white rectangle.
clearDiag :: WidgetClass widget
=> widget
-> IO ()
clearDiag da = do
dw <- widgetGetDrawWindow da
let (_, r) = renderDia Cairo
(CairoOptions "" (Width 600) SVG False)
(emptyRect 600 600)
renderWithDrawable dw r