module PlotHo.PlotChart
( AxisScaling(..)
, displayChart
, chartGtkUpdateCanvas
) where
import Control.Lens ( (.~) )
import Data.Default.Class ( def )
import qualified Graphics.UI.Gtk as Gtk
import qualified Graphics.Rendering.Chart as Chart
import Graphics.Rendering.Chart.Backend.Cairo ( runBackend, defaultEnv )
import Graphics.Rendering.Cairo hiding (width, height)
import PlotHo.PlotTypes ( AxisScaling(..) )
chartGtkUpdateCanvas :: Chart.Renderable () -> Gtk.DrawingArea -> IO ()
chartGtkUpdateCanvas chart canvas = do
Gtk.threadsEnter
maybeWin <- Gtk.widgetGetWindow canvas
case maybeWin of
Nothing -> Gtk.threadsLeave >> return ()
Just win -> do
(width, height) <- Gtk.widgetGetSize canvas
regio <- Gtk.regionRectangle $ Gtk.Rectangle 0 0 width height
Gtk.threadsLeave
let sz = (fromIntegral width,fromIntegral height)
let render0 :: Render (Chart.PickFn ())
render0 = runBackend (defaultEnv Chart.bitmapAlignmentFns) (Chart.render chart sz)
withImageSurface FormatARGB32 width height $ \surface -> do
_ <- renderWith surface render0
let render1 = setSourceSurface surface 0 0 >> paint
Gtk.threadsEnter
Gtk.drawWindowBeginPaintRegion win regio
_ <- Gtk.renderWithDrawable win render1
Gtk.drawWindowEndPaint win
Gtk.threadsLeave
displayChart :: (Chart.PlotValue a, Show a, RealFloat a) =>
(AxisScaling, AxisScaling) -> (Maybe (a,a),Maybe (a,a)) ->
[(String, [[(a,a)]])] -> Chart.Renderable ()
displayChart (xScaling,yScaling) (xRange,yRange) namePcs = Chart.toRenderable layout
where
drawOne (name,pc) col
= Chart.plot_lines_values .~ pc
$ Chart.plot_lines_style . Chart.line_color .~ col
$ Chart.plot_lines_title .~ name
$ def
allLines = zipWith drawOne namePcs Chart.defaultColorSeq
xscaleFun = case xScaling of
LogScaling -> Chart.layout_x_axis . Chart.laxis_generate .~ Chart.autoScaledLogAxis def
LinearScaling -> case xRange of
Nothing -> id
Just range -> Chart.layout_x_axis . Chart.laxis_generate .~ Chart.scaledAxis def range
yscaleFun = case yScaling of
LogScaling -> Chart.layout_y_axis . Chart.laxis_generate .~ Chart.autoScaledLogAxis def
LinearScaling -> case yRange of
Nothing -> id
Just range -> Chart.layout_y_axis . Chart.laxis_generate .~ Chart.scaledAxis def range
layout = Chart.layout_plots .~ map Chart.toPlot allLines
$ Chart.layout_x_axis . Chart.laxis_title .~ "time [s]"
$ xscaleFun
$ yscaleFun
def