packages feed

cairo-appbase 0.2 → 0.3

raw patch · 2 files changed

+124/−49 lines, 2 filesdep ~base

Dependency ranges changed: base

Files

cairo-appbase.cabal view
@@ -1,28 +1,87 @@-Cabal-Version:   >= 1.6-Name:            cairo-appbase-Version:         0.2-Synopsis:        Template code for an app using GTK, Glade and Cairo graphics-Description:     This is a template for building new GUI applications. The-                 GTK widget layout is done via a Glade XML file which can be-                 edited visually using glade.+Name:                cairo-appbase -                 This template includes working callbacks to handle the File-                 and Help menus and File Save/Open dialogs, with dummy-                 handlers for selecting filenames and the Edit menu's-                 cut/copy/paste.+Version:             0.3 -                 The main canvas for this application uses Cairo for-                 graphics rendering, and includes example code from the-                 cairo package.-License:         BSD3-License-file:    LICENSE-Author:          Conrad Parker, Johan Bockgård-Maintainer:      conrad@metadecks.org-Category:        GUI-Build-Depends:   base < 5, glib, gtk, glade, cairo-Build-Type:      Simple-Data-Files:      data/main.glade+Synopsis:            A template for building new GUI applications using GTK, Glade and Cairo. -Executable:      cairo-appbase-Main-Is:         cairo-appbase.hs-Hs-Source-Dirs:  src+Description:+    This template includes working callbacks to handle the File and Help+    menus and File Save/Open dialogs, with dummy handlers for selecting+    filenames and the Edit menu's Cut, Copy, and Paste. The main canvas uses+    Cairo for graphics rendering, and includes example code from the cairo+    package.+    .+    To build your own application on top of this, first grab the code. You+    can either grab it from hackage with @cabal unpack cairo-appbase@, or+    clone the git repo:+    .+    >   git clone git://github.com/kfish/cairo-appbase.git+    .+    To add widgets, install glade from your distro system and run+    @glade data/main.glade@+    .+    Note that you must run @cabal install@ to put the glade file in the correct+    place for your application to pick it up. To modify the code, edit+    @src/cairo-appbase.hs@. Hooking up functions to widgets is very simple: get+    a widget by name (which you set in glade file), and hook one of its+    signals (which you found in the Signals tab in glade) to an @IO ()@ action:+    .+    > cut1 <- get G.castToMenuItem "cut1"+    > G.onActivateLeaf cut1 $ myCut+    .+    The template code includes a trivial definition of myCut:+    .+    > myCut :: IO ()+    > myCut = putStrLn "Cut"+    .+    A real application will want to pass data to the callback. In C, this is+    fairly tedious as you only have a single void * to pass to callbacks as+    @user_data@, and applications typically do lots of marshalling and+    unmarshalling to pass data around. In Haskell however, you can make+    yourself a more complex callback handler and use a curried version of it+    in each instance:+    .+    > cut1 <- get G.castToMenuItem "cut1"+    > G.onActivateLeaf cut1 $ myComplexCut project phase 7+    >+    > ...+    >+    > myCut :: Project -> MoonPhase -> LuckyNumber -> IO ()+    > myCut project phase num = do+    >     let selection = currentSelection project+    >     when (phase == Full) howl+    >     when (num /= 7) fail+    >     doActualCut selection+    .++License:             BSD3+License-file:        LICENSE+Author:              Conrad Parker, Johan Bockgård+Maintainer:          conrad@metadecks.org+Category:            Development++Cabal-Version:       >= 1.8+Build-type:          Simple+Data-Files:          data/main.glade++flag splitBase+  description: Use the split-up base package.++Executable cairo-appbase+  if flag(splitBase)+    build-depends:+      base >= 3 && < 6+  else+    build-depends:+      base < 3++  Main-Is:             cairo-appbase.hs+  Hs-Source-Dirs:      src+  Build-Depends:       glib, gtk, glade, cairo++------------------------------------------------------------------------+-- Git repo+--+source-repository head+  type: git+  location: git://github.com/kfish/cairo-appbase.git
src/cairo-appbase.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS -Wall #-} -- -- Based on Gtk2Hs/demo/cairo/Drawing2.hs  -- Author: Johan Bockgård <bojohan@dd.chalmers.se>@@ -5,6 +6,7 @@ -- This code is in the public domain. -- +import Control.Monad (replicateM_) import qualified System.Glib.Types as GTypes import qualified Graphics.UI.Gtk as G import qualified Graphics.UI.Gtk.Glade as Glade@@ -18,8 +20,8 @@ windowHeight  = 500  -- Write image to file-writePng :: IO ()-writePng =+_writePng :: IO ()+_writePng =   C.withImageSurface C.FormatARGB32 width height $ \ result -> do       C.renderWith result $ example width height       C.surfaceWriteToPNG result "Draw.png"@@ -27,8 +29,9 @@         height = windowHeight  -- Display image in window+main :: IO () main = do-  G.initGUI+  _ <- G.initGUI    -- load up the glade file   filename <- My.getDataFileName "data/main.glade"@@ -44,37 +47,37 @@    -- set up File->New   new1 <- get G.castToMenuItem "new1"-  G.onActivateLeaf new1 $ myNew+  _ <- G.onActivateLeaf new1 $ myNew    -- set up the File->Open dialog   open1 <- get G.castToMenuItem "open1"   openDialog <- get G.castToFileChooserDialog "opendialog"-  G.onActivateLeaf open1 $ G.widgetShow openDialog-  G.onResponse openDialog $ myFileOpen openDialog+  _ <- G.onActivateLeaf open1 $ G.widgetShow openDialog+  _ <- G.onResponse openDialog $ myFileOpen openDialog    -- set up the File->Save_As dialog   save1 <- get G.castToMenuItem "save1"   save_as1 <- get G.castToMenuItem "save_as1"   saveDialog <- get G.castToFileChooserDialog "savedialog"-  G.onActivateLeaf save_as1 $ G.widgetShow saveDialog-  G.onActivateLeaf save1 $ G.widgetShow saveDialog-  G.onResponse saveDialog $ myFileSave saveDialog+  _ <- G.onActivateLeaf save_as1 $ G.widgetShow saveDialog+  _ <- G.onActivateLeaf save1 $ G.widgetShow saveDialog+  _ <- G.onResponse saveDialog $ myFileSave saveDialog    -- set up Edit menu   cut1 <- get G.castToMenuItem "cut1"-  G.onActivateLeaf cut1 $ myCut+  _ <- G.onActivateLeaf cut1 $ myCut   copy1 <- get G.castToMenuItem "copy1"-  G.onActivateLeaf copy1 $ myCopy+  _ <- G.onActivateLeaf copy1 $ myCopy   paste1 <- get G.castToMenuItem "paste1"-  G.onActivateLeaf paste1 $ myPaste+  _ <- G.onActivateLeaf paste1 $ myPaste   delete1 <- get G.castToMenuItem "delete1"-  G.onActivateLeaf delete1 $ myDelete+  _ <- G.onActivateLeaf delete1 $ myDelete    -- set up the Help->About dialog   about1 <- get G.castToMenuItem "about1"   aboutdialog1 <- get G.castToAboutDialog "aboutdialog1"-  G.onActivateLeaf about1 $ G.widgetShow aboutdialog1-  G.onResponse aboutdialog1 $ const $ G.widgetHide aboutdialog1+  _ <- G.onActivateLeaf about1 $ G.widgetShow aboutdialog1+  _ <- G.onResponse aboutdialog1 $ const $ G.widgetHide aboutdialog1    -- fix size   --   G.windowSetResizable window False@@ -82,12 +85,12 @@    -- quit on File->Quit menu selection   quit1 <- get G.castToMenuItem "quit1"-  G.onActivateLeaf quit1 $ G.widgetDestroy window-  G.onDestroy window G.mainQuit+  _ <- G.onActivateLeaf quit1 $ G.widgetDestroy window+  _ <- G.onDestroy window G.mainQuit    -- set up the canvas   canvas <- get G.castToDrawingArea "drawingarea1"-  G.onExpose canvas $ const (updateCanvas canvas)+  _ <- G.onExpose canvas $ const (updateCanvas canvas)   G.widgetShowAll window   G.mainGUI @@ -102,6 +105,7 @@     G.ResponseCancel -> putStrLn "Cancelled!"     G.ResponseDeleteEvent -> putStrLn "FileChooserDialog Deleted!"     G.ResponseClose -> putStrLn "Closed!"+    _ -> return ()   G.widgetHide fcdialog  myFileSave :: G.FileChooserDialog -> G.ResponseId -> IO ()@@ -121,8 +125,8 @@  updateCanvas :: G.DrawingArea -> IO Bool updateCanvas canvas = do-  win <- G.drawingAreaGetDrawWindow canvas-  (width, height) <- G.drawingAreaGetSize canvas+  win <- G.widgetGetDrawWindow canvas+  (width, height) <- G.widgetGetSize canvas   G.renderWithDrawable win $       example width height   return True@@ -132,24 +136,29 @@ foreach :: (Monad m) => [a] -> (a -> m b) -> m [b] foreach = flip mapM +keepState :: C.Render t -> C.Render () keepState render = do   C.save-  render+  _ <- render   C.restore +drawCircle :: Double -> Double -> Double -> C.Render () drawCircle x y r = do   C.arc x y r 0 (2 * pi)   fillStroke +drawRectangle :: Double -> Double -> Double -> Double -> C.Render () drawRectangle x y w h = do   C.rectangle x y w h   fillStroke +stroke :: C.Render () stroke =   keepState $ do   C.setSourceRGBA 0 0 0 0.7   C.stroke +fillStroke :: C.Render () fillStroke = do   C.fillPreserve   stroke@@ -158,11 +167,13 @@  -- Example +example :: Int -> Int -> C.Render () example width height = do   prologue width height   example1  -- Set up stuff+prologue :: Int -> Int -> C.Render () prologue wWidth wHeight = do   let width   = 10       height  = 10@@ -191,6 +202,7 @@   -- Grid and axes+grid :: Double -> Double -> Double -> Double -> C.Render () grid xmin xmax ymin ymax =   keepState $ do   C.setSourceRGBA 0 0 0 0.7@@ -204,20 +216,22 @@          C.lineTo x ymax          C.stroke +example1 :: C.Render () example1 = do   -- circles   drawCircle 0 0 1   drawCircle 2 2 3   -- a bunch of rectangles   keepState $-    foreach [1 .. 5] $ \ _ ->-        do drawRectangle 0 1 2 3-           C.rotate (pi/8)+    replicateM_ 5 $ do+        drawRectangle 0 1 2 3+        C.rotate (pi/8)   -- some cute stuff   thought   apple   snake +thought :: C.Render () thought =   keepState $ do   C.scale 0.04 0.04@@ -274,6 +288,7 @@         c 146 424 144 422 143 422         z +apple :: C.Render () apple =   keepState $ do   C.scale 0.05 0.05@@ -309,6 +324,7 @@         c 1153 249 1152 249 1151 249         z +snake :: C.Render () snake =   keepState $ do   C.scale 0.04 0.04