packages feed

lhae-0.0.2: src/Controller/Menu/File/Export/Diagram/BoxPlot.hs

module Controller.Menu.File.Export.Diagram.BoxPlot (eventHandler)
    where

import Control.Applicative ((<$>))
import Control.Monad (when)
import Text.Printf (printf)
import Data.List (sort)
import Controller (Controller,getFromConfig,onView
                  ,onGridView,setOnConfig)
import Controller.Menu.File.Export.Diagram.BoxPlotParameters (Parameters(..))
import qualified Controller.Menu.File.Export.Diagram.Common as Common
import Controller.Dialog (nonNumericDataWarningText
                         ,noColumnsSelectedText,saveFileDialog)
import Config (boxPlotExportParameters)
import View.Component.Grid (getColumnLabels)
import View.Dialog.Complex (Layout (..),Widget (..),Modifier (..)
                           ,showDialog,cancelButton)
import Util.FileType (justPngWildcard)
import qualified Model.CellExpression.Evaluator.Math as Math
import I18n (__)

data Action = Preview | Export

eventHandler :: Controller ()
eventHandler = getFromConfig boxPlotExportParameters 
               >>= \params -> eventHandlerWith $ params {columns = []}

eventHandlerWith :: Parameters -> Controller ()
eventHandlerWith initParams = do
  result <- do d <- dialog <$> onGridView getColumnLabels
               onView $ showDialog (__ "Export") d initParams
  case result of
    Nothing -> return ()
    Just (params,Export) ->         
        do saveFile <- saveFileDialog (__ "Export") justPngWildcard
           setOnConfig $ \c -> c {boxPlotExportParameters = params}
           case saveFile of
             Nothing -> eventHandlerWith params
             Just imageFilePath -> 
                 do success <- Common.plot (gpFileContent params) 
                               (dataFileContent params) imageFilePath
                    when (not success) $ eventHandlerWith params

    Just (params,Preview) ->
        do setOnConfig $ \c -> c {boxPlotExportParameters = params}
           _ <- Common.showPreview (gpFileContent params) 
                                   (dataFileContent params)
           eventHandlerWith params

dialog :: [String] -> Layout Parameters Action
dialog columnLabels =
    let setCols p cols = p {columns = cols}
        setBoxWidth p w = p {boxWidth = w}
        setGaps p g = p {gaps = g}
    in
      Modifier Margin $ Column 
       [ Row [ Grid [[ Label $ __ "Box width"
                     , Widget $ NumberEntry boxWidth setBoxWidth]
                    ,[ Label $ __ "Gaps"
                     , Widget $ Spinner 1 maxBound gaps setGaps]
                    ]
             , Modifier Center $ Modifier (Boxed $ __ "Columns") 
                 $ Widget $ MultiListBox columnLabels columns setCols
             ]
       , Modifier Center $ Row 
                      [ Widget $ DefaultButton (__ "&Export") Export
                      , Widget $ Button (__ "&Preview") Preview
                      , cancelButton]]

dataFileContent :: Parameters -> Controller (Either String String)
dataFileContent (Parameters {columns = []}) = return $ Left noColumnsSelectedText
dataFileContent (Parameters {columns = cols,gaps = gaps}) = do
  numericColumns <- Common.getNumericColumns cols
  case numericColumns of
    Left nonNumeric -> return $ Left $ nonNumericDataWarningText nonNumeric
    Right columns -> 
        let toLine (i,(label,values)) =
                let sorted = sort values
                    max = maximum sorted
                    min = head sorted
                    firstQuartile = Math.firstQuartileSorted sorted
                    thirdQuartile = Math.thirdQuartileSorted sorted
                    median = Math.medianSorted sorted
                    values' = [firstQuartile,min,max,thirdQuartile,median]
                in unwords $ [show label,show i] ++ (map show values')
        in
          return $ Right $ unlines $ map toLine $ zip [0,gaps..] columns

gpFileContent :: Parameters -> FilePath -> String
gpFileContent params dataFilePath = 
    printf (unlines
      [ "set key off"
      , "set xrange [%d:%d]"
      , "set boxwidth %f"
      , "plot '%s' using 2:3:4:5:6:xtic(1) with candlesticks whiskerbars,"
        ++ "'' using 2:7:7:7:7 with candlesticks"
      ])
    (-(gaps params)) (length (columns params) + (gaps params) - 1)
    (boxWidth params) dataFilePath