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