# The `Object I/O` package: GUI library for Haskell

## Object I/O

The Original `Object I/O` library was written in Clean from university of Nijmeegs. At 12th International Workshop on the Implementation of Functional Languages Peter Achten and Simon Peyton Jones, presented, first attempt to port library to Haskell. Initial port has been very simple, but support basic features of complete library. I decided to continue their work and now `Object I/O` supports a large list of features: Windows, Dialogs, Various kind of controls, Menus, Timers, Graphics and some other. In CVS repository there are some interesting examples. Currently `Object I/O` works only on Windows Platform but I plan porting to GTK for the next release.

## Basics

The central point of `Object I/O` are various kinds of objects (devices) as Windows, Controls, Timers, Menus and Process. Every object has it's own unique Id which may be defined from user or may be automatically generated from the system. Having object Id we may manage it, i.e. change it attributes. For example: we may change the windows's title. The most important attribute of the object is it's local state. It can be data from various types who describe the current state of the object. The object can also receive events. Every time an event is received, a user defined function, named 'handler', is called. The 'handler' takes current local state of the object and the local state of process in which the object exists, and returns the modified states.

## Usage

To gain access to the library, just `import ObjectIO` in your Haskell module and add the `-package objectio` option to the command line.

The library contains a set of modules described in the next chapters. Each module corresponds to a defined type of device. By using this module you can avoid the import of every single module i.e. to import all of them.

## StdIOCommon

This module contains a set of data types and definitions of functions that are used in the other modules.

General type constructors for composing context-independent data structures.

    infixr 9 :^:
    data    Tup     t1 t2                   = t1 :^: t2

General type constructors for composing context-dependent data structures.

    infixr 9 :~:
    data    TupSt   t1 t2   ps      = (t1 ps) :~: (t2 ps)
    data    ListCS  t               ps      = ListCS [t ps]
    data    NilCS                   ps      = NilCS

General type constructors for composing local and context-dependent data structures.

    infixr 9 :+:
    data    TupLS   t1 t2   ls      ps      = (t1 ls ps) :+: (t2 ls ps)
    data    ListLS  t       ls      ps      = ListLS [t ls ps]
    data    NilLS           ls      ps      = NilLS
    data    NewLS   t       ls      ps      = forall new . NewLS new (t  new     ps)
    data    AddLS   t       ls      ps      = forall add . AddLS add (t (add,ls) ps)

    data SelectState = Able | Unable deriving (Eq,Show)
    enabled :: SelectState -> Bool

SelectState is similar to Bool but it shows whether an object is enabled or disabled.

    data MarkState = Mark | NoMark deriving (Eq,Show)
    marked :: MarkState -> Bool

MarkState is similar to Bool but it shows whether the `CheckControl` is marked.

    class Toggle a where
            toggle :: a -> a

`toggle` is a polymorphic version of `not`. There are

    instance Toggle Bool                    -- toggle b = not b
    instance Toggle SelectState
    instance Toggle MarkState

Other type classes

    class Zero a where
            zero   :: a
    class One a where
            one    :: a

There are instances for Zero and One for some of the following types.

    type    Index = Int
    type    Title = String

    data    Vector2 = Vector2 {vx :: !Int, vy :: !Int}
            deriving (Eq,Show)
    instance Zero Vector2 where
    instance Num Vector2 where

Note that (*), abs, signum and fromInteger members of Num instance are undefined!!

    class ToVector x where
            toVector :: x -> Vector2

ToVector allow coercion between Vector2 and Size and Point2 types.

    data    Size = Size {w :: !Int, h :: !Int}
            deriving (Eq,Show)
    instance Zero Size where                -- {w=0,h=0}
    instance ToVector Size where    -- {w,h}->{vx=w,vy=h}

    data    Point2    = Point2 {x :: !Int, y :: !Int}
            deriving (Eq,Show)
    instance Zero Point2 where
    instance Num Point2 where
    instance ToVector Point2 where

Note that (*), abs, signum and fromInteger members of Num instance are undefined!!

    data    Rectangle = Rectangle {corner1 :: !Point2, corner2 :: !Point2}
            deriving (Eq,Show)
    instance Zero Rectangle where

    rectangleSize :: Rectangle -> Size              -- {w=abs (@1.corner1-@1.corner2).x,
                                                                                    --  h=abs (@1.corner1-@1.corner2).y}
    movePoint :: Vector2 -> Point2 -> Point2        -- {vx,vy} {x,y} -> {vx+x,vy+y}

    data KeyboardState
            = CharKey    Char       KeyState                        -- ASCII character input
            | SpecialKey SpecialKey KeyState Modifiers      -- Special key input
            | KeyLost                                                                       -- Key input lost while key was down
            deriving (Eq,Show)
    data    KeyState
            = KeyDown    IsRepeatKey                                        -- Key is down
            | KeyUp                                                                         -- Key goes up
            deriving (Eq,Show)
    type    IsRepeatKey                                                             -- Flag on key down:
            = Bool                                                                          -- True iff key is repeating
    data    Key
            = IsCharKey    Char
            | IsSpecialKey SpecialKey

KeyboardState is passed to keyboard handler for every keyboard event.

    getKeyboardStateKeyState:: KeyboardState -> KeyState

getKeyboardStateKeyState gets KeyState from KeyboardState (KeyUp if KeyboardState is KeyLost)

    getKeyboardStateKey :: KeyboardState -> Maybe Key

getKeyboardStateKey gets Key value from KeyboardState (Nothing if KeyboardState is KeyLost)

    data    MouseState
            = MouseMove     Point2 Modifiers                -- Mouse is up     (position,modifiers)
            | MouseDown     Point2 Modifiers Int            -- Mouse goes down (and nr down)
            | MouseDrag     Point2 Modifiers                -- Mouse is down   (position,modifiers)
            | MouseUp       Point2 Modifiers                -- Mouse goes up   (position,modifiers)
            | MouseLost                                     -- Mouse input lost while mouse was down
            deriving (Eq, Show)
    data    ButtonState
            = ButtonStillUp                                 -- MouseMove
            | ButtonDown                                    -- MouseDown _ _ 1
            | ButtonDoubleDown                              --                       _ _ 2
            | ButtonTripleDown                              --           _ _ >2
            | ButtonStillDown                               -- MouseDrag
            | ButtonUp                                      -- MouseUp/MouseLost
            deriving (Eq, Show)
    type    MouseStateFilter =                              -- Predicate on MouseState:
                    MouseState -> Bool                      -- evaluate MouseFunction only if True

    getMouseStatePos :: MouseState -> Point2
    getMouseStateModifiers :: MouseState -> Modifiers
    getMouseStateButtonState:: MouseState   -> ButtonState

    data    SliderState
            = SliderState
                    { sliderMin     :: !Int
                    , sliderMax     :: !Int
                    , sliderThumb   :: !Int
                    }
            deriving (Eq, Show)

    data    UpdateState
            = UpdateState
                    { oldFrame      :: !ViewFrame
                    , newFrame      :: !ViewFrame
                    , updArea       :: !UpdateArea
                    }
            deriving (Show)
    type    ViewDomain = Rectangle
    type    ViewFrame  = Rectangle
    type    UpdateArea = [ViewFrame]

    rectangleToUpdateState :: Rectangle -> UpdateState

    viewDomainRange :: ViewDomain
    viewFrameRange :: ViewFrame

viewDomainRange and viewFrameRange define the minimum and maximum values for ViewDomains and ViewFrames.

    data    Modifiers
            = Modifiers
                    { shiftDown     :: !Bool                        -- True iff shift   down
                    , optionDown    :: !Bool                        -- True iff option  down
                    , commandDown   :: !Bool                        -- True iff command down
                    , controlDown   :: !Bool                        -- True iff control down
                    , altDown       :: !Bool                        -- True iff alt     down
                    }
            deriving (Eq,Show)

Modifiers indicates the meta keys that have been pressed (True) or not (False).

    noModifiers, shiftOnly, optionOnly, commandOnly, controlOnly, altOnly :: Modifiers

These are constants that check which of the Modifiers are pressed.

The layout language used for windows and controls.

    type    ItemPos
            =       ( ItemLoc
                    , ItemOffset
                    )
    data    ItemLoc
     --     Absolute:
            = Fix
     --     Relative to corner:
            | LeftTop
            | RightTop
            | LeftBottom
            | RightBottom
     --     Relative in next line:
            | Left
            | Center
            | Right
     --     Relative to other item:
            | LeftOf  Id
            | RightTo Id
            | Above   Id
            | Below   Id
     --     Relative to previous item:
            | LeftOfPrev
            | RightToPrev
            | AbovePrev
            | BelowPrev
            deriving (Eq,Show)
    type    ItemOffset = Vector2    -- A constant offset vector

