packages feed

lhae-0.0.2: src/Controller/Grid.hs

module Controller.Grid (new,changePageEventHandler
                       ,setFilePath,deleteCurrent,changePageTo
                       ,writeCell,writeCells
                       ,updateRowLabel,updateColumnLabel
                       ,updateRowLabels,updateColumnLabels
                       ,markAsSaved)
    where

import Control.Monad.Reader
import qualified Graphics.UI.WXCore as WXC
import Controller (Controller,onView,onModel,onGridModel,onGridView)
import Controller.Cell (updateInView,showContent,showSelectedContent)
import Controller.Menu.Table.Add (addRow,addColumn)
import View (onGrid,info)
import qualified View.GridPage as GridPage
import View.Component.Grid (getRowLabel,getColumnLabel,numDataRows
                           ,numDataColumns)
import qualified View.Component.Grid as GridV
import View.Dialog.Simple (input)
import View.Modes (formulaMode)
import qualified Model as M
import qualified Model.Grid as GridM
import qualified Model.Cell as Cell
import System.FilePath (takeFileName)
import Util (justWhen)
import CellCoordinate (CellCoord)
import View.FormulaInput (logString)

new :: Maybe FilePath -> Controller ()
new filePath = 
    let addModel id = 
            do viewInfo <- onView $ return . info
               onModel $ M.addGrid id viewInfo
               justWhen filePath $ onGridModel . GridM.setFilePath

        addView grid =
            do onView $ GridPage.add (fmap takeFileName filePath) grid
               ctrl <- ask
               onView $ \view -> 
                   onGrid view $ \grid ->
                       do WXC.gridOnGridEvent grid $ \event -> 
                              runReaderT (eventHandler event) ctrl
                          WXC.windowOnKeyDown grid 
                                 $ GridPage.keyEventHandler view
    in do
      (gridViewId,gridView) <- onView GridPage.new
      addModel gridViewId
      addView gridView

setFilePath :: FilePath -> Controller ()
setFilePath filePath = do
  onView $ GridPage.setCurrentCaption $ takeFileName filePath
  onGridModel $ GridM.setFilePath filePath

markAsUnsaved :: Controller ()
markAsUnsaved = do
  caption <- onView GridPage.getCurrentCaption
  when (head caption /= '*') 
           $ onView $ GridPage.setCurrentCaption $ '*':caption

markAsSaved :: Controller ()
markAsSaved = do
  x:xs <- onView GridPage.getCurrentCaption
  when (x == '*') $ onView $ GridPage.setCurrentCaption xs

deleteCurrent :: Controller ()
deleteCurrent = do
  onModel M.deleteCurrent
  onView GridPage.deleteCurrent
  next <- onView GridPage.currentSelectionId
  case next of
    Just n -> do onModel $ M.setCurrent n
                 showSelectedContent  
    Nothing -> onView $ logString ""

eventHandler :: WXC.EventGrid -> Controller ()
eventHandler event = 
    case event of 
        WXC.GridLabelMouse row col (WXC.MouseLeftDown {}) -> 
            do extendWhenClicked (row,col)
               liftIO WXC.propagateEvent
        WXC.GridLabelMouse row col (WXC.MouseLeftDClick {}) -> 
            do value <- if col == -1
                        then onGridView $ getRowLabel row
                        else onGridView $ getColumnLabel col
               value' <- onView $ input "Label" value
               justWhen value' $ if col == -1
                                 then updateRowLabel row
                                 else updateColumnLabel col

        WXC.GridCellMouse row col (WXC.MouseLeftDown {}) -> 
            do extendWhenClicked (row,col)
               liftIO WXC.propagateEvent
        WXC.GridEditorShown row col veto -> 
            do extendWhenClicked (row,col) 
               cell <- onGridModel $ GridM.getCell (row,col)
               onView (formulaMode (row,col) $ Cell.input cell)
               liftIO veto
        WXC.GridCellSelect row col _ -> 
            do showContent (row,col)
               liftIO WXC.propagateEvent
        _ -> liftIO WXC.propagateEvent

changePageEventHandler :: Controller ()
changePageEventHandler = do
  Just n <- onView $ GridPage.currentSelectionNum
  Just id <- onView $ GridPage.currentSelectionId
  onView $ GridPage.setCurrent n
  onModel $ M.setCurrent id  
  showSelectedContent

changePageTo :: Int -> Controller ()
changePageTo = onView . GridPage.fireSelectionEvent

extendWhenClicked :: CellCoord -> Controller ()
extendWhenClicked (row,column) = do
  rows <- onGridView GridV.numDataRows
  cols <- onGridView GridV.numDataColumns
  when (row == rows) $ addRow Nothing
  when (column == cols) $ addColumn Nothing

updateRowLabel,updateColumnLabel :: Int -> String -> Controller ()
updateRowLabel n to = do
  changed <- onGridModel $ GridM.updateRowLabel n to
  onGridView $ GridV.setRowLabel n to
  updateInView changed
  showSelectedContent
  markAsUnsaved
updateColumnLabel n to = do
  changed <- onGridModel $ GridM.updateColumnLabel n to
  onGridView $ GridV.setColumnLabel n to
  updateInView changed
  showSelectedContent
  markAsUnsaved

updateRowLabels,updateColumnLabels :: [String] -> Controller ()
updateRowLabels labels = do
  n <- onGridView numDataRows
  forM_ (zip [0..n-1] labels) $ uncurry updateRowLabel
updateColumnLabels labels = do
  n <- onGridView numDataColumns
  forM_ (zip [0..n-1] labels) $ uncurry updateColumnLabel

writeCell :: CellCoord -> String -> Controller ()
writeCell coord input = writeCells [(coord,input)]

writeCells :: [(CellCoord,String)] -> Controller ()
writeCells [] = return ()
writeCells cells = 
    let (maxRow,maxCol) = maximum $ map fst cells
    in do
      rows <- onGridView numDataRows
      cols <- onGridView numDataColumns

      forM_ [rows..maxRow] $ \_ -> addRow Nothing
      forM_ [cols..maxCol] $ \_ -> addColumn Nothing

      forM_ cells $ \(coord,input) -> do
         changed <- onGridModel $ GridM.setCell coord input
         updateInView changed

      markAsUnsaved