------------------------------------------------------------------------------- |-- Module : Graphics.Rendering.Chart.Gtk-- Copyright : (c) Tim Docker 2006-- License : BSD-style (see chart/COPYRIGHT)moduleGraphics.Rendering.Chart.Gtk(renderableToWindow,createRenderableWindow,updateCanvas)whereimportqualifiedGraphics.UI.GtkasGimportqualifiedGraphics.UI.Gtk.Gdk.EventsasGEimportqualifiedGraphics.Rendering.CairoasCimportGraphics.Rendering.ChartimportGraphics.Rendering.Chart.RenderableimportGraphics.Rendering.Chart.TypesimportData.List(isPrefixOf)importData.IORefimportControl.Monad(when)importSystem.IO.Unsafe(unsafePerformIO)-- do action m for any keypress (except meta keys)anyKey::(Monadm)=>ma->GE.Event->mBoolanyKeym(GE.Key{GE.eventKeyName=key})|any(`isPrefixOf`key)ignores=returnTrue|otherwise=m>>returnTruewhereignores=["Shift","Control","Alt","Super","Meta","Hyper"]-- Yuck. But we really want the convenience function-- renderableToWindow as to be callable without requiring-- initGUI to be called first. But newer versions of-- gtk insist that initGUI is only called onceguiInitVar::IORefBool{-# NOINLINE guiInitVar #-}guiInitVar=unsafePerformIO(newIORefFalse)initGuiOnce::IO()initGuiOnce=dov<-readIORefguiInitVarwhen(notv)$do-- G.initGUIG.unsafeInitGUIForThreadedRTSwriteIORefguiInitVarTrue-- | Display a renderable in a gtk window.---- Note that this is a convenience function that initialises GTK on-- it's first call, but not subsequent calls. Hence it's -- unlikely to be compatible with other code using gtk. In -- that case use createRenderableWindow.renderableToWindow::Renderablea->Int->Int->IO()renderableToWindowchartwindowWidthwindowHeight=doinitGuiOncewindow<-createRenderableWindowchartwindowWidthwindowHeight-- press any key to exit the loopG.onKeyPresswindow$anyKey(G.widgetDestroywindow)G.onDestroywindowG.mainQuitG.widgetShowAllwindowG.mainGUI-- | Create a new GTK window displaying a renderable.createRenderableWindow::Renderablea->Int->Int->IOG.WindowcreateRenderableWindowchartwindowWidthwindowHeight=dowindow<-G.windowNewcanvas<-G.drawingAreaNewG.widgetSetSizeRequestwindowwindowWidthwindowHeightG.onExposecanvas$const(updateCanvaschartcanvas)G.setwindow[G.containerChildG.:=canvas]returnwindowupdateCanvas::Renderablea->G.DrawingArea->IOBoolupdateCanvaschartcanvas=dowin<-G.widgetGetDrawWindowcanvas(width,height)<-G.widgetGetSizecanvasletsz=(fromIntegralwidth,fromIntegralheight)G.renderWithDrawablewin$runCRender(renderchartsz)bitmapEnvreturnTrue