The Direction type.

    data    Direction
            = Horizontal
            | Vertical
            deriving Eq

The CursorShape type.

    data    CursorShape
            = StandardCursor
            | BusyCursor
            | IBeamCursor
            | CrossCursor
            | FatCrossCursor
            | ArrowCursor
            | HiddenCursor
            deriving Eq

Document interface of interactive processes.

    data    DocumentInterface
            = NDI                                                   -- No       Document Interface
            | SDI                                                   -- Single   Document Interface
            | MDI                                                   -- Multiple Document Interface
            deriving (Eq,Show)

    data    SliderMove
            = SliderIncSmall
            | SliderDecSmall
            | SliderIncLarge
            | SliderDecLarge
            | SliderThumb Int
            deriving Show

Common error report types. See throwGUI

    data    ErrorReport                                             -- Usual cause:
            = ErrorViolateDI                                        -- Violation against DocumentInterface
            | ErrorIdsInUse                                         -- Object contains Ids that are bound
            | ErrorUnknownObject                            -- Object can not be found
            | ErrorNotifierOpen                                     -- It was tried to open a second send notifier
            | ErrorUnableReceiver
            | ErrorDeadlock
            | OtherError !String                            -- Other kind of error
            deriving (Eq,Show)

    handleErrorReport :: Monad m => ErrorReport -> m a

`handleErrorReport` is a help function that just calls `fail` with an appropriate error message. It can be used with `catchGUI`. Example:

    test1 :: GUI ps x
    test1 = . . .

    test :: GUI ps x
    test = catchGUI test1 handleErrorReport

Note: The Scheduler calls all object callbacks in that way.

Monad extensions

    class Monad m => IOMonad m where
            liftIO :: IO a -> m a

    instance IOMonad IO where
            liftIO f = f

`IOMonad` class is a simply way to call `IO` monads from other `IO`-like monads.

## StdGUI

This module provides declaration of abstract `GUI monad`.

    data GUI ps x
    type GUIFun  ls ps = (ls,ps) -> GUI ps (ls,ps)
    type GUI2Fun ps = ps -> GUI ps ps

where ps is a type of local process state. GUIFun and GUI2Fun are additional types which describe state transforming GUI actions, first with both local and process state and second only with process state. There are instances of Monad, IOMonad and Functor type classes.

    instance Monad (GUI ps)
    instance IOMonad (GUI ps)
    instance Functor (GUI ps)

Each object event handler must be GUI monad action, usually of GUIFun or GUI2Fun type.

## StdId

Id generation routines.

    openId     :: Ids m => m Id
    openIds    :: Ids m => Int -> m [Id]

    openR2Id   :: Ids m => m (R2Id m r)
    openR2Ids  :: Ids m => Int -> m (R2Id m r)

    openRId    :: Ids m => m (RId x)
    openRIds   :: Ids m => Int -> m [RId x]

There is `Ids` type class, which allows the functions to be called both from `IO` and `GUI` monad.

`openId` returns one new id

`openIds` returns a list of N items i.e. [id1, id2..idN]

    openIds 3 = [id1, id2, id3]

`openRId`, `openRIds`, `openR2Id` and `openR2Ids` are the same as openId and openIds but they return special receiver and bi-receiver ids (see ).

## StdWindow

In the Object I/O library there are two main window types:

`data Dialog c ls ps = Dialog Title (c ls ps) [WindowAttribute ls ps]`

  The dialogs are nonresizable modal or nonmodal windows. They adjust their size to the common size of the contained controls. They usually have two special buttons called `Ok` and `Cancel`. When the user presses Enter or Esc keys, the dialog interprets this event as clicking on `Ok` or `Cancel`.

`data Window c ls ps = Window Title (c ls ps) [WindowAttribute ls ps]`

  The windows are resizable and one can draw in the view domain.This can be programmed as a Haskell's function. They also can have vertical and horizontal scroll bars, which extend logical view frame of the windows.

Both windows and dialogs can contain various kinds of controls but they can't contain other windows or dialogs. The type variable `c` mentioned above corresponds to the type of the containing controls.

The type variables `ls` and `ps` as usual define local state and process state types.

`WindowAttribute` defines a set of built-in window attributes.

    data    WindowAttribute ls ps                        -- Default:
             --     Attributes for Windows and Dialogs:
             =      WindowActivate   (GUIFun ls ps)              -- id
             |      WindowClose      (GUIFun ls ps)              -- user can't close window
             |      WindowDeactivate (GUIFun ls ps)              -- id
             |      WindowHMargin    Int Int                     -- system dependent
             |      WindowId         Id                          -- system defined id
             |      WindowIndex      Int                         -- open front-most
             |      WindowInit       (GUIFun ls ps)              -- no actions after opening window
             |      WindowInitActive Id                          -- system dependent
             |      WindowItemSpace  Int Int                     -- system dependent
             |      WindowOuterSize  Size                        -- screen size
             |      WindowPos        ItemPos                     -- system dependent
             |      WindowViewSize   Size                        -- screen size
             |      WindowVMargin    Int Int                     -- system dependent
             --     Attributes for Dialog only:
             |      WindowCancel     Id                          -- no cancel  (Custom)ButtonControl
             |      WindowOk         Id                          -- no default (Custom)ButtonControl
             --     Attributes for Windows only:
             |      WindowCursor     CursorShape                 -- no change of cursor
             |      WindowHScroll    ScrollFunction              -- no horizontal scrolling
             |      WindowKeyboard   KeyboardStateFilter SelectState (KeyboardFunction ls ps) -- no keyboard input
             |      WindowLook       Bool Look                   -- show system dependent background
             |      WindowMouse      MouseStateFilter SelectState (MouseFunction ls ps) -- no mouse input
             |      WindowOrigin     Point2                      -- left top of picture domain
             |      WindowPen        [PenAttribute]              -- default pen attributes
             |      WindowSelectState       SelectState          -- Able
             |      WindowViewDomain        ViewDomain           -- {zero,max range}
             |      WindowVScroll           ScrollFunction       -- no vertical scrolling

### Windows creation.

If the user wants to define his/her own window types, there are polymorphic creation functions.

    class Windows wdef where
            openWindow :: ls -> wdef ls ps -> ps -> GUI ps ps

    class Dialogs ddef where
            openDialog :: ls -> ddef ls ps -> ps -> GUI ps ps
            openModalDialog :: ls -> ddef ls ps -> ps -> GUI ps (ps, (Maybe ls))

The user must define instances of Windows or Dialogs classes for his/her own window or dialog types. Built-in types have instances defined as:

    instance Controls c => Dialog (Dialog c)
    instance Controls c => Window (Window c)

where `Controls` type class has instances for all types of controls.

### Windows closing.

    closeWindow :: Id -> GUI2Fun ps
    closeActiveWindow :: GUI2Fun ps

`closeWindow`

  closes window with specified Id

`closeActiveWindow`

  closes active window. Often we can use `closeActiveWindow` together with WindowClose attribute. For example adding

      WindowClose (noLS
                  closeActiveWindow)

  to the window attributes list closes the window when the user clicks the close button.

### Getting and setting active window

    setActiveWindow :: Id -> GUI ps ()
    getActiveWindow :: GUI ps (Maybe Id)

`setActiveWindow`

  activates window with specified Id

`getActiveWindow`

  returns Id of active window if it exists.

### Getting and setting active control inside a window

    setActiveControl :: Id -> GUI ps ()
    getActiveControl :: GUI ps (Maybe Id)

`setActiveControl`

  activates control with specified Id.

`getActiveControl`

  returns Id of active control if it exists.

### Stacking order

    stackWindow :: Id -> Id -> GUI ps ()
    getWindowStack :: GUI ps [(Id,WindowKind)]
    getWindowsStack :: GUI ps [Id]
    getDialogsStack :: GUI ps [Id]

`stackWindow`

  `stackWindow id1 id2` stacking window with id1 before window with id2.

`getWindowStack`

  returns list of window and dialog ids in stacking order.

`getWindowsStack`

  returns list of window ids in stacking order.

`getDialogsStack`

  returns list of dialog ids in stacking order.

### Window margins

Getting values of default horizontal and vertical window margins and control item space

    getDefaultHMargin :: Bool -> GUI ps Int
    getDefaultVMargin :: Bool -> GUI ps Int
    getDefaultItemSpace :: GUI ps (Int,Int)

