Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use the diagrams library with GTK drawables?

I'm trying to learn how to draw diagrams using the diagrams library and the Cairo / GTK backend. I've got a blank window to appear, but my drawing won't render. What am I doing wrong?

module Main where

import Control.Monad.Trans (liftIO)
import Graphics.UI.Gtk
import Diagrams.Backend.Cairo
import Diagrams.Backend.Cairo.Gtk
import Diagrams.Prelude

main :: IO ()
main = do
  initGUI
  window <- windowNew
  canvas <- drawingAreaNew
  canvas `on` sizeRequest $ return (Requisition 1000 1000)
  set window [ containerBorderWidth := 10,
               containerChild := canvas ]
  canvas `on` exposeEvent $ renderFigure
  onDestroy window mainQuit
  widgetShowAll window
  mainGUI


renderFigure :: EventM EExpose Bool
renderFigure = do
   win <- eventWindow
   liftIO $ renderToGtk win $ toGtkCoords figure
   -- liftIO $ defaultRender win figure
   return True


figure :: Diagram Cairo R2
figure =  unitCircle # scaleX 0.5 # rotateBy (1/6) # scale 50

I've tried using "defaultRender" (as commented out above), but that gives a type error: apparently "win" is not the right type.

I've read the tutorial and user manual for diagram, but it doesn't actually tell you how to use the Cairo backend.

Update: I've got the ellipse to render. The "renderFigure" function now says:

renderFigure :: DrawingArea -> EventM EExpose Bool
renderFigure canvas = do
   -- win <- eventWindow
   liftIO $ do
      -- diagramArea <- widgetGetDrawWindow canvas 
      -- renderToGtk diagramArea $ toGtkCoords figure
      defaultRender canvas figure
   return True

and the DrawingArea passed in is the "canvas" referenced in the "canvas on exposeEvent..." setting.

But I still can't get it to render a fixed size diagram using "renderToGtk".

Update 2: Thanks to Joachim Breitner's answer, I've now got the minimal diagram-on-GTK program looking like this, ready for your cut-and-paste pleasure.

module Main where

import Control.Monad.Trans (liftIO)
import Graphics.UI.Gtk
import Diagrams.Backend.Cairo
import Diagrams.Backend.Cairo.Gtk
import Diagrams.Prelude

main :: IO ()
main = do
  initGUI
  window <- windowNew
  canvas <- drawingAreaNew
  canvas `on` sizeRequest $ return (Requisition 256 256)
  set window [ containerBorderWidth := 10,
               containerChild := canvas ]
  canvas `on` exposeEvent $ renderFigure
  onDestroy window mainQuit
  widgetShowAll window
  mainGUI


renderFigure :: EventM EExpose Bool
renderFigure = do
   win <- eventWindow
   liftIO $ renderToGtk win $ toGtkCoords figure
   return True


figure :: Diagram Cairo R2
figure =  unitCircle # scaleX 0.5 # rotateBy (1/6) # scale 50 # fc red  
like image 453
Paul Johnson Avatar asked Aug 09 '12 14:08

Paul Johnson


2 Answers

Your initial code actually works. But renderToGtk does not scale the image, so it appears rather small, too small to be visible at that line width. But try

figure :: Diagram Cairo R2
figure =  unitCircle # scaleX 0.5 # rotateBy (1/6) # scale 50 # fc red

and it will work like a charm!

like image 149
Joachim Breitner Avatar answered Oct 12 '22 23:10

Joachim Breitner


You can note that in recent versions of diagrams, you should use

import Diagrams.Backend.Gtk

instead of

import Diagrams.Backend.Cairo.Gtk

and

figure :: Diagram Cairo

instead of

figure :: Diagram Cairo R2

The result now looks like :

module Main where

import Control.Monad.Trans (liftIO)
import Graphics.UI.Gtk
import Diagrams.Backend.Cairo
import Diagrams.Backend.Gtk
import Diagrams.Prelude

main :: IO ()
main = do
  initGUI
  window <- windowNew
  canvas <- drawingAreaNew
  canvas `on` sizeRequest $ return (Requisition 256 256)
  Graphics.UI.Gtk.set window [ containerBorderWidth := 10,
               containerChild := canvas ]
  canvas `on` exposeEvent $ renderFigure
  onDestroy window mainQuit
  widgetShowAll window
  mainGUI


renderFigure :: EventM EExpose Bool
renderFigure = do
   win <- eventWindow
   liftIO $ renderToGtk win $ toGtkCoords figure
   return True


figure :: Diagram Cairo
figure =  unitCircle # scaleX 0.5 # rotateBy (1/6) # scale 50 # fc red
like image 32
tobiasBora Avatar answered Oct 12 '22 22:10

tobiasBora