packages feed

INblobs-0.1.1: src/Ports.hs

module Ports 
    ( Port
    , Ports
    , PortName
    , PortZone(..)

    , isTheSameAs
    , isInterfacePort
    , drawPorts
    , drawPort 
    , drawFig 
    , drawPrincipalPort 
    , portZone 
    , isUp
    ) where

import Math
import Constants
import Shape
import CommonIO
import Colors
import Graphics.UI.WX as WX
import Graphics.UI.WXCore

{- | 'Ports' represents the extra information for a generalization of nodes in which a node have special points where it can conect with other nodes (more conrrectly the ports of other nodes). 

Each port is represented by its name and a point relative to the center of node shape.
-}

type PortName = String
type Port = (PortName, DoublePoint)

type Ports = [Port]

-- | Equality on ports. Right now it is exactly the same as @(==)@.
isTheSameAs :: Port -> Port -> Bool
isTheSameAs = (==)

isInterfacePort :: PortName -> Bool
isInterfacePort = (== "interface")

drawPorts :: Size -> DC () -> DoublePoint -> Ports -> [Prop (DC ())] -> IO ()
drawPorts ppi dc centre ports options =  
  case ports of 
    [("interface",position)] -> drawPrincipalPort ppi dc centre optionsIP position
    p  -> when (not $ null p)
                    (if hasPrincipalPorts
                     then do drawPrincipalPort ppi dc centre optionsPP (snd $ head p)
                             mapM_ ( drawPort ppi dc centre optionsP . snd ) (tail p)
                     else mapM_ ( drawPort ppi dc centre optionsP . snd ) p
                    )

  where options' = [ brushKind  := BrushSolid ] ++ options
        optionsP  = [ brushColor := kPortBrushColor
                    , penColor   := kPortPenColor 
                    ] ++ options'
        optionsPP = [ brushColor := kPrincipalPortBrushColor 
                    , penColor   := kPrincipalPortPenColor 
                    ] ++ options'
        optionsIP = [ brushColor := kInterfacePortBrushColor 
                    , penColor   := kInterfacePortPenColor 
                    ] ++ options'

drawPort :: Size -> DC () -> DoublePoint -> [Prop (DC ())] -> DoublePoint -> IO ()
drawPort ppi dc centre options point =
    WX.circle dc 
              (logicalToScreenPoint ppi $ translate centre point)
              (logicalToScreenX ppi kPortRadius)
              options

drawPrincipalPort :: Size -> DC () -> DoublePoint -> [Prop (DC ())] -> DoublePoint -> IO ()
drawPrincipalPort ppi dc centre options point = 
   WX.polygon dc points options
   where centro = logicalToScreenPoint ppi $ translate centre point
         param  = kPrincipalPortSize
         points = 
            [ pointMove (vector param     param)     centro
            , pointMove (vector param     (- param)) centro
            , pointMove (vector (- param) (- param)) centro
            , pointMove (vector (- param) param)     centro
            ]

drawFig :: DC () -> Rect -> Shape -> Ports -> [Prop (DC ())] -> IO ()
drawFig dc r shape ports options = 
  do{
    -- Scale if the DC we are drawing to has a different PPI from the screen
    ; dcPPI <- dcGetPPI dc
    ; screenPPI <- getScreenPPI
    ; when (dcPPI /= screenPPI) $
        dcSetUserScale dc
            (fromIntegral (sizeW dcPPI ) / fromIntegral (sizeW screenPPI ))
            (fromIntegral (sizeH dcPPI ) / fromIntegral (sizeH screenPPI ))

    -- Set font
    ; set dc [ fontFamily := FontDefault, fontSize := 10 ]

    ; let ppi = screenPPI
          -- center of drawing area
          center = screenToLogicalPoint ppi $ rectCentralPoint r 

    ; logicalDraw ppi dc center shape options
    ; drawPorts ppi dc center ports options
    }


data PortZone = Ztop | Zbottom | Zleft | Zright deriving (Show)

-- | Divides the 2D space with y=x and y=-x rects 
portZone :: Port -> PortZone
portZone (_, DoublePoint x y) | y >  x && y <= -x = Zleft
                              | y >= x && y >  -x = Zbottom
                              | y <  x && y >= -x = Zright
                              | y <= x && y <  -x = Ztop

-- | A different division in 2D space; the port is in the upper part of the node?
isUp :: Port -> Bool
isUp (_, DoublePoint _ y) = y <= 0