Getting values of current horizontal and vertical window margins and control item space

    getWindowHMargin :: Id  -> GUI ps (Maybe (Int,Int))
    getWindowVMargin :: Id  -> GUI ps (Maybe (Int,Int))
    getWindowItemSpace :: Id -> GUI ps (Maybe (Int,Int))

Current values are defined with `WindowHMargin`, `WindowVMargin`, `WindowItemSpace`

### Enable/Disable Window, Keyboard and Mouse

The following functions correspond to WindowSelectState attribute:

    enableWindow :: Id -> GUI ps ()
    disableWindow :: Id -> GUI ps ()
    getWindowSelectState :: Id -> GUI ps (Maybe SelectState)

`enableWindow`

  enables window with specified Id

`disableWindow`

  disables window with specified Id

`getWindowSelectState`

  returns current select state

The following functions correspond to WindowMouse attribute

    enableWindowMouse  :: Id -> GUI ps ()
    disableWindowMouse :: Id -> GUI ps ()

    setWindowMouseSelectState :: SelectState -> Id -> GUI ps ()
    getWindowMouseSelectState :: Id -> GUI ps (Maybe SelectState)

    getWindowMouseStateFilter :: Id -> GUI ps (Maybe MouseStateFilter)
    setWindowMouseStateFilter :: Id -> MouseStateFilter -> GUI ps ()

`setWindowMouseSelectState`

  set current select state for mouse events

`enableWindowMouse`

  enables receiving mouse events for a window with a specified Id

      enableWindowMouse =
                  setWindowMouseSelectState Able

`disableWindowMouse`

  disables receiving mouse events for a window with a specified Id

      disableWindowMouse =
                  setWindowMouseSelectState Unable

`getWindowSelectState`

  returns current mouse select state

`getWindowMouseStateFilter`, `setWindowMouseStateFilter`

  Receiving mouse event can be additionally disabled with specified MouseStateFilter

The following functions correspond to WindowKeyboard attribute

    enableWindowKeyboard  :: Id -> GUI ps ()
    disableWindowKeyboard :: Id -> GUI ps ()

    setWindowKeyboardSelectState :: SelectState -> Id -> GUI ps ()
    getWindowKeyboardSelectState :: Id -> GUI ps (Maybe SelectState)

    getWindowKeyboardStateFilter :: Id -> GUI ps (Maybe KeyboardStateFilter)
    setWindowKeyboardStateFilter :: Id -> KeyboardStateFilter -> GUI ps ()

`setWindowKeyboardSelectState`

  sets current select state for keyboard events

`enableWindowKeyboard`

  enables receiving keyboard events for a window with a specified Id

      enableWindowKeyboard = setWindowKeyboardSelectState Able

`disableWindowKeyboard`

  disables receiving keyboard events for a window with a specified Id

      disableWindowKeyboard = setWindowKeyboardSelectState Unable

`getWindowKeyboard`

  returns current keyboard select state

`getWindowKeyboardStateFilter`, `setWindowKeyboardStateFilter`

  Receiving of keyboard event can be additionally disabled with specified KeyboardStateFilter

### Drawing

Every window can have its own WindowLook attribute, which describes its Look function. The Look is defined as the type `SelectState -> UpdateState -> Draw ()` and this function is called every time when the window needs to be redrawn

The current look can be accessed by the following functions:

    setWindowLook :: Id -> Bool -> (Bool,Look) -> GUI ps ()
    getWindowLook :: Id -> GUI ps (Maybe (Bool,Look))

Use `updateWindow` to force window redrawing

    updateWindow :: Id -> Maybe ViewFrame -> GUI ps ()

We can also draw directly in the window with `drawInWindow` function but in this case everything displayed with `drawInWindow` will be erased after the next updateWindow call.

    drawInWindow :: Id -> Draw x -> GUI ps (Maybe x)

See for details about drawing.

### Window positioning and window resizing

    setWindowPos :: Id -> ItemPos -> GUI ps ()
    getWindowPos :: Id -> GUI ps (Maybe Vector2)

`setWindowPos`

  positions the specified window to a given position

`getWindowPos`

  returns current window position

    moveWindowViewFrame :: Id -> Vector2 -> GUI ps ()
    getWindowViewFrame :: Id -> GUI ps ViewFrame

`ViewFrame` is the current visible `Rectangle` of the window. When there are horizontal and vertical scroll bars, then the changing of the scroller thumb changes the ViewFrame.`getWindowViewFrame` returns the current ViewFrame and `moveWindowViewFrame` moves it through the specified vector.

    setWindowViewSize :: Id -> Size -> GUI ps ()
    getWindowViewSize :: Id -> GUI ps Size

`ViewSize` is the current inner size of the window (It doesn't include the title bar and the scrollers' area). The above functions get/set the current ViewSize value.

    setWindowOuterSize :: Id -> Size -> GUI ps ()
    getWindowOuterSize :: Id -> GUI ps Size

`OuterSize` is the current full window size. The above functions get/set the current OuterSize value.

    setWindowViewDomain :: Id -> ViewDomain -> GUI ps ()
    getWindowViewDomain :: Id -> GUI ps (Maybe ViewDomain)

`ViewDomain` is a `Rectangle` which specifies the logical drawing area of the window. The above functions get/set the current ViewDomain value.

### Windows scrolling

    setWindowScrollFunction :: Id -> Direction -> ScrollFunction -> GUI ps ()
    getWindowScrollFunction :: Id -> Direction -> GUI ps (Maybe ScrollFunction)

The ScrollFunction describes the behaviour of the horizontal or vertical (according to `Direction` parameter) scroll bars. The ScrollFunction calculates the step by which ViewFrame is moved inside the ViewDomain.

### Mouse cursor

    setWindowCursor :: Id -> CursorShape -> GUI ps ()
    getWindowCursor :: Id -> GUI ps (Maybe CursorShape)

The `CursorShape` describes the shape of the mouse cursor when it is over the window.

### Window title

    setWindowTitle :: Id -> Title -> GUI ps ()
    getWindowTitle :: Id -> GUI ps (Maybe Title)

`Title` is a string, which is displayed at the top of the window. The title can also be defined with the WindowTitle attribute.

### Dialogs: Ok and Cancel buttons

    getWindowOk :: Id -> GUI ps (Maybe Id)
    getWindowCancel :: Id -> GUI ps (Maybe Id)

The above functions return Ids of Ok and Cancel buttons of the specified dialog. These Ids must be defined with WindowOk and WindowCancel attributes.

## StdControl

Object I/O library supports various kinds of built-in controls which can be placed inside windows and dialogs. In order to define his/her own type controls, the user should give an instance of Controls class (see )

    class Controls cdef where
            controlToHandles :: cdef ls ps -> GUI ps [ControlState ls ps]

    instance Controls c => Controls (AddLS c)
    instance Controls c => Controls (NewLS c)
    instance Controls c => Controls (ListLS c)
    instance Controls NilLS
    instance (Controls c1,Controls c2) => Controls (TupLS c1 c2)

For every user defined control we must have instance of `Controls` class. Controls can be combined with `:+:` (`TupLS` type) and ListLS constructors. With AddLS and NewLS we can extend or change the local state of a given group of controls. NilLS specifies empty control.

Controls can be dynamically added to an existing window with `openControls` function.

    openControls :: Controls cdef => Id -> ls -> cdef ls ps -> GUI ps ()

### Common

Control attributes

    data    ControlAttribute ls ps                      -- Default:
     -- General control attributes:
     =      ControlActivate     (GUIFun ls ps)          -- return
     |      ControlDeactivate   (GUIFun ls ps)          -- return
     |      ControlFunction (GUIFun ls ps)              -- (\st->return st)
     |      ControlHide                                 -- initially visible
     |      ControlId       Id                          -- no id
     |      ControlKeyboard KeyboardStateFilter SelectState (KeyboardFunction ls ps)
                                                                                                    -- no keyboard input/overruled
     |      ControlMinimumSize  Size                    -- zero
     |      ControlModsFunction (ModifiersFunction ls ps)
                                                                                                            -- ControlFunction
     |      ControlMouse        MouseStateFilter    SelectState (MouseFunction ls ps)
                                                                                            -- no mouse input/overruled
     |      ControlPen          [PenAttribute]          -- default pen attributes
     |      ControlPos          ItemPos                 -- (RightTo previous,zero)
     |      ControlResize       ControlResizeFunction   -- no resize
     |      ControlSelectState  SelectState             -- control Able
     |      ControlTip          String                  -- no tip
     |      ControlWidth        ControlWidth            -- system derived
     --     For CompoundControls only:
     |      ControlHMargin      Int Int                 -- system dependent
     |      ControlHScroll      ScrollFunction          -- no horizontal scrolling
     |      ControlItemSpace    Int Int                 -- system dependent
     |      ControlLook         Bool Look               -- control is transparant
     |      ControlOrigin       Point2                  -- Left top of ViewDomain
     |      ControlOuterSize    Size                    -- enclose elements
     |      ControlViewDomain   ViewDomain              -- {zero,max range}
     |      ControlViewSize     Size                    -- enclose elements
     |      ControlVMargin      Int Int                 -- system dependent
     |      ControlVScroll      ScrollFunction          -- no vertical   scrolling

    type ControlResizeFunction =
            Size ->                                                 -- current control outer size
            Size ->                                                 -- old     parent  view  size
            Size ->                                                 -- new     parent  view  size
            Size                                                    -- new     control outer size

    data    RowsOrColumns
     = Rows       Int
     | Columns    Int

    data    ControlWidth                                -- The width of the control:
     =      PixelWidth   Int                            -- the exact number of pixels
     |      TextWidth    String                         -- the exact string width in dialog font
     |      ContentWidth String                         -- width of the control as if string is its content

