packages feed

plot-lab-0.0.1.9: src/PlotLab/Events.hs

module PlotLab.Events (attachHandlers) where

import           PlotLab.FigureSettings

import           Data.Char               (toLower)
import           Data.Colour.Names
import           Data.IORef              (IORef, modifyIORef, readIORef)
import           Data.Maybe              (fromJust)
import           Data.Text               (unpack)
import           Data.Vector.Storable    (Vector)
import           Graphics.Rendering.Plot
import           Graphics.UI.Gtk         hiding (Circle, Color, Cross)
import           Numeric.LinearAlgebra   (linspace)

attachHandlers :: (Ordinate a, ComboBoxClass self) =>
                  Builder
                  -> IORef FigureSettings
                  -> [Adjustment]
                  -> (DrawingArea ->
                      IORef FigureSettings -> [Adjustment] -> IO ())
                  -> ([Double] -> a)
                  -> ((Vector Double, [FormattedSeries])
                      -> FigureSettings -> Figure ())
                  -> self
                  -> IO (ConnectId Button)
attachHandlers builder iofset adjs updateCanvas g buildFigure combo = do
  -- Canvas
  canvas <- builderGetObject builder castToDrawingArea "Plotting Canvas"
  let redraw = updateCanvas canvas iofset adjs
  _ <- onExpose canvas $ \_ -> redraw >> return False

  -- Adjustments for parameter sliders
  mapM_ (`onValueChanged` redraw) adjs

  -- Plot-Title Entry
  titleEntry <- builderGetObject builder castToEntry "Plot Title Entry"
  _ <- onEntryActivate titleEntry $ do
    titleNew <- entryGetText titleEntry
    modifyIORef iofset $ \f -> f { plotTitle = Just titleNew }
    redraw

  -- Plot-Title Font Size
  titleSize <- builderGetObject builder castToAdjustment "Title Font Size"
  _ <- onValueChanged titleSize $ do
    size <- adjustmentGetValue titleSize
    modifyIORef iofset $ \f -> f { plotTitleSize = size }
    redraw

  -- Subtitle Entry
  subEntry <- builderGetObject builder castToEntry "Subtitle Entry"
  _ <- onEntryActivate subEntry $ do
    titleNew <- entryGetText subEntry
    modifyIORef iofset $ \f -> f { subTitle = Just titleNew }
    redraw

  -- Subtitle Font Size
  subSize  <- builderGetObject builder castToAdjustment "Subtitle Font Size"
  _ <- onValueChanged subSize $ do
    size <- adjustmentGetValue subSize
    modifyIORef iofset $ \f -> f { subTitleSize = size }
    redraw

  -- Show X-Axis CheckButton
  showX <- builderGetObject builder castToCheckButton "X-Axis Check"
  _ <- onToggled showX $ do
    state <- toggleButtonGetActive showX
    modifyIORef iofset
      (\f -> f { showXAxis = state })
    redraw

  -- Show Y-Axis CheckButton
  showY <- builderGetObject builder castToCheckButton "Y-Axis Check"
  _ <- onToggled showY $ do
    state <- toggleButtonGetActive showY
    modifyIORef iofset
      (\f -> f { showYAxis = state })
    redraw

  let adjustmentPairValues (a1, a2) = do v1 <- adjustmentGetValue a1
                                         v2 <- adjustmentGetValue a2
                                         return (v1, v2)
  -- X-Axis Range
  xLower <- builderGetObject builder castToAdjustment "X-Lower"
  xUpper <- builderGetObject builder castToAdjustment "X-Upper"
  let updateX x = onValueChanged x $ do
        (xl, xu) <- adjustmentPairValues (xLower, xUpper)
        modifyIORef iofset $ \f -> f { xRange = Just (xl, xu) }
        redraw
    in mapM_ updateX [xLower, xUpper]

  -- X-Range Auto-determination CheckBox
  xRangeEntries <- builderGetObject builder castToHBox "X-Range Entries"
  autoXCheck <- builderGetObject builder castToCheckButton "X-Range Check"
  _ <- onToggled autoXCheck $ do
    state <- toggleButtonGetActive autoXCheck
    if state
      then error "Invalid xRange"
           -- do modifyIORef iofset $ \f -> f { xRange = Nothing }
           --    widgetHideAll xRangeEntries
      else do lower <- builderGetObject builder castToAdjustment "X-Lower"
              upper <- builderGetObject builder castToAdjustment "X-Upper"
              (l, u) <- adjustmentPairValues (lower, upper)
              widgetShowAll xRangeEntries
              modifyIORef iofset $ \f -> f { xRange = Just (l, u) }
    redraw

  -- Y-Axis Range
  yLower <- builderGetObject builder castToAdjustment "Y-Lower"
  yUpper <- builderGetObject builder castToAdjustment "Y-Upper"
  let updateY y = onValueChanged y $ do
        (yl, yu) <- adjustmentPairValues (yLower, yUpper)
        modifyIORef iofset $ \f -> f { yRange = Just (yl, yu) }
        redraw
    in mapM_ updateY [yLower, yUpper]

  -- Y-Range Auto-determination CheckBox
  yRangeEntries <- builderGetObject builder castToHBox "Y-Range Entries"
  autoYCheck <- builderGetObject builder castToCheckButton "Y-Range Check"
  _ <- onToggled autoYCheck $ do
    state <- toggleButtonGetActive autoYCheck
    if state
      then do modifyIORef iofset $ \f -> f { yRange = Nothing }
              widgetHideAll yRangeEntries
      else do lower <- builderGetObject builder castToAdjustment "Y-Lower"
              upper <- builderGetObject builder castToAdjustment "Y-Upper"
              (l, u) <- adjustmentPairValues (lower, upper)
              widgetShowAll yRangeEntries
              modifyIORef iofset $ \f -> f { yRange = Just (l, u) }
    redraw

  -- Sampling Rate
  sampleRate  <- builderGetObject builder castToAdjustment "Sampling Adj"
  _ <- onValueChanged sampleRate $ do
    rate <- adjustmentGetValue sampleRate
    modifyIORef iofset $ \f -> f { samplingRate = floor rate }
    redraw

  -- X-Label Entry
  xLabelEntry <- builderGetObject builder castToEntry "X-Label Entry"
  _ <- onEntryActivate xLabelEntry $ do
    label' <- entryGetText xLabelEntry
    modifyIORef iofset $ \f -> f { xLabel = Just label' }
    redraw

  -- X-Label Size
  xlSize <- builderGetObject builder castToAdjustment "X-Label Size"
  _ <- onValueChanged xlSize $ do
    size <- adjustmentGetValue xlSize
    modifyIORef iofset $ \f -> f { xLabelSize = size }
    redraw

  -- Y-Label Entry
  yLabelEntry <- builderGetObject builder castToEntry "Y-Label Entry"
  _ <- onEntryActivate yLabelEntry $ do
    label' <- entryGetText yLabelEntry
    modifyIORef iofset $ \f -> f { yLabel = Just label' }
    redraw

  ylSize <- builderGetObject builder castToAdjustment "Y-Label Size"
  _ <- onValueChanged ylSize $ do
    size <- adjustmentGetValue ylSize
    modifyIORef iofset $ \f -> f { yLabelSize = size }
    redraw

  -- Export Filename extry

  -- Export Button
  export <- builderGetObject builder castToButton "Export Button"
  onClicked export $ do
    fset <- readIORef iofset
    vars <- mapM adjustmentGetValue adjs

    comboText <- comboBoxGetActiveText combo
    nameEntry <- builderGetObject builder castToEntry "File Entry"
    nameText  <- entryGetText nameEntry

    modifyIORef iofset $ \f -> f { fileName = nameText }

    let rate    = samplingRate fset
        samples = (\(x, y) -> rate * floor (y - x)) (fromJust $ xRange fset)
        domain  = linspace samples (fromJust $ xRange fset)
        f = g vars
        colour = blue :: Color
        dset = (domain, [line f colour])
        dimensions = exportSize fset

        parseType txt = case txt of
                         "PNG" -> PNG
                         "SVG" -> SVG
                         "PS"  -> PS
                         "PDF" -> PDF
                         _     -> error "Invalid FileType!"


        filetype = let ftype = maybe (error "Invalid FileType!") unpack comboText
                   in parseType ftype

        parseExt fileType = case fileType of
                        PNG -> "PNG"
                        SVG -> "SVG"
                        PS  -> "PS"
                        PDF -> "PDF"

        filename = nameText ++ "." ++ map toLower (parseExt filetype)
    writeFigure filetype filename dimensions $ buildFigure dset fset