packages feed

INblobs-0.1.1: src/Document.hs

{-| Module      :  Document
    Maintainer  :  afie@cs.uu.nl

    This module contains functions to create documents
    and to get and set components of the Document datatype.
-}

module Document
    ( Document
    , RuleName
    , ActiveCanvas(..) 
    , Selection(..)
    , empty
    , getNetwork,       setNetwork, unsafeSetNetwork
    , getPalette,       setPalette
    , getSelection,     setSelection
    , getRules,         setRules

    , updateNetwork, updateNetworkEx
    , joinPalette
    , updateRules
    , selectNetwork
    , updateSelNetwork, updateSelNetworkEx
    , removeMappingElemWithNode
    , show'
    ) where

import Network hiding (empty)
import INRule
import INRules hiding (empty) 
import InfoKind
import Math
import Ports
import Palette hiding (delete, empty)
import qualified Network (empty)
import qualified INRules (empty) 
import qualified Palette (empty)

import Data.Maybe

{--------------------------------------------------
 -- TYPES
 --------------------------------------------------}

data Document g n e = Document
    { docNetwork        :: Network g n e
    , docPalette        :: Palette n          -- ^ the current 'Palette'
    , docSelection      :: Selection
    , docRules          :: INRules g n e
    } deriving Show

type RuleName = String
data ActiveCanvas = Net | LHS RuleName | RHS RuleName deriving (Show, Eq, Read)

data Selection
    = NoSelection
    | NodeSelection ActiveCanvas Int (Maybe PortName)
    | EdgeSelection ActiveCanvas Int
    | ViaSelection  ActiveCanvas Int Int
    | MultipleSelection ActiveCanvas 
                        (Maybe (DoublePoint,DoublePoint)) [Int] [(Int,Int)]
	-- DoublePoint pair is for displaying dragged selection rectangle
    deriving (Show, Read, Eq)

{--------------------------------------------------
 -- CREATION
 --------------------------------------------------}


-- | An empty document
empty :: (InfoKind e g, InfoKind n g) => g -> n -> e -> Document g n e
empty g n e =
    Document
    { docNetwork    = Network.empty g n e
    , docPalette    = Palette.empty
    , docSelection  = NoSelection
    , docRules      = INRules.empty g n e
    }

{--------------------------------------------------
 -- GETTERS
 --------------------------------------------------}

getNetwork              :: Document g n e -> Network g n e
getPalette              :: Document g n e -> Palette n
getSelection            :: Document g n e -> Selection
getRules                :: Document g n e -> INRules g n e

getNetwork              doc = docNetwork   doc
getPalette              doc = docPalette   doc
getSelection            doc = docSelection doc
getRules                doc = docRules     doc

{--------------------------------------------------
 -- SETTERS
 --------------------------------------------------}

-- | setNetwork clears the selection because the node may not exist
--   in the new network
setNetwork :: Network g n e -> Document g n e -> Document g n e
setNetwork theNetwork doc =
    doc { docNetwork = theNetwork
        , docSelection = NoSelection
        }

setPalette :: Palette n -> Document g n e -> Document g n e
setPalette thePalette doc = doc { docPalette = thePalette }

setSelection :: Selection -> Document g n e -> Document g n e
setSelection theSelection doc = doc { docSelection = theSelection }

setRules :: INRules g n e -> Document g n e -> Document g n e
setRules theRules doc = doc {docRules = theRules}

updateNetwork :: (Network g n e -> Network g n e)
                 -> Document g n e -> Document g n e
updateNetwork networkFun doc
    = unsafeSetNetwork (networkFun (getNetwork doc))
    $ doc

updateNetworkEx :: (Network g n e -> (b, Network g n e))
                   -> Document g n e -> (b, Document g n e)
updateNetworkEx networkFun doc =
    let (result, newNetwork) = networkFun (getNetwork doc)
    in ( result
       , unsafeSetNetwork newNetwork doc
       )

joinPalette :: (Eq n) => Palette n -> Document g n e -> Document g n e
joinPalette palette doc = doc { docPalette = join (getPalette doc) palette }

updateRules :: (INRules g n e -> INRules g n e) 
               -> Document g n e -> Document g n e
updateRules rulesFun doc = doc { docRules = rulesFun $ docRules doc }

-- | Doesn't clear the selection
unsafeSetNetwork :: Network g n e -> Document g n e -> Document g n e
unsafeSetNetwork theNetwork doc = doc { docNetwork = theNetwork }

-- | Given a document and the active canvas this function selects 
-- the corresponding network.
selectNetwork :: Document g n e -> ActiveCanvas -> Network g n e
selectNetwork doc canvas =
   case canvas of
      Net          -> getNetwork doc
      LHS ruleName -> fromMaybe (erro ruleName)
                       $ getLHS `fromRule` ruleName $ getRules doc
      RHS ruleName -> fromMaybe (erro ruleName) 
                       $ getRHS `fromRule` ruleName $ getRules doc
   where erro ruleName = error $ "This shouldn't happen because << "
                               ++ ruleName ++ " >> must be a rule."

-- | Given a document and the active canvas this function updates 
-- the corresponding network accordingly the the updater network 
-- function given as an argument.
updateSelNetwork :: (Network g n e -> Network g n e)
                    -> ActiveCanvas -> Document g n e -> Document g n e
updateSelNetwork netFunc canvas doc =
   case canvas of 
      Net          -> updateNetwork netFunc doc
      LHS ruleName -> updateRules (updateRule ruleName $ updateLHS netFunc) doc
      RHS ruleName -> updateRules (updateRule ruleName $ updateRHS netFunc) doc

updateSelNetworkEx :: (Network g n e -> (b, Network g n e))
                      -> ActiveCanvas -> Document g n e -> (b, Document g n e)
updateSelNetworkEx networkFun canvas doc =
    let (result, newNetwork) = networkFun (selectNetwork doc canvas)
    in ( result
       , case canvas of
            Net          -> unsafeSetNetwork newNetwork doc
            LHS ruleName -> updateRules (updateRule ruleName 
                                           $ setLHS newNetwork) doc
            RHS ruleName -> updateRules (updateRule ruleName 
                                           $ setRHS newNetwork) doc
       )

removeMappingElemWithNode :: ActiveCanvas -> NodeNr -> Document g n e -> Document g n e
removeMappingElemWithNode canv nodeNr = 
     case canv of
        Net -> id
        LHS rule -> updateRules $ updateRule rule $ updateMapping $ filter $ (/= nodeNr) . fst
        RHS rule -> updateRules $ updateRule rule $ updateMapping $ filter $ (/= nodeNr) . snd

show' :: ActiveCanvas -> String
show' Net        = "net"
show' (LHS rule) = "rule " ++ rule ++ "'s LHS"
show' (RHS rule) = "rule " ++ rule ++ "'s RHS"