#### Utils

    getParentWindowId :: Id -> GUI ps (Maybe Id)

    controlSize :: (Controls cdef) => cdef ls ps -> Bool -> Maybe (Int,Int) -> Maybe (Int,Int) -> Maybe (Int,Int) -> GUI ps Size

`getParentWindowId`

  returns id of parent window of control with specified Id

`controlSize`

  giving horizontal and vertical margins and item spaces calculates the size of the given control.

      theSize <- controlSize (ButtonControl "Ok" []) isWindow (Just (left, right)) (Just (top, bottom)) (Just (horz,vert))

#### Show/Hide controls

    showControls :: [Id] -> GUI ps ()
    showControl :: Id -> GUI ps ()

    hideControls :: [Id] -> GUI ps ()
    hideControl :: Id -> GUI ps ()

    setControlsShowState :: Bool -> [Id] -> GUI ps ()

    getControlShowStates :: [Id] -> GUI ps [(Bool,Bool)]
    getControlShowState :: Id -> GUI ps (Bool,Bool)

`showControls`,`showControl`

  shows a given control or a set of controls

`hideControls`,`hideControl`

  hides a given control or a set of controls

`setControlsShowState`

  shows or hides a given set of controls according to the given boolean parameter

`getControlShowStates`,`getControlShowState`

  returns current show state of the given control or set of controls

#### Enabling/Disabling of controls

    enableControls :: [Id] -> GUI ps ()
    enableControl :: Id -> GUI ps ()

    disableControls :: [Id] -> GUI ps ()
    disableControl :: Id -> GUI ps ()

    getControlSelectStates :: [Id] -> GUI ps [(Bool,SelectState)]
    getControlSelectState :: Id -> GUI ps (Bool,SelectState)

`enableControls`,`enableControl`

  enables given control or set of controls

`disableControls`,`disableControl`

  disables given control or set of controls

`getControlSelectStates`,`getControlSelectState`

  returns current select state of given control or set of controls

#### Getting and setting text of EditControl, TextControl and ButtonControl

    setControlTexts :: [(Id,String)] -> GUI ps ()
    setControlText :: Id -> String -> GUI ps ()

    getControlTexts :: [Id] -> GUI ps [(Bool,Maybe String)]
    getControlText :: Id -> GUI ps (Bool,Maybe String)

`setControlTexts`, `setControlText`

  Change the text of given control or set of controls.

`getControlTexts`, `getControlText`

  returns the text of given control or set of controls.

#### Drawing in CustomControl, CustomButtonControl and CompoundControl

    drawInControl :: Id -> Draw x -> GUI ps (Maybe x)

    updateControl :: Id -> Maybe ViewFrame -> GUI ps ()

    setControlLooks :: [(Id,Bool,(Bool,Look))] -> GUI ps ()
    setControlLook :: Id -> Bool -> (Bool,Look) -> GUI ps ()

    getControlLooks :: [Id] -> GUI ps [(Bool,Maybe (Bool,Look))]
    getControlLook :: Id -> GUI ps (Bool,Maybe (Bool,Look))

`setControlLooks`, `setControlLook`

  change the Look of the corresponding control or set of controls but redraw only if the first boolean parameter is True

`getControlLooks`, `getControlLook`

  returns current controls look

`drawInControl`

  direct draw in control

`updateControl`

  update look of control

See for details about drawing.

#### Positioning and resizing of controls

    setControlPos :: Id -> [(Id,ItemPos)] -> GUI ps Bool

    getControlViewSizes :: [Id] -> GUI ps [(Bool,Size)]
    getControlViewSize :: Id -> GUI ps (Bool,Size)

    getControlOuterSizes :: [Id] -> GUI ps [(Bool,Size)]
    getControlOuterSize :: Id -> GUI ps (Bool,Size)

    getControlMinimumSizes :: [Id] -> GUI ps [(Bool,Maybe Size)]
    getControlMinimumSize :: Id -> GUI ps (Bool,Maybe Size)

    getControlResizes :: [Id] -> GUI ps [(Bool,Maybe ControlResizeFunction)]
    getControlResize :: Id -> GUI ps (Bool,Maybe ControlResizeFunction)

`setControlPos`

  repositions control to given position

`getControlViewSizes`, `getControlViewSize`

  returns current view size

`getControlOuterSizes`, `getControlOuterSize`

  returns current view size including the size of border

`getControlMinimumSizes`, `getControlMinimumSize`

  returns the minimal valid size when resizing

`getControlResizes`, `getControlResize`

  returns the control resizing function. When the parent window of a given control is resized, then the control can be resized if it has a resize function.

### ButtonControl

Data definition

    data    ButtonControl ls ps
     =      ButtonControl String                                                    [ControlAttribute ls ps]

describes how to get or set the caption of a button

### CheckControl

Data definition

    data    CheckControl  ls ps
      =     CheckControl  [CheckControlItem ps (ls,ps)]  RowsOrColumns              [ControlAttribute ls ps]

    type    CheckControlItem ps st = (String, Maybe ControlWidth, MarkState, st -> GUI ps st)

Access functions:

    setControlsMarkState :: MarkState -> Id -> [Index] -> GUI ps ()
    markCheckControlItems :: Id -> [Index] -> GUI ps ()
    unmarkCheckControlItems :: Id -> [Index] -> GUI ps ()

    getCheckControlItems :: [Id] -> GUI ps [(Bool,Maybe [String])]
    getCheckControlItem :: Id -> GUI ps (Bool,Maybe [String])

    getCheckControlSelections :: [Id] -> GUI ps [(Bool,Maybe [Index])]
    getCheckControlSelection :: Id -> GUI ps (Bool,Maybe [Index])

`setControlsMarkState`

  This function is used for marking/unmarking of the check control according to the MarkState value.

`markCheckControlItems`

  This function is used for marking of check controls.

      markCheckControlItems = setControlsMarkState Mark

`unmarkCheckControlItems`

  This function is used for unmarking of check controls.

      unmarkCheckControlItems = setControlsMarkState Unmark

`getCheckControlItems`, `getCheckControlItem`

  returns the list of items for a given control or set of controls

`getCheckControlSelections`, `getCheckControlSelection`

  returns a the list of indexes for selected items

### CompoundControl

The compound control is a control that contains other controls. It introduces a new layout scope like LayoutControl (see ) but it provides programmers with a lot more functionality. Just like the windows, the compound controls have a view domain and can have its own Look function. If we add ControlHScroll or ControlVScroll then the control will be decorated with scroll bars.

Data definition

    data    CompoundControl c ls ps
     =      CompoundControl (c ls ps)                                               [ControlAttribute ls ps]

Access functions:

    getControlViewFrame :: Id -> GUI ps (Bool,Maybe ViewFrame)
    getControlViewFrames :: [Id] -> GUI ps [(Bool,Maybe ViewFrame)]

    moveControlViewFrame :: Id -> Vector2 -> GUI ps ()

    setControlViewDomain :: Id -> ViewDomain -> GUI ps ()

    getControlViewDomain :: Id -> GUI ps (Bool,Maybe ViewDomain)
    getControlViewDomains :: [Id] -> GUI ps [(Bool,Maybe ViewDomain)]

    setControlScrollFunction :: Id -> Direction -> ScrollFunction -> GUI ps ()

    getControlScrollFunction ::   Id  -> GUI ps  (Bool,Maybe ((Direction,Maybe ScrollFunction),(Direction,Maybe ScrollFunction)))
    getControlScrollFunctions :: [Id] -> GUI ps [(Bool,Maybe ((Direction,Maybe ScrollFunction),(Direction,Maybe ScrollFunction)))]

    openCompoundControls :: Controls cdef => Id -> ls -> cdef ls ps -> GUI ps ()

`getControlViewFrames`, `getControlViewFrame`

  `ViewFrame` is the current visible `Rectangle` of CompoundControl. When there are horizontal and vertical scroll bars then the changing of the scroller thumb will change the ViewFrame.

`moveControlViewFrame :: Id -> Vector2 -> GUI ps ()`

  moves the `ViewFrame` of the CompoundControl in the direction of the given vector.

`getControlViewDomains`, `getControlViewDomain`

  `ViewDomain` is the `Rectangle`, which specifies the logical drawing area of the CompoundControl.

`setControlViewDomain :: Id -> ViewDomain -> GUI ps ()`

  sets a new view domain of the CompoundControl.

`setControlScrollFunction :: Id -> Direction -> ScrollFunction -> GUI ps ()`

  sets a new scroll function of the CompoundControl.

`getControlScrollFunction`, `getControlScrollFunctions`

  getControlScrollFunction(s) yields the ScrollFunctions of the indicated CompoundControl. If the given control is not a CompoundControl, then Nothing is returned.

`openCompoundControls :: Controls cdef => Id -> ls -> cdef ls ps -> GUI ps ()`

  `openCompoundControls` adds controls to the indicated CompoundControl.

describes how to draw inside the CompoundControl

### CustomButtonControl

`CustomButtonControl` is like the ButtonControl but has its own Look and doesn't accept the ControlTitle attribute

    data    CustomButtonControl ls ps
     =      CustomButtonControl Size Look [ControlAttribute ls ps]

describes how to draw inside the CustomButtonControl

### CustomControl

`CustomControl` allows the programmer to design his/her own controls.

    data    CustomControl       ls ps
     =      CustomControl Size Look [ControlAttribute ls ps]

describes how to draw inside the CustomControl

### EditControl

Data definition

    data EditControl   ls ps
      =      EditControl   String ControlWidth NrLines [ControlAttribute ls ps]

    type NrLines = Int

Access functions

    setEditControlCursor :: Id -> Int -> GUI ps ()

    getControlNrLines :: [Id] -> GUI ps [(Bool,Maybe NrLines)]
    getControlNrLine :: Id -> GUI ps (Bool,Maybe NrLines)

`setEditControlCursor`

  sets the cursor position

`getControlsNrLines`, `getControlNrLines`

  returns the number of lines that can be seen (on the screen at the moment) for a given control

describes how to get or set the text of an edit control

### LayoutControl

The layout control is a control that contains other controls. It introduces a new layout scope: i.e. the controls inside it are positioned in relation to the bounds of the layout control.

    data    LayoutControl     c ls ps
     =      LayoutControl     (c ls ps)                                             [ControlAttribute ls ps]

### PopUpControl

Data definition

    data    PopUpControl    ls ps
      =     PopUpControl    [PopUpControlItem ps (ls,ps)] Index                     [ControlAttribute ls ps]
    type    PopUpControlItem ps st = (String,                                st -> GUI ps st)

Access functions

    openPopUpControlItems :: Id -> Index -> [PopUpControlItem ps ps] -> GUI ps ()

    closePopUpControlItems :: Id -> [Index] -> GUI ps ()

    selectPopUpControlItem :: Id -> Index -> GUI ps ()

    getPopUpControlItems :: [Id] -> GUI ps [(Bool,Maybe [String])]
    getPopUpControlItem :: Id -> GUI ps (Bool,Maybe [String])

    getPopUpControlSelections :: [Id] -> GUI ps [(Bool,Maybe Index)]
    getPopUpControlSelection :: Id -> GUI ps (Bool,Maybe Index)

`openPopUpControlItems`

  `openPopUpControlItems` adds items to the PopUpControl.

`closePopUpControlItems`

  deletes a string in the list box of a popup control.

`selectPopUpControlItem`

  selects a string in the list box of a popup control. If necessary, the list box scrolls the string into view (if the list box is visible). Any previous selection in the control is removed.

`getPopUpControlsItems`, `getPopUpControlItems`

  returns a list of control items

`getPopUpControlsSelection`, `getPopUpControlSelection`

  Call this function to determine which item in the popup control is selected. It returns an index into the list.

### RadioControl

Data definition

    data    RadioControl    ls ps
      =     RadioControl    [RadioControlItem ps (ls,ps)] RowsOrColumns Index       [ControlAttribute ls ps]

    type    RadioControlItem ps st = (String, Maybe ControlWidth,            st -> GUI ps st)

Access functions

    selectRadioControlItem :: Id -> Index -> GUI ps ()

    getRadioControlSelections :: [Id] -> GUI ps [(Bool,Maybe Index)]
    getRadioControlSelection :: Id -> GUI ps (Bool,Maybe Index)

    getRadioControlItems :: [Id] -> GUI ps [(Bool,Maybe [String])]
    getRadioControlItem :: Id -> GUI ps (Bool,Maybe [String])

`selectRadioControlItem`

  sets a current selection of a radio control

`getRadioControlSelections`, `getRadioControlSelection`

  returns the current control selection

`getRadioControlItems`, `getRadioControlItem`

  returns the list of control items

### SliderControl

Data definition

    data    SliderControl   ls ps
     =      SliderControl   Direction ControlWidth SliderState  (SliderAction  ls ps) [ControlAttribute ls ps]

Access functions

    setSliderStates :: [(Id,IdFun SliderState)] -> GUI ps ()
    setSliderState :: Id -> IdFun SliderState -> GUI ps ()

    setSliderThumbs :: [(Id,Int)] -> GUI ps ()
    setSliderThumb :: Id -> Int -> GUI ps ()

    getSliderStates :: [Id] -> GUI ps [(Bool,Maybe SliderState)]
    getSliderState :: Id -> GUI ps (Bool,Maybe SliderState)

    getSliderDirections :: [Id] -> GUI ps [(Bool,Maybe Direction)]
    getSliderDirection :: Id -> GUI ps (Bool,Maybe Direction)

`setSliderStates`, `setSliderState`

  changes the SliderState and redraws the settings of the SliderControls.

`setSliderThumbs`, `setSliderThumb`

  changes the thumb values of the SliderState of SliderControl or a set of controls.

`getSliderStates`, `getSliderState`

  gets a current SliderState.

`getSliderDirections`, `getSliderDirection`

  gets the slider direction i. e. Horizontal or Vertical.

### TextControl

This is a simple control that just displays its caption. In is described how to change the caption.

    data    TextControl   ls ps
     =      TextControl   String                                                    [ControlAttribute ls ps]

### Controls closing

    closeControls :: Id -> [Id] -> Bool -> GUI ps ()

    closeAllControls :: Id -> GUI ps ()

`closeControls`

  closes the specified controls in the indicated window.

`closeAllControls`

  closes all controls in the indicated window.

## StdKey

Keyboard event handlers receive KeyboardState (see for definition) as a parameter. When the special key (like F1, F2, PgUp, PgDn and other) is pressed, then the KeyboardState contains a value of `SpecialKey` type. Here is a list of all predefined values:

    backSpaceKey, beginKey, clearKey, deleteKey, downKey, endKey, enterKey,
    escapeKey, f1Key, f2Key, f3Key, f4Key, f5Key, f6Key, f7Key, f8Key,
    f9Key, f10Key, f11Key, f12Key, f13Key, f14Key, f15Key, helpKey,
    leftKey, pgDownKey, pgUpKey, rightKey, upKey :: SpecialKey

## StdPicture

While drawing we need the current state called `Picture` state. The functions that are used for drawing need a `Picture` state as an argument and return the new updated state. The Draw monad is defined so that it would be easier for the user to write the functions. The Draw monad is in fact an IO monad, but it also takes care of the management of the `Picture` state. The definition of Draw is abstract

    newtype Draw

    instance Monad Draw
    instance Functor Draw
    instance IOMonad Draw

See for definition of IOMonad class.

There are some basic objects related to the drawing:

### Pen

    data    PenAttribute                                    -- Default:
            = PenSize       Int                             -- 1
            | PenPos        Point2                          -- zero
            | PenColour     Colour                          -- Black
            | PenBack       Colour                          -- White
            | PenFont       Font                            -- defaultFont

    setPenAttributes :: [PenAttribute] -> Draw ()
    getPenAttributes :: Draw [PenAttribute]

    setPenPos :: Point2 -> Draw ()
    getPenPos :: Draw Point2

    class MovePen f where
            movePenPos :: f -> Draw ()

    instance MovePen Vector2
    instance MovePen Curve

    setPenSize :: Int -> Draw ()
    getPenSize :: Draw Int
    setDefaultPenSize :: Draw ()

    setPenColour :: Colour -> Draw ()
    getPenColour :: Draw Colour
    setDefaultPenColour :: Draw ()

    setPenBack :: Colour -> Draw ()
    getPenBack :: Draw Colour
    setDefaultPenBack :: Draw ()

    setPenFont :: Font -> Draw ()
    getPenFont :: Draw Font
    setDefaultPenFont :: Draw ()

`setPenPos`

  corresponds to the PenPos attribute. The function moves the pen to the given position.

`getPenPos`

  corresponds to the PenPos attribute. The function returns the current pen position.

`class MovePen`

  With this class the pen position can be moved in the direction of any linear graphical object. There is instances:

      instance MovePen Vector2
      instance MovePen Oval

  where Oval is defined in .

`setPenSize`

  corresponds to the PenSize attribute. The function sets the new pen size.

`getPenSize`

  corresponds to the PenSize attribute. The function returns the current pen size.

`setDefaultPenSize`

  corresponds to the PenSize attribute. The function sets the pen size to 1.

`setPenColour`

  corresponds to the PenColour attribute. The function sets the new pen colour.

`getPenColour`

  corresponds to the PenColour attribute. The function returns the current pen colour.

`setDefaultPenColour`

  corresponds to the PenColour attribute. The function sets the pen colour to Black.

`setPenBack`

  corresponds to the PenBack attribute. The function sets the new pen background colour.

`getPenBack`

  corresponds to the PenBack attribute. The function returns the current pen background colour.

`setDefaultPenBack`

  corresponds to the PenBack attribute. The function sets the pen background colour to White.

`setPenFont`

  corresponds to the PenFont attribute. The function sets the new pen font.

`getPenFont`

  corresponds to the PenFont attribute. The function returns the current pen font.

`setDefaultPenFont`

  corresponds to the PenFont attribute. The function sets the pen font to the system dependent default font.

`setPenAttributes`

  setups the pen attributes by a list of values.

`getPenAttributes`

  returns the current pen attributes as a list of values.

### Font

    data Font -- abstract

    data    FontDef
            = FontDef
                    { fName           :: !FontName          -- Name of the font
                    , fStyles         :: ![FontStyle]       -- Stylistic variations
                    , fSize           :: !FontSize          -- Size in points
                    }

    type    FontName  = String
    type    FontStyle = String
    type    FontSize  = Int

    data    FontMetrics
            = FontMetrics
                    { fAscent         :: !Int               -- Distance between top    and base line
                    , fDescent        :: !Int               -- Distance between bottom and base line
                    , fLeading        :: !Int               -- Distance between two text lines
                    , fMaxWidth       :: !Int               -- Max character width including spacing
                    }

    openFont :: FontDef -> Draw (Maybe Font)
    openDefaultFont :: Draw Font
    openDialogFont :: Draw Font

    getFontNames :: Draw [FontName]

    getFontStyles :: FontName -> Draw [FontStyle]

    getFontSizes :: Int -> Int -> FontName -> Draw [FontSize]

    getFontDef :: Font -> FontDef

    getFontCharWidth :: Font -> Char -> Draw Int
    getFontCharWidths :: Font -> [Char] -> Draw [Int]
    getFontStringWidth :: Font -> String -> Draw Int
    getFontStringWidths :: Font -> [String] -> Draw [Int]
    getFontMetrics :: Font -> Draw FontMetrics

    getPenFontCharWidth :: Char -> Draw Int
    getPenFontCharWidths :: [Char] -> Draw [Int]
    getPenFontStringWidth :: String -> Draw Int
    getPenFontStringWidths :: [String] -> Draw [Int]
    getPenFontMetrics :: Draw FontMetrics

`openFont`

  creates a font with name, size and styles defined in the `FontDef` parameter.

`openDefaultFont`

  creates the system dependent default font.

`openDialogFont`

  creates a font with the same parameters that are used for the system font for dialogs.

`getFontNames`

  returns a list of names for all existing fonts.

`getFontStyles`

  returns a list of all existing styles for a given font.

`getFontSizes sizeBound1 sizeBound2`

  returns a list of all existing sizes between sizeBound1 and sizeBound2 for a given font.

`getFontDef`

  extracts the font definition from a given font.

`getFontCharWidth`, `getFontCharWidths`

  calculates the single char width(s) for a given font

`getFontStringWidth`, `getFontStringWidths`

  calculates the string width(s) for a given font

`getFontMetrics`

  returns FontMetrics data for a given font

`getPenFontCharWidth`, `getPenFontCharWidths`

  calculates the single char width(s) for the active font

`getPenFontStringWidth`, `getPenFontStringWidths`

  calculates the string width(s) for the active font

`getPenFontMetrics`

  returns FontMetrics data for the active font

### Drawables,Fillables and Hilites

Basic graphical objects such as line,circle and point are defined in the system. The user can define his/her own shape types. There are three classes which allow user to define the graphical view of his/her shapes.

    class Drawables figure where
            draw    :: figure -> Draw ()
            drawAt  :: Point2 -> figure -> Draw ()
            undraw  :: figure -> Draw ()
            undrawAt:: Point2 -> figure -> Draw ()

    class Fillables figure where
            fill    :: figure -> Draw ()
            fillAt  :: Point2 -> figure -> Draw ()
            unfill  :: figure -> Draw ()
            unfillAt:: Point2 -> figure -> Draw ()

    class Hilites figure where
            hilite  :: figure -> Draw ()
            hiliteAt:: Point2 -> figure -> Draw ()

This is a list of all built-in shapes.

    data    Line2                                           -- A line connects two points
            = Line2
                    { line_end1       :: !Point2            -- The first  point
                    , line_end2       :: !Point2            -- The second point
                    }
    data    Oval                                            -- An oval is a stretched unit circle
            = Oval
                    { oval_rx         :: !Int               -- The horizontal radius (stretch)
                    , oval_ry         :: !Int               -- The vertical   radius (stretch)
                    }
    data    Curve                                           -- A curve is a slice of an oval
            = Curve
                    { curve_oval      :: !Oval              -- The source oval
                    , curve_from      :: !Float             -- Starting angle (in radians)
                    , curve_to        :: !Float             -- Ending   angle (in radians)
                    , curve_clockwise :: !Bool              -- Direction: True iff clockwise
                    }
    data    Box                                             -- A box is a rectangle
            = Box
                    { box_w           :: !Int               -- The width  of the box
                    , box_h           :: !Int               -- The height of the box
                    }
    data    Polygon                                         -- A polygon is an outline shape
            = Polygon
                    { polygon_shape   :: ![Vector2]         -- The shape of the polygon
                    }

Instances for Drawables:

    instance Drawables Char
    instance Drawables String
    instance Drawables Vector2
    instance Drawables Rectangle
    instance Drawables Line2
    instance Drawables Oval
    instance Drawables Curve
    instance Drawables Box
    instance Drawables Polygon

Instances for Fillables:

    instance Fillables Rectangle
    instance Fillables Oval
    instance Fillables Curve
    instance Fillables Box
    instance Fillables Polygon

Instances for Hilites:

    instance Hilites Box where
    instance Hilites Rectangle where

## StdBitmap

    data Bitmap     -- abstract

    openBitmap :: FilePath -> IO (Maybe Bitmap)
    disposeBitmap :: Bitmap -> IO ()

    getBitmapSize :: Bitmap -> Size
    resizeBitmap :: Size -> Bitmap -> Bitmap

    instance Drawables Bitmap

`openBitmap`

  creates a bitmap from the given file name.

`disposeBitmap`

  Warning:Allways dispose of the bitmap when it is no longer needed.

`getBitmapSize`

  returns the current bitmap size.

`resizeBitmap`

  resizes the bitmap. The resizing of the bitmap affects only the data that is in the memory. The visual effect will appear when the bitmap is displayed.

## StdProcess

In Object I/O there are multiple interactive processes. Each process has its main window and works independently from the other processes.

Note: The interactive process isn't a thread. The multiple processes just denote multiple main windows.

The behaviour of the process is determined by document interface (see for definition of DocumentInterface type):

- SDI process can have just one window

- MDI process has one main window with multiple child windows

- NDI process can't have windows. It can work only with dialogs

The process is defined as type:

    data Process
            = forall ps . Process
                            DocumentInterface       -- The process document interface
                            ps                      -- The process private state
                            (ProcessInit ps)        -- The process initialisation
                            [ProcessAttribute ps]   -- The process attributes
    type    ProcessInit ps
            = GUI2Fun ps

    data    ProcessAttribute ps                  -- Default:
        = ProcessActivate   (GUI2Fun ps)        -- No action on activate
        | ProcessDeactivate (GUI2Fun ps)        -- No action on deactivate
        | ProcessClose      (GUI2Fun ps)        -- Process is closed
    --  Attributes for (M/S)DI process only:
        | ProcessOpenFiles  (ProcessOpenFilesFunction ps)    -- Request to open files
        | ProcessWindowPos  ItemPos              -- Platform dependent
        | ProcessWindowSize Size                 -- Platform dependent
        | ProcessWindowResize   (ProcessWindowResizeFunction ps) -- Platform dependent
        | ProcessToolbar    [ToolbarItem ps]         -- Process has no toolbar
     -- Attributes for MDI processes only:
        | ProcessNoWindowMenu                    -- Process has WindowMenu

    type    ProcessWindowResizeFunction ps
         =  Size                        -- Old ProcessWindow size
         -> Size                        -- New ProcessWindow size
         -> GUI2Fun ps

    type    ProcessOpenFilesFunction ps
         =  [String]                    -- The file names to open
         -> GUI2Fun ps

    data    ToolbarItem ps
        = ToolbarItem Bitmap (Maybe String) (ps -> GUI ps ps)
        | ToolbarSeparator

    class Processes pdef where
            startProcesses :: pdef -> IO ()
            openProcesses  :: pdef -> GUI ps ()

    instance Processes Process
    instance Processes pdef => Processes [pdef]

    startIO :: DocumentInterface -> ps -> ProcessInit ps -> [ProcessAttribute ps] -> IO ()

    closeProcess :: GUI2Fun ps

    getProcessWindowPos :: GUI ps Point2
    getProcessWindowSize :: GUI ps Size

Process attributes

`ProcessActivate`

  describes a callback function, which will be called each time the process is activated.

`ProcessDeactivate`

  describes a callback function, which will be called each time the process is deactivated.

`ProcessClose`

  describes a callback function, which will be called before the process is closed.

`ProcessOpenFiles`

  describes a callback function, which will be called when the user drags files from the Windows Explorer and drops them over the process window (for (M/S)DI processes only).

`ProcessWindowPos`

  defines the position in which the main process window will be created (for (M/S)DI processes only).

`ProcessWindowSize`

  defines the size of the main process window when it is created (for (M/S)DI processes only).

`ProcessWindowResize`

  describes the callback function which will be called when the user resizes the process window (for (M/S)DI processes only).

`ProcessToolbar`

  defines the process toolbar items (for (M/S)DI process only).

`ProcessNoWindowMenu`

  prevents the creation of a standard "Window" menu (for MDI processes only).

The processes can be created by `Processes` class. This allows the user to define his/her own process types instead of built-in types

`startIO`

  This is the standard way for a single processed applications to run.

      main = startIO SDI () init [ProcessClose closeProcess
              where
                      init :: GUI2Fun ps
                      init = ...

`closeProcess`

  closes the current process

`getProcessWindowPos`

  returns the system dependent position where the process window is created

`getProcessWindowSize`

  returns the system dependent size with which the process window will be created.

## StdReceiver

The receiver is a component which allows the communication between different interactive process or between different devices (For example from Timer device to Menu device) by user defined message events

There are two kinds of receivers:

- Uni-directional (defined as Receiver type) receivers cannot respond to messages;

- Bi-directional (defined as Receiver2 type) receivers respond to messages and return a result.

    data    Receiver         m ls ps = Receiver (RId m) (ReceiverFunction m ls ps) [ReceiverAttribute ls ps]
    type    ReceiverFunction m ls ps = m -> GUIFun ls ps

    data    Receiver2         m r ls ps = Receiver2 (R2Id m r) (Receiver2Function m r ls ps) [ReceiverAttribute ls ps]
    type    Receiver2Function m r ls ps = m -> (ls,ps) -> GUI ps (r,(ls,ps))

    data    ReceiverAttribute ls ps                         -- Default:
     =      ReceiverInit               (GUIFun ls ps)       -- no actions after opening receiver
     |      ReceiverSelectState        SelectState          -- receiver Able

    class Receivers rdef where
            openReceiver :: ls -> rdef ls ps -> ps -> GUI ps ps

    instance Receiver (Receiver  m)
    instance Receiver (Receiver2 m r)

    closeReceiver :: Id -> GUI ps ()

    getReceivers :: GUI ps [Id]

    enableReceivers :: [Id] -> GUI ps ()
    disableReceivers :: [Id] -> GUI ps ()
    getReceiverSelectState :: Id -> GUI ps (Maybe SelectState)

    asyncSend :: RId msg -> msg -> GUI ps ()
    syncSend :: RId msg -> msg -> ps -> GUI ps ps
    syncSend2 :: R2Id msg resp -> msg -> ps -> GUI ps (resp,ps)

Receivers can be created `Receivers` class. This allows user to define his/her own receiver types instead of built-in types

`closeReceiver`

  closes the receiver with the specified id

`getReceivers`

  returns the list of all existing receivers for an active process

`enableReceivers`

  enables message handling for the specified receivers

`disableReceivers`

  disables message handling for the specified receivers

`getReceiverSelectState`

  returns the current select state for the specified receiver.

`asyncSend`

  sends an asynchronous message to the receiver.

`syncSend`

  sends a synchronous message to the receiver.

`syncSend2`

  sends a synchronous message to the bi-receiver and returns the response from the receiver message handler.

## StdControlReceiver, StdMenuReceiver, StdTimerReceiver

Receivers can be inluded as a part of the definition of windows, menus or timers. This is done with the following instance definitions and allows inter device communication.

    instance Controls (Receiver  m)
    instance Controls (Receiver2 m r)

    instance MenuElements (Receiver  m)
    instance MenuElements (Receiver2 m r)

    instance TimerElements (Receiver  m)
    instance TimerElements (Receiver2 m r)

See , and for class definitions.

## StdMenu

### Definition

    --      Menus:

    data    Menu        m ls ps = Menu        Title         (m ls ps)        [MenuAttribute ls ps]
    data    PopUpMenu   m ls ps = PopUpMenu                 (m ls ps)

    --      Menu elements:

    data    MenuItem      ls ps = MenuItem    Title                            [MenuAttribute ls ps]
    data    MenuSeparator ls ps = MenuSeparator                                [MenuAttribute ls ps]
    data    RadioMenu     ls ps = RadioMenu   [MenuRadioItem (ls,ps) ps] Index [MenuAttribute ls ps]
    data    SubMenu     m ls ps = SubMenu     Title        (m ls ps)           [MenuAttribute ls ps]

    type    MenuRadioItem st ps = (Title,Maybe Id,Maybe Char,st -> GUI ps st)

    data    MenuAttribute ls ps                                                     -- Default:
     --     Attributes for Menus and MenuElements:
            =       MenuId                  Id                                      -- no Id
            |       MenuSelectState         SelectState                             -- menu(item) Able
     --     Attributes only for Menus:
            |       MenuIndex               Int                                     -- at the end of the current menu list
            |       MenuInit                (ps -> GUI ps ps)                       -- no actions after opening menu
     --     Attributes ignored by (Sub)Menus:
            |       MenuFunction            (GUIFun ls ps)                          -- return
            |       MenuMarkState           MarkState                               -- NoMark
            |       MenuModsFunction        (ModifiersFunction ls ps)               -- MenuFunction
            |       MenuShortKey            Char                                    -- no ShortKey

    class MenuElements m where
            menuElementToHandles    :: m ls ps -> GUI ps [MenuElementState ls ps]

    class PopUpMenuElements m where
            popUpMenuElementToHandles :: m ls ps -> GUI ps [MenuElementState ls ps]

    class Menus mdef where
            openMenu :: ls -> mdef ls ps -> ps -> GUI ps ps

    instance MenuElements m => MenuElements (AddLS m)
    instance MenuElements m => MenuElements (NewLS m)
    instance MenuElements m => MenuElements (ListLS m)
    instance MenuElements NilLS
    instance (MenuElements m1, MenuElements m2) => MenuElements (TupLS m1 m2)
    instance MenuElements m => MenuElements (SubMenu m)
    instance MenuElements m => Menus (Menu m)
    instance MenuElements RadioMenu
    instance MenuElements MenuItem
    instance MenuElements MenuSeparator

    instance PopUpMenuElements m => PopUpMenuElements (AddLS m)
    instance PopUpMenuElements m => PopUpMenuElements (NewLS m)
    instance PopUpMenuElements m => PopUpMenuElements (ListLS m)
    instance PopUpMenuElements NilLS
    instance (PopUpMenuElements m1, PopUpMenuElements m2) => PopUpMenuElements (TupLS m1 m2)
    instance PopUpMenuElements m => Menus (PopUpMenu m)
    instance PopUpMenuElements RadioMenu
    instance PopUpMenuElements MenuItem
    instance PopUpMenuElements MenuSeparator

There are two kinds of menus:

- the standard menus (Menu type) are usually placed at the top of the process window and can be selected at any time;

- the popup menus (PopUpMenu type) can be created and shown at any time as a response to any other event (usually to the click of the right mouse button).

The menus have four kinds of items:

- the simple menu item (MenuItem type) is just an item with a specified title and an event handler which is called when the item is clicked;

- the menu separator (MenuSeparator type) is nonselectable item which can be used to separate menu items in different groups;

- the radio menu (RadioMenu type) is a group of items which can be used as `RadioControl`;

- the sub menu (SubMenu type) item is an item which shows a sub menu when the user selects it.

The menu items can be combined with :+: (TupLS type) and ListLS constructors. The local state for a given group of items can be extended and changed by AddLS and NewLS constructors. NilLS specifies an empty menu.

### Menu access functions

    closeMenu :: Id -> GUI ps ()

    enableMenuSystem :: GUI ps ()
    disableMenuSystem :: GUI ps ()

    enableMenus :: [Id] -> GUI ps ()
    disableMenus :: [Id] -> GUI ps ()
    getMenuSelectState :: Id -> GUI ps (Maybe SelectState)

    openMenuElements :: MenuElements m => Id -> Index -> ls -> m ls ps -> GUI ps ()
    openSubMenuElements :: MenuElements m => Id -> Index -> ls -> m ls ps -> GUI ps ()
    openRadioMenuItems :: Id -> Index -> [MenuRadioItem ps ps] -> GUI ps ()

    closeMenuElements :: Id -> [Id] -> GUI ps ()
    closeMenuIndexElements :: Id -> [Index] -> GUI ps ()
    closeSubMenuIndexElements :: Id -> [Index] -> GUI ps ()
    closeRadioMenuIndexElements :: Id -> [Index] -> GUI ps ()

    getMenus :: GUI ps [Id]

    getMenuPos :: Id -> GUI ps (Maybe Index)

    setMenuTitle :: Id -> Title -> GUI ps ()
    getMenuTitle :: Id -> GUI ps (Maybe Title)

`closeMenu`

  closes the specified menu.

`enableMenuSystem`

  enables all menus.

`disableMenuSystem`

  disables all menus.

`enableMenus`

  enables the menus with the specified Ids.

`disableMenus`

  disables the menus with the specified Ids.

`getMenuSelectState`

  returns `SelectState` of the specified menu.

`openMenuElements`

  dynamically creates additional elements to the specified menu.

`openSubMenuElements`

  dynamically creates additional elements to the specified sub menu (here the Id is an Id of the sub menu).

`openRadioMenuItems`

  dynamically creates additional radio menu elements.

`closeMenuElements`

  closes the elements with specified Ids from the specified menu.

`closeMenuIndexElements`

  closes the elements with specified indexes from the specified menu.

`closeSubMenuIndexElements`

  closes the elements with specified indexes from the specified sub menu.

`closeRadioMenuIndexElements`

  closes the radio menu elements with specified indexes from the specified menu.

`getMenus`

  returns the list of ids of all existing menus for the current process.

`getMenuPos`

  returns the menu item index from the item Id.

`setMenuTitle`

  sets the menu title.

`getMenuTitle`

  returns the menu title.

### Menu elements access functions

#### Enable/Disable menu items

    enableMenuElements :: [Id] -> GUI ps ()
    disableMenuElements :: [Id] -> GUI ps ()

    getMenuElementSelectStates :: Id -> [Id] -> GUI ps [(Bool,SelectState)]
    getMenuElementSelectState :: Id -> Id -> GUI ps (Bool,SelectState)

#### Mark/Unmark menu items

Just like CheckControl, the menu items also can be checked and unchecked.

    markMenuItems :: [Id] -> GUI ps ()
    unmarkMenuItems :: [Id] -> GUI ps ()

    getMenuElementMarkStates :: Id -> [Id] -> GUI ps [(Bool,MarkState)]
    getMenuElementMarkState :: Id -> Id -> GUI ps (Bool,MarkState)

#### Getting and setting of menu item titles

    setMenuElementTitles :: [(Id,Title)] -> GUI ps ()

    getMenuElementTitles :: Id -> [Id] -> GUI ps [(Bool,Maybe String)]
    getMenuElementTitle :: Id -> Id -> GUI ps (Bool,Maybe String)

#### Radio menu items selection

Radio menu is just like `RadioControl`. Only one item from the radio menu can be selected at a certain time.

    selectRadioMenuItem :: Id -> Id -> GUI ps ()
    selectRadioMenuIndexItem :: Id -> Index -> GUI ps ()

    getSelectedRadioMenuItems :: Id -> [Id] -> GUI ps [(Index,Maybe Id)]
    getSelectedRadioMenuItem :: Id -> Id -> GUI ps (Index,Maybe Id)

#### Menu elements access functions

    getMenuElementShortKeys :: Id -> [Id] -> GUI ps [(Bool,Maybe Char)]
    getMenuElementShortKey :: Id -> Id -> GUI ps (Bool,Maybe Char)

`getMenuElementShortKeys`, `getMenuElementShortKey`

  returns the shortcut key associated with the menu element.

## StdTimer

The timer is a device with a specified event handler, which is called at a fixed time interval.

    data Timer t ls ps = Timer TimerInterval (t ls ps) [TimerAttribute ls ps]

    type TimerInterval = Int

    data TimerAttribute ls ps                                       -- Default:
            = TimerFunction         (TimerFunction ls ps)           -- \_ x->x
            | TimerId               Id                              -- no Id
            | TimerInit             (GUIFun ls ps)                  -- no actions after opening timer
            | TimerSelectState      SelectState                     -- timer Able

    type TimerFunction ls ps = NrOfIntervals -> GUIFun ls ps
    type NrOfIntervals = Int

    class Timers tdef where
            openTimer :: ls -> tdef ls ps -> ps -> GUI ps ps

    instance TimerElements t => Timers (Timer t)

    closeTimer :: Id -> GUI ps ()

    getTimers :: GUI ps [Id]

    enableTimer :: Id -> GUI ps ()
    disableTimer :: Id -> GUI ps ()
    getTimerSelectState :: Id -> GUI ps (Maybe SelectState)

    setTimerInterval :: Id -> TimerInterval -> GUI ps ()
    getTimerInterval :: Id -> GUI ps (Maybe TimerInterval)

Timers can be created by `Timers` class. This allows the user to define his/her own timer types instead of built-in types

`closeTimer`

  closes the timer with the specified Id

`getTimers`

  returns the list of Ids of all existing timers for the current process.

`enableTimer`

  enables the timer with the specified Id

`disableTimer`

  disables the timer with the specified Id

`getTimerSelectState`

  returns the current `SelectState` for timer with the specified Id. `SelectState` can be changed by `enableTimer` and `disableTimer` functions.

`setTimerInterval`

  sets the timer interval

`getTimerInterval`

  returns the current timer interval

## StdFileSelect

    selectInputFile :: ps -> GUI ps (Maybe FilePath, ps)

    selectOutputFile :: String -> String -> ps -> GUI ps (Maybe FilePath, ps)

    selectDirectory :: ps -> GUI ps (Maybe FilePath, ps)

`selectInputFile`

  opens a dialog for file selecting and returns the selected file name. If the file doesn't exist, the function shows a popup message box with a warning message.

`selectOutputFile`

  opens a dialog for file selecting and returns the selected file name. If the file already exists, the function shows a popup message box with a warning message.

`selectDirectory`

  opens a dialog for directory selecting.

## StdSound

Experimental feature! playSoundFile opens the sound file at filename and plays it synchronously. The Boolean result indicates whether the sound file could be succesfully played.

    playSoundFile :: FilePath -> IO Bool

## StdClipboard

The current clipboard implementation supports only string data type

    data ClipboardItem
            = ClipboardString String                -- Support for strings

    class Clipboard item where
            toClipboard     :: item                 -> ClipboardItem
            fromClipboard   :: ClipboardItem        -> Maybe item

    instance Clipboard String where
            toClipboard string = ClipboardString string
            fromClipboard (ClipboardString string) = Just string

    setClipboard :: [ClipboardItem] -> GUI ps ()

    getClipboard :: GUI ps [ClipboardItem]
    clipboardHasChanged :: GUI ps Bool