20.8 Guienv Interface

ORIGIN '~beta/basiclib/betaenv';
LIB_DEF 'guienv' '../lib';
INCLUDE '~beta/containers/list';
INCLUDE 'graphmath';
INCLUDE 'keys';
BODY  'private/guienvbody'
(*
 * COPYRIGHT
 *       Copyright (C) Mjolner Informatics, 1991-96
 *       All rights reserved.
 *)
-- lib: attributes --
GUIenv: 
  (# <<SLOT guienvLib: attributes>>;
     onStartApplication:< 
       (* is called when this application is started with no
        * documents. You can for example further bind this to show a
        * splash screen
        *)
       (# do INNER #);
     onOpenDocument:<
       (* is called whenever a user opens a document created by this
        * application
        *)
       (# fileName: ^text;
       enter fileName[]
       do INNER
       #);
     onQuit:<
       (* is called when application is going to quit, either
        * because terminate is called or because the system are
        * are going to shut down.
        * If okToQuit is set to false the application will
        * not quit.
        *)
       (# okToQuit: @boolean;
       do true -> okToQuit;
          INNER;
       exit okToQuit
       #);
     terminate:
       (* will terminate the entire application if invoked 
        * Terminate calls onQuit and will only quit if
        * onQuit returns true.
        *) 
       (# ... #);
     applicationMenubar:
       (* applicationMenubar is used to install a menubar with
        * functionality that is common for all parts for the
        * application.
        *)
       (# theMenubar: ^menubarType
       enter (# enter theMenubar[] ... #)
       exit (# ... exit theMenuBar[] #)
       #);
     menubarType:<
       (* if further bound, an instance of menubarType is
        * automatically installed for the application. Further bind it
        * to standardMenubar if you want the standard menubar (file
        * and edit menu)
        *)
       menubar;
     interfaceObject: 
       (* superpattern for all objects used for interaction with the
        * user
        *)
       (# <<SLOT interfaceObjectLib: attributes>>;
          theEventhandler: 
            (* The only instance of the eventhandler virtual *)
            @eventhandler;
          eventhandler:<
            (* Encapsulates the patterns related to event handling *)
            (# <<SLOT eventhandlerLib: attributes>>;
               event: 
                 (* the abstract superpattern of all events *)
                 (# <<SLOT eventLib: attributes>>;
                 ...
                 #) (* event *);
               basicEvent: event 
                 (* abstract superpattern for all events
                  * originating directly from the OS 
                  *)
                 (# <<SLOT basicEventLib: attributes>>;
                    shiftKey: booleanValue
                      (* true if the shiftkey was the down, when
                       * THIS(basicEvent) occurred
                       *) 
                      (# 
                      ...
                      #);
                    altKey: booleanValue
                      (* true if the altkey was the down, when
                       * THIS(basicEvent) occurred
                       *) 
                      (# 
                      ...
                      #);
                    metaKey: booleanValue
                      (* true if the metakey was the down, when
                       * THIS(basicEvent) occurred
                       *) 
                      (# 
                      ...
                      #);
                    controlKey: booleanValue
                      (* true if the controlkey was the down, when
                       * THIS(basicEvent) occurred
                       *)
                      (# 
                      ...
                      #);
                    buttonState: integerValue
                      (* the number designating the button, which was
                       * pressed down, when THIS(basicEvent) occurred
                       * - 0 means 'no button'.  This value depe nds
                       * on the number of buttons on the mouse -
                       * Typically 1, 2 or 3.
                       *)
                      (# 
                      ...
                      #);
                    when: integerValue
                      (* the tick count when THIS(basicEvent)
                       * occurred.  1 tick = 1/60 sec.
                       *)
                      (# 
                      ...
                      #);
                    globalPosition: 
                      (* global coordinates of the mouse, when
                       * THIS(basicEvent) occurred
                       *)
                      (# p: @point;
                      ...
                      exit p
                      #);
                    localPosition: 
                      (* local coordinates of the mouse, when
                       * THIS(basicEvent) occurred - relative to
                       * THIS(inteefaceObject)
                       *)
                      (# p: @point;
                      ...
                      exit p
                      #);
                 do INNER;
                 #);
               mouseEvent: basicEvent
                 (* abstract superpattern for events related to the
                  * mouse
                  *)
                 (# <<SLOT mouseEventLib: attributes>>;
                    doubleClick: booleanValue
                      (* true if THIS(mouseEvent) is a doubleclick.
                       * For a mouse click to qualify as doubleclick
                       * it must happen close in time and space, and
                       * with the same mouse button
                       *)
                      (# 
                      ...
                      #);
                 do INNER;
                 #);
               keyEvent: basicEvent
                 (* abstract superpattern for events related to the
                  * keyboard.
                  *)
                 (# <<SLOT keyEventLib: attributes>>;
                    ch:
                      (* the key on the keyboard, related to
                       * THIS(keyEvent)
                       *)
                      (# theChar: @char;
                      ...
                      exit theChar
                      #);
                    key:
                      (* the specialkey on the keyboard, related to
                       * THIS(keyEvent).
                       * See keys.bet for descriptions.
                       *)
                      (# theKey:@int32;
                      ...
                      exit theKey
                      #)
                 do INNER
                 #);
               mouseDown: mouseEvent
                 (* This event occurs when the user presses any mouse
                  * button down on THIS(interfaceObject)
                  *)
                 (# <<SLOT mouseDownLib: attributes>>;
                    delay:
                      (* used to wait for period ticks to pass, while
                       * mouse.isStillDown is true, and then execute
                       * INNER.  If mouseStillDown becomes false
                       * before period ticks, INNER is not executed
                       *)
                      (# period: @integer
                      enter period
                      ...
                      #)
                 do INNER
                 #);
               onMouseDown:< mouseDown;
               mouseUp: mouseEvent 
                 (* This event occurs when the user releases any
                  * mouse button after having pressed it on
                  * THIS(interfaceObject)
                  *)
                 (# do INNER #);
               onMouseUp:< mouseUp;
               keyDown: keyEvent
                 (* Occurs when the user presses a key, related to
                  * THIS(interfaceObject)
                  *)
                 (# do INNER #);
               onKeyDown:< keyDown;
               refresh: basicEvent
                 (* This event tells THIS(interfaceobject), that it
                  * needs to redraw itself. UpdateRect is the 
                  * rectangle that needs to be updated expressed
                  * in the coordinate system of this(interfaceObject).
                  *)
                 (# updateRect:
                      (# value: ^rectangle;
                      ...
                      exit value[]
                      #)
                 do INNER 
                 #);
               onRefresh:< refresh;
               activate: basicEvent
                 (* Send when THIS(interfaceObject) becomes active *)
                 (# do INNER #);
               onActivate:< activate;
               deactivate: basicEvent
                 (* Send when THIS(interfaceObject) becomes inactive
                  *)
                 (# do INNER #);
               onDeactivate:< deactivate;
            #);
          action:
            (* Actions is a means of subscribing to events.  The
             * desired event is specified by further binding
             * eventType.  Actions can be prepended or appended to
             * THIS(interfaceobject).  When some event is called, the
             * prepended actions for the event is called *before* the
             * INNER and the appended actions are called after.
             *)
            (# <<SLOT actionLib: attributes>>;
               eventType:< theEventhandler.event;
               theEvent: ^eventType;
            enter theEvent[]
            do INNER;
            #);
          prependAction:
            (* Prepends the action, so it will be executed before the
             * event is subscribes to
             *)
            (# theAction: ^action;
            enter theAction[]
            ...
            #);
          appendAction:
            (* Appends the action, so it will be executed after the
             * event is subscribes to.
             *)
            (# theAction: ^action;
            enter theAction[]
            ...
            #);
          deleteAction:
            (* Remove the action *)
            (# theAction: ^action;
            enter theAction[]
            ...
            #);
          open:< 
            (* must be called before any other operation on
             * THIS(interfaceObject).
             *)
            (# create:< (# ... #);
            ...
            #);
          close:< 
            (* closes THIS(interfaceObject) and dispose all related
             *              structures
             *)
            (# ... #);
          enableEventType:<
            (* makes THIS(interfaceObject) sensible to the specified
             * type of events
             *)
            (# ev: ##theEventhandler.event
            enter ev##
            ...
            #);
          disableEventType:<
            (* makes THIS(interfaceObject) insensible to the
             * specified type of events
             *)
            (# ev: ##theEventhandler.event
            enter ev##
            ...
            #);
          interfaceObjectException: exception
            (* abstract superpattern for exceptiosn related to
             * THIS(interfaceObject).
             *)
            (# 
            ... 
            #);
          notOpenedException: interfaceObjectException
            (# location: ^text
            enter location[]
            ...
            #);
          notOpenedError:< 
            (* this exception is raised if any operation is performed
             * on THIS(interfaceObject) is called before open is
             * called.  This will also happen if "close" is called
             * twice
             *)
            notOpenedException;
          private: @...;
       do INNER
       #) (* interfaceObject *);
     menubar: interfaceObject
       (* menubar is a bar containing the titles of the contained
        * menus. A menu is pulled down by clicking at the title,
        * allowing the user to select a menuitem in the menu.  A
        * menubar is only visible if it is installed - either as the
        * global menubar or as the menubar in some window.
        *)
       (# <<SLOT menubarLib: attributes>>;
          append: 
            (* inserts a menu after all menues in the menubar.  If
             * the menu is already in the menu bar, nothing happens
             *)
            (# theMenu: ^menu;
            enter theMenu[]
            ...
            #);
          delete: 
            (* deletes a menu from the menu bar. The menu titles
             * following the deleted menu will move over to fill the
             * vacancy
             *)
            (# theMenu: ^menu
            enter theMenu[]
            ...
            #);
          clear: 
            (* removes all menues from the menu bar when you want to
             * start with new menues
             *)
            (# ... #);
          appendMenubar: 
            (* inserts all menues in another menubar after all menues
             * in THIS(menubar).  This is the same as calling
             * insertMenubar with NONE as afterMenu.
             *)
            (# theMenubar: ^menubartype;
            enter theMenubar[]
            ...
            #);
          replaceMenubar: 
            (* replace all menues in theMenubar with all menues in
             * replacementMenubar in THIS(menubar).
             *)
            (# theMenubar, replacementMenubar: ^menubartype
            enter (theMenubar[], replacementMenubar[])
            ...
            #);
          deleteMenubar: 
            (* deletes all menues in theMenubar from
             * THIS(menubar). The menu titles following the menues in
             * the deleted menubar will move over to fill the vacancy
             *)
            (# theMenubar: ^menubartype
            enter theMenubar[]
            ...
            #);
          scan: 
            (* iterates over all menues currently inserted in the
             * menubar
             *)
            (# current: ^menu;
            ... #);
          open::<
            (# create::< (# ... #);
            ...
            #);
          close::<
            (# 
            ...
            #);
          private: @...; 
       #) (* menubar *);
     menu: interfaceObject
       (* menu contains a group of menuitems and is usefull for
        * letting the user perform commands or set settings in the
        * application. A menu can be installed in a menubar, as a
        * submenu to some menuitem or simply be popped up on the
        * screen.
        *)
       (# <<SLOT menuLib: attributes>>;
          name:
            (* the name of the menu as shown in the menubar.  if the
             * menu is not in a menubar, the name is not visible
             *)
            (# theName: ^text
            enter (# enter theName[] ... #)
            exit (# ... exit theName[] #)
            #);
          eventhandler::<
            (# select: event
                 (* executed when the user selects THIS(menu) (or
                  * pops it up) just before the menu is shown.
                  *)
                 (# do INNER #);
               onSelect:< select;
            #);
          menuitem: interfaceObject
            (* menuitem is used for letting the user perform commands
             * in the application or display the state of some option,
             * by checking and unchecking the menuitem. It can also
             * serve as the title of a submenu.
             *)
            (# <<SLOT menuitemLib: attributes>>;
               key: 
                 (* the key shortcut of THIS(menuitem), allows the
                  * user to select THIS(menuitem) without using the
                  * mouse.
                  *)
                 (# c: @char
                 enter (# enter c ... #)
                 exit (# ... exit c #)
                 #);
               specialkey:
                 (* Extendend version of key. 
                  * key is the shortcut, if less than 255 used as char. 
                  * Only one modifier at a time is supported!
                  *)
                 (# key:@integer; (* from special keys in keys.bet *)
                    ctrl,shift,alt:@boolean;
                 enter (# enter (key,shift,ctrl,alt) ... #)
                 #);
               name: 
                 (* models the name of THIS(menuitem).  Evaluate the
                  * enter-part to set the name.  Evaluate the
                  * exit-part to get the name
                  *)
                 (# t: ^text;
                 enter (# enter t[] ... #)
                 exit (# ... exit t[] #)
                 #);
               checked:
                 (* when THIS(menuitem) is checked, a check mark is
                  * displayed at the left side the menuitem
                  *)
                 (# checked: @boolean
                 enter (# enter checked ... #)
                 exit (# ... exit checked #)
                 #);
               subMenu:
                 (* if a submenu is attached to THIS(menuitem), that
                  * menu is pulled down by selecting
                  * THIS(menuitem). In that case onSelect is never
                  * issued for THIS(menuitem)
                  *)
                 (# theMenu: ^menu;
                 enter (# enter theMenu[] ... #)
                 exit (# ... exit theMenu[] #)
                 #);
               position: IntegerValue
                 (* the position of THIS(menuitem) in its menu,
                  * separator items are counted as well
                  *)
                 (# 
                 ...
                 #);
               eventhandler::<
                 (# onStatus:< booleanValue
                      (* executed just before THIS(menuitem) is
                       * shown.  should return true if THIS(menuitem)
                       * is enabled.  Default is true
                       *)
                      (# ... #);
                    select: event
                      (* executed when THIS(menuitem) is selected in
                       * the menu.  If a submenu is attached, it will
                       * not be executed - instead the submenu is
                       * pulled down
                       *)
                      (# do INNER #);
                    onSelect:< select;
                 #);
               open::<
                 (# create::< (# ... #);
                 ...
                 #);
               private: @...;
            do INNER
            #) (* menuitem *);
          dynamicMenuitem: menuitem
            (* dynamic menuitem does not call its own onStatus and
             * onSelect events, instead these events are called on the
             * attached action, if any is attached
             *)
            (# <<SLOT dynamicItemLib: attributes>>;
               theAction: ^menuAction;
               attach: 
                 (* anAction is attached to THIS(menuitem) *)
                 (# anAction: ^menuAction;
                 enter anAction[]
                 ...
                 #);
               detach:
                 (* the menuitemHandler that is currently attached to
                  * THIS(menuitem) is detached, meaning that no action
                  * is attached
                  *)
                 (# ... #);
               eventhandler::<
                 (# onStatus::< (# ... #);
                    onSelect::< (# ... #);
                 #);
            #) (* dynamicMenuitem *);
          menuAction:
            (* a menuAction can dynamicly be attached to
             * dynamicMenuitems within THIS(menu), meaning that the
             * onStatus and onSelect events of THIS(menuAction) will
             * be executed instead of these events of the
             * dynamicMenuitem. The pointer "theMenuitem" refers to
             * the dynamicMenuitem THIS(menuAction) is currently
             * attached to
             *)
            (# theMenuitem:
                 (* the menuitem THIS(menuAction) is attached to *)
                 ^dynamicMenuitem;
               onStatus:< booleanValue
                 (* this status is evaluated instead of the status of
                  * the actual menuitem (theMenuitem) THIS(menuAction)
                  * is attached to.  Default returns true
                  *)
                 (# ... #);
               onSelect:< 
                 (* onSelect is executed from the hit of the actual
                  * dynamicMenuitem THIS(action) is attached to
                  *)
                 object;
            #) (* action *);
          separator: menuitem
            (* defines a menu separator, which is a unselectable line
             * in the menu, dividing groups of menuitems.
             *)
            (# open::<
                 (# create::< (# ... #);
                 ...
                 #);
               close::< (# ... #);
            #);
          append:
            (* appends the menuitem to THIS(menu) *)
            (# theMenuitem: ^menuitem
            enter theMenuitem[]
            ...
            #);
          delete: 
            (* deletes the menuitem from THIS(menu) *)
            (# theMenuitem: ^menuitem
            enter theMenuitem[]
            ...
            #);
          scan: 
            (* iterates over all menuitems in THIS(menu) *)
            (# current: ^menuitem
              ...
            #);
          clear:
            (* deletes all menuitems in  THIS(menu) *)
            (#
            ...
            #);
          noOfMenuitems: integerValue
            (* returns the number of menuitems in THIS(menu) *)
            (# ... #);
          popUp: 
            (* THIS(menu) is popped up as follows: The menuitem
             * indexed by "popupWith" is selected (not checked but
             * hilited) and popupAt is the top left corner of that
             * menuitem in the coordinate system of the popupIn
             * window.
             *)
            (# popupWith: @integer;
               popupAt: @point;
               popupIn: ^window.windowitem;
            enter (popupWith,popupAt,popupIn[])
            ...
            #);
          getMenuitemByNumber: 
            (* returns a reference to the menuitem at the specified
             * position in the menu
             *)
            (# number: @integer;
               theMenuitem: ^menuitem;
            enter number
            ...
            exit theMenuitem[]
            #);
          enable: (* enable THIS(menu) *)
            (# ... #);
          disable: (* disable THIS(menu) *)
            (# ... #);
          enabled:< booleanValue
            (* should return true if THIS(menu) is enabled *)
            (# ... #);
          open::< 
            (* the menu is not automatically inserted in the
             * menubar. You have to do this yourself
             *)
            (# create::< (# ... #);
            ... 
            #);
          close::< (# ... #);
          private: @...;
       #) (* menu *);
     standardMenubar: menubar
       (# standardFileMenu: menu
            (# newMenuitem: @dynamicMenuitem;
               openMenuitem: @dynamicMenuitem;
               closeMenuitem: @dynamicMenuitem;
               saveMenuitem: @dynamicMenuitem;
               saveAsMenuitem: @dynamicMenuitem;
               revertMenuitem: @dynamicMenuitem;
               printMenuitem: @dynamicMenuitem;
               pageSetUpMenuitem: @dynamicMenuitem;
               quitMenuitem: @dynamicMenuitem;
               open::< (# ... #);    
            #) (* standardFileMenu *);
          fileMenu:< menu;
          theFileMenu: ^fileMenu;
          standardEditMenu: menu
            (# undoMenuitem: @dynamicMenuitem;
               cutMenuitem: @dynamicMenuitem;
               copyMenuitem: @dynamicMenuitem;
               pasteMenuitem: @dynamicMenuitem;
               clearMenuitem: @dynamicMenuitem;
               open::< (# ... #)
            #) (* standardEditMenu *);
          editMenu:< menu;
          theEditMenu: ^editMenu;
          open::<
            (# 
            ...
            #);
       #);
     window: interfaceObject
       (* user interaction with the window such as dragging and
        * resizing is taken care of by the window manager.  Anything
        * visible you may want to place in the window is subpatterns
        * of the abstract pattern windowitem, which is a subpattern of
        * interfaceObject. The window can be used as a modal dialog by
        * means of the pattern "showModal"
        *)
       (# <<SLOT windowLib: attributes>>;
          eventhandler::<
            (# aboutToClose: event
                 (* is called whenever the user has performed an
                  * action that causes THIS(window) to close.  Further
                  * bind this to perform actions before the window is
                  * actually closed.  You can prevent the window from
                  * closing by assigning false to the boolean
                  * 'okToClose'
                  *)
                 (# okToClose: @boolean
                 do true -> okToClose;
                    INNER
                 exit okToClose
                 #);
               onAboutToClose:<  aboutToClose;
               onActivate::<
                 (* is send to contents, which takes care of sending
                  * the event to all children
                  *)
                 (# ... #);
               onDeactivate::<
                 (* is send to contents, which takes care of sending
                  * the event to all children
                  *)
                 (# ... #);
            #);
          theMenubar:
            (* is used to install a menubar for THIS(window), and to
             * gain access to the menubar of THIS(window)
             *)
            (# theBar: ^menubartype
            enter (# enter theBar[] ... #)
            exit (# ... exit theBar[] #)
            #);
          menubarType:<
            (* if further bound, an instance of menubarType is
             * automatically installed for THIS(window)
             *)
            menubar;
          menubarVisible:< 
            (* Specifies if the menubar should be visible. *)
            trueObject;
          type:<
            (* The type can be one of the following:
             *   windowTypes.normal  <- default
             *   windowTypes.dialog
             *   windowTypes.palette
             *)
            integerValue;
          resizeable:< booleanValue
            (# 
            do (if type=windowTypes.normal then
                   true -> value; INNER 
               if);
            #);
          title: 
            (* the title of the window is displayed in the windows
             * title-bar if the window has one.
             *)
            (# theTitle: ^text
            enter (# enter theTitle[] ... #)
            exit (# ... exit theTitle[] #)
            #);
          position: 
            (* the window's position is the coordinates of the
             * topLeft corner of the window's inside rectangle on the
             * screen
             *)
            (# pt: @point;
            enter (# enter pt ... #)
            exit (# ... exit pt #)
            #);
          size: 
            (* the size is the size of the inside rectangle of the
             * window
             *)
            (# width, height: @integer;
            enter (# enter (width, height) ... #)
            exit (# ... exit (width, height) #)
            #);
          frame:
            (* the frame is defined as the rectangle THIS(window)
             * occupies on the screen = (position,position + size)
             *)
            (# theFrame: @rectangle;
            enter (# enter theFrame ... #)
            exit (# ... exit theFrame #)
            #);
          insideRectangle: 
            (* the inside rectangle is the window's content rectangle
             * in terms of local coordinates in the window.  The top
             * left corner is (0, 0) and the bottom right corner is
             * the window's size
             *)
            (# theRectangle: @rectangle;
            ...
            exit theRectangle
            #);
          show: 
            (* shows THIS(window) in front of other windows *)
            (# ... #);
          showModal:
            (* shows THIS(window) in a modal way. Interaction with
             * other windows is prevented until THIS(window) is either
             * closed or hidden, and then showModal returns to the
             * caller
             *)
            (# ... #);
          hide: 
            (* hides THIS(window), i.e. make it invisible without
             * destroying it. Can be made visible again using show
             *)
            (# ... #);
          visible:
            (* The visibility of the window. *)
            (# value: @boolean;
            enter (# enter value ... #)
            exit (# ... exit value #)
            #);
          maxSize: 
            (* use this to set the maximum size THIS(window) is
             * allowed to get, when resized by the user. maxSize
             * doesn't affect the behaviour of setSize.
             *)
            (# width, height: @integer;
            enter (# enter (width, height) ... #)
            exit (# ... exit (width, height) #)
            #);
          minSize: 
            (* use this to set the minimum size THIS(window) is
             * allowed to get, when resized by the user. minSize
             * doesn't affect the behaviour of setSize
             *)
            (#  width, height: @integer;
            enter (# enter (width, height) ... #)
            exit (# ... exit (width, height) #)
            #);
          bringToFront: 
            (* THIS(window) is brought to the front of all other
             * windows
             *)
            (# ... #);
          bringBack: 
            (* THIS(window) is placed behind all other windows *)
            (# ... #);
          bringBehind: 
            (* THIS(window) is placed behind the window referred to
             * by "theWindow"
             *)
            (# theWindow: ^window;
            enter theWindow[]
            ...
            #);
          update: 
            (* Updates the window by posting a refresh event.  If
             * emmediate is true, the refresh event will be processed
             * immediately.
             *)
            (# immediate: @boolean;
            enter immediate
            ...
            #);
          backgroundColor:
            (* Sets backgroundcolor of this window *)
            (# theColor: @color
            enter theColor
            ...
            #);
          contents:
            (* The contents of THIS(window) is the father of all
             * other windowitems in THIS(window).
             *)
            (# theContents: ^canvas;
            ...
            exit theContents[]
            #);
          target: 
            (* the window's target is a reference to the windowitem
             * that receives keyDown. You are responsible for making
             * sure the window's target is the windowitem that is
             * affected by menu commands. The eventhandler of
             * windowitem has two events: "enableTarget" and
             * "disableTarget". When a windowitem is becomming the new
             * target, first "disableTarget" is called for the old
             * target then "enableTarget" is called for the new target
             *)
            (# theTarget: ^windowitem;
            enter (# enter theTarget[] ... #)
            exit (# ... exit theTarget[] #)
            #);
          windowitem: interfaceObject
            (* superclass for all interfaceobjects in this window.  A
             * windowitem is always part of a canvas (father)
             *)
            (# <<SLOT windowitemLib: attributes>>;
               eventhandler::<
                 (# visibleChanged: event
                      (* is called, when THIS(windowitem) is hidden
                       * or shown
                       *)
                      (# do INNER #);
                    onVisibleChanged:< visibleChanged;
                    frameChanged: event
                      (* is called whenever the frame of
                       * THIS(windowitem) is changed
                       *)
                      (# oldFrame, newFrame: @rectangle;
                      enter (oldFrame, newFrame)
                      do INNER 
                      #);
                    onFrameChanged:< frameChanged;
                    fatherFrameChanged: event
                      (* is called when the frame of the father of
                       * THIS(windowitem) is changed
                       *)
                      (# oldFrame, newFrame: @rectangle;
                      enter (oldFrame, newFrame)
                      do INNER 
                      #);
                    onFatherFrameChanged:< fatherFrameChanged;
                    enabledChanged: event
                      (* is called, when THIS(windowitem) is
                       * enabled/disabled
                       *)
                      (# do INNER #);
                    onEnabledChanged:< enabledChanged;
                    enableTarget: event
                      (* is called when THIS(windowitem) is becomming
                       * target in the window
                       *)
                      (# do INNER #);
                    onEnableTarget:< enableTarget;
                    disableTarget: event
                      (* is called when THIS(windowitem) was target
                       * and another windowitem is becomming target
                       *)
                      (# do INNER #);
                    onDisableTarget:< disableTarget;
                   borderVisibleChanged: event
                     (* is called, when the border of 
                       * THIS(windowitem) is shown or hidden
                       *)
                     (# do INNER #);
                   onBorderVisibleChanged:< borderVisibleChanged;
                   borderStyleChanged: event
                     (* is called, when the border style of
                       * THIS(windowitem) is changed
                       *)
                     (# do INNER #);
                   onBorderStyleChanged:< borderStyleChanged;
                    theCursorChanged: event
                      (* is called, when THIS(windowitem) is assigned
                       * a new cursor
                       *)
                      (# do INNER #);
                    onTheCursorChanged:< theCursorChanged;
                    hiliteChanged: event
                      (* Is called when THIS(windowitem) is hilited
                       * or dehilited
                       *)
                      (# do INNER; #);
                    onHiliteChanged:< hiliteChanged;
                    onRefresh::< (# ... #);
                    mouseEnter:event
                      (* Is called when the mouse enters THIS(windowitem) *)
                      (# do INNER #);
                    onMouseEnter:<mouseEnter;
                    mouseLeave:event
                      (* Is called when the mouse leaves THIS(windowitem) *)
                      (# do INNER #);
                    onMouseLeave:<mouseLeave;
                 #);
               father: ^
                 (* father is the canvas that THIS(windowitem) is a
                  * child of
                  *)
                 canvas;
               frame: 
                 (* the frame is defined as the rectangle
                  * THIS(windowitem) occupies in the coordinate system
                  * of the father. When the frame is changed
                  * THIS(windowitem) is updated and the father is
                  * informed about the change.  If you need other
                  * actions to take place, when changing the frame,
                  * you must further bind the event onFrameChanged
                  *)
                 (# theFrame: @rectangle;
                 enter (# enter theFrame ... #)
                 exit (# ... exit theFrame #)
                 #);
               position: 
                 (* the position of THIS(windowitem) is defined as
                  * the topLeft corner of the bounding frame. When the
                  * position is changed, the frame is changed, so the
                  * onFrameChanged event is called
                  *)
                 (# pt: @point;
                 enter (# enter pt ... #)
                 exit (# ... exit pt #)
                 #);
               move: 
                 (* moves THIS(windowitem) relative (dh, dv), by
                  * setting the position, meaning that the
                  * onFrameChanged event is called
                  *)
                 (# dh, dv: @integer;
                 enter (dh, dv)
                 ...
                 #);
               size: 
                 (* the size of THIS(windowitem) is defined as the
                  * height and width of the bounding frame. When the
                  * size is changed, the frame is changed, so the
                  * onFrameChanged event is called
                  *)
                 (# width, height: @integer;
                 enter (# enter (width, height) ... #)
                 exit (# ... exit (width, height) #)
                 #);
               fitToContents:<
                 (* Adjusts the size of THIS(windowItem) to 
                  * fit the contents
                  *)
                 (# doneInInner: @boolean;
                 ...
                 #);
               bindLeft, bindRight, bindBottom, bindTop: @
                 (* these attributes specify how THIS(windowitem)
                  * shall behave when the father changes it's
                  * frame. If e.g. "bindLeft" is true, the leftSide
                  * will have the same constant distance to the
                  * leftSide of the father, when the father is resized
                  *)
                 boolean;
               visible:
                 (* an invisible windowitem will be ingored w.r.t.
                  * user interaction (it is not visible on the screen)
                  *)
                 (# value: @boolean;
                 enter (# enter value ... #)
                 exit (# ... exit value #)
                 #);
               hilite:
                 (# value: @boolean;
                 enter (# enter value ... #)
                 exit (# ... exit value #)
                 #);
               show: 
                 (* makes THIS(windowitem) visible *)
                 (# ... #);
               hide: 
                 (* makes THIS(windowitem) invisible *)
                 (# ... #);
               enabled:
                 (* if THIS(windowitem) is enabled it receives mouse
                  * events or key events
                  *)
                 (# value: @boolean
                 enter (# enter value ... #)
                 exit (# ... exit value #)
                 #);
               enable:
                 (* enables THIS(windowitem) so it can receive mouse
                  * or key events
                  *)
                 (# ... #);
               disable:
                 (* disables THIS(windowitem) so it does not receive
                  * any mouse or key events
                  *)
                 (# ... #);
               backgroundColor:
                 (# theColor: @color;
                 enter (# enter theColor ... #)
                 exit (# ... exit theColor #)
                 #);
               border: @
                 (* the border around THIS(windowitem) makes it 
                  * apparent, where it is located on the screen.
                  *)
               (# visible:
                    (* if the border is visible, the insideRect of
                     * THIS(windowitem) is inset depending on the
                     * style of the border.
                     *) 
                    (# value: @boolean;
                    enter (# enter value ... #)
                    exit (# ... exit value #)
                    #);
                  style:
                    (* the border style can be one of the
                     * following:
                     *   borderStyles.simple: 
                     *      A simple one pixel wide border.
                     *   borderStyles.shadowIn:
                     *      Draws the border so THIS(windowitem)
                     *      appears inset.
                     *   borderStyles.shadowOut:
                     *      Draws the border so THIS(windowitem)
                     *      appears outset.
                     *   borderStyles.etchedIn:
                     *      Draws the border using a double line
                     *      giving the effect of a line etched
                     *      into the window.
                     *   borderStyles.etchedOut:
                     *      Draws the border using a double line
                     *      giving the effect of a line comming
                     *      out of the window.
                     *)
                    (# value: @integer;
                    enter (# enter value ... #)
                    exit (# ... exit value #)
                    #);
               #);
               insideRectangle:
                 (* insideRectangle is the area inside the border of
                  * THIS(windowitem).
                  *)
                 (# theRectangle: @rectangle;
                 ...
                 exit theRectangle
                 #);
               theCursor:
                 (* theCursor is used to install a cursor for
                  * THIS(windowitem), and to gain access to the cursor
                  * of THIS(windowitem)
                  *)
                 (# theCur: ^cursor;
                 enter (# enter theCur[] ... #)
                 exit (# ... exit theCur[] #)
                 #);
               cursorType:<
                 (* if further bound, an instance of cursorType is
                  * automatically installed for THIS(windowitem)
                  *)
                 cursor;
               trackMouse: 
                 (* this is a control pattern usually evaluated from
                  * a mouseDown eventhandler. Initially 'mousePress'
                  * is evaluated, then 'mouseMove' is evaluated
                  * whenever the mouse moves as long as the mouse is
                  * stillDown - (h, v) will be the horizontal and
                  * vertical distance the mouse has moved since the
                  * last call to 'mouseMove'.  When the user releases
                  * the mouse, 'mouseRelease' is evaluated.  If the
                  * mouse isn't stillDown (see stillDown) when track
                  * is called nothing will happen.  All the
                  * coordinates are local to THIS(WindowItem).
                  *)
                 (# mousePress:< object;
                    mouseMove:< 
                      (# h, v: @integer;
                      enter (h, v)
                      do INNER
                      #);
                    mouseRelease:< object;
                    curPt, prevPt: @point;
                 ...
                 #);
               drag: 
                 (* lets the user drag a gray outline of this
                  * windowitem
                  *)
                 (# ... #);
               resize: 
                 (* lets the user resize this windowitem by dragging
                  * a gray outline
                  *)
                 (# ... #);
               update: 
                 (* THIS(windowitem) is updated, by posting an
                  * refresh event to the window. If "immediate" is
                  * true the update is performed immediately,
                  * otherwise the update is performed, when there is
                  * no other event waiting (this is normally what you
                  * want)
                  *)
                 (# immediate: @boolean;
                 enter immediate
                 ...
                 #);
               open::< 
                 (* initially a windowitem is visible and active *)
                 (# create::< (# ... #);
                 enter father[]
                 ...
                 #);
               close::< 
                 (* no actions are performed at this level *)
                 (# ... #);
               private: @...;
            #); (* windowitem *)
          separator: windowitem
            (* a separator is a horzontal or vertical separating line
             *)
            (# <<SLOT separatorLib: attributes>>;
               eventhandler::<
                 (# styleChanged: event
                      (* Called when the style is changed *)
                     (# do INNER #);
                    onStyleChanged:< styleChanged;
                    onRefresh::< (# ... #);
                #);
               vertical:< 
                 (* Further bind to specify the orientation of
                  * THIS(separator) default is horizontal
                  *)
                 booleanObject;
               style:
                (* the  style can be one of the following:
                 *   lineStyles.singleLine: 
                 *     A single line is drawn.
                 *   lineStyles.doubleLine:
                 *     A double line is drawn.
                 *   lineStyles.dashedSingleLine:
                 *     A dashed single line is drawn.
                  *   lineStyles.dashedDoubleLine:
                 *     A dashed double line is drawn.
                 *   lineStyles.etchedIn:
                 *     A double line is drawn giving the effect of
                  *     a line etched into the window.
                 *   lineStyles.etchedOut:
                 *     A double line is drawn giving the effect of
                  *     a line comming of of the window.
                 *)
                (# value: @integer;
                enter (# enter value ... #)
                exit (# ... exit value #)
                #);
               open::<
                 (# create::< (# ... #);
                ...
                #);
               close::<
                 (# ... #);
               private: @...;
            #);
          canvas: windowitem
            (* A canvas is a sub-window in the window.  Only the
             * windowitems located inside the frame of THIS(canvas)
             * will be visible
             *)
            (# <<SLOT canvasLib: attributes>>;
               eventhandler::<
                 (# childFrameChanged: event
                      (* is called when a child of THIS(canvas) has
                       * changed frame
                       *)
                      (# oldFrame, newFrame: @rectangle;
                      enter (oldFrame, newFrame) 
                      do INNER 
                      #);
                    onChildFrameChanged:< childFrameChanged;
                    onActivate::< (# ... #);
                    onDeactivate::< (# ... #);
                    onMouseDown::< (# ... #);
                    onRefresh::< (# ... #);
                    onMouseUp::< (# ... #);
                    onFrameChanged::< (# ... #);
                    onVisibleChanged::< (# ... #);
                 #);
               selection: @
                 (# add:
                      (# theWindowitem: ^windowitem;
                      enter theWindowitem[]
                      ...
                      #);
                    set:
                      (# theWindowitem: ^windowitem;
                      enter theWindowitem[]
                      ...
                      #);
                    remove:
                      (# theWindowitem: ^windowitem;
                      enter theWindowitem[]
                      ...
                      #);
                    empty: booleanValue
                      (# 
                      ...
                      #);
                    scan:
                      (# current: ^windowitem;
                      ...
                      #);
                    clear:
                      (# 
                      ...
                      #);
                 #);
               scan:
                 (* Scan operation on the children of THIS(canvas) *)
                 (# current: ^windowitem;
                 ...
                 #);
               open::< 
                 (* The canvas is opened and displayed. *)
                 (# create::< (# ... #);
                 ... 
                 #);
               close::< 
                 (* close is called for all the children of
                  * THIS(canvas)
                  *)
                 (# ... #);
               private: @...;
            #) (* canvas *);
          localToGlobal:
            (* Translate the point from global coordinates to window
             * coordinates.
             *)
            (# local, global: @point;
            enter local
            ...
            exit global
            #);
          globalToLocal:
            (* Translates the point to window coordinates to global
             * local coordinates
             *)
            (# global, local: @point;
            enter global
            ...
            exit local
            #);
          open::< 
            (# create::< (# ... #);
            ... 
            #);
          close::< 
            (* the windows close operation is normally automatically
             * called from the content's aboutToGoAway event.  You can
             * also call it directly. theContents.close is called to
             * close all of the windows internal structures
             *)
            (# ... #);
          <<SLOT BifrostAttributes: attributes>>;
          private: @...;
       #) (* window *);
     cursor: 
       (* A cursor is the raster attached to the mouse pointer *)
       (# <<SLOT cursorLib: attributes>>;
          private: @... 
       #);  
     pixmap:
       (* Pixmap pattern *)
       (# <<SLOT pixmapLib: attributes>>;
          read:
            (* Reads the specified file into THIS(pixmap). 
             * The type of the  file are guessed by looking 
             * at the extension, or the the first few bytes,
             * or the macintosh file type - all depending
             * on the platform
             *)
            (# name: ^text;
               error:< exception
                 (# what: ^text;
                 enter what[]
                 do what[] -> msg.append;
                    INNER;
                 #);
            enter name[]
            ...
            #);
          clear:
             (* Clear the Pixmap with the specified color *)
             (# theColor: @Color;
             enter theColor
             ...
             #);
          init:<
            (* Intializes the raster to have the specified width 
             * and height. Allocates any data needed - 
             * you have to call dispose to free that data.
             *)
            (# width, height: @integer;
            enter (width, height)
            ...
            #);
          dispose:<
            (* call this to dispose the memory occupied 
             * by THIS(pixmap) when completely done with 
             * THIS(pixmap)
             *)
            (#
            ...
            #);
          width: integerValue
            (* returns the width set by init or by 
             * read operations 
             *)
            (# ... #);
          height: integerValue
            (* returns the height set by init or 
             * by read operations 
             *)
            (# ... #);
          transparent:
             (* Specifies that the "background" of this(pixmap) is
              * transparent.
              * This attribute is automatically set to TRUE 
              * If a transparentColor or a mask is specified.
              * If "transparent" is set to FALSE, the transparentColor
              * or mask will be cleared.
              *)
             (# value: @boolean;
             enter (# enter value ... #)
             exit (# ... exit value #)
             #);
          transparentColor:
            (* Specify which color in the pixmap should be transparent.
             * This will normally be the background color in the pixmap.
             * When a transparentColor is specified the "transparent" 
             * attribute will be set to TRUE.
             * If the "transparent" is set to FALSE, any transparentColor
             * will be cleared.
             *)
            (# theColor: @color;
            enter (# enter theColor ... #)
            exit (# ... exit theColor #)
            #);
          mask:
            (* Specify a mask for this(pixmap). A mask is a one-depth
             * pixmap. Only the pixels in this(pixmap) that has 
             * corresponding pixel in the mask with the value 1, will
             * be drawn on the screen, when drawing this(pixmap).
             * If a mask is specified the "transparent" attribute will
             * be set to TRUE. If transparent is set to FALSE, any mask
             * will be cleared.
             *)
            (# theMask: ^pixmap;
            enter (# enter theMask[] ... #)
            exit (# ... exit theMask[] #)
            #);
          drawPixmap:
            (* Draw the pixmap "other" on this(pixmap) *)
            (# other: ^pixmap;
               from, to: @point;
               width, height: @integer;
            enter (other[], from, to, width, height)
            ...
            #);
          private: @...;
       #);
     textStyle: 
       (* textStyle is font, size and face. You can use this pattern
        * to communicate stylic changes to layout-text and
        * document-text - or to get information about the dimension of
        * text drawn in a specific textStyle
        *)
       (# <<SLOT textStyleLib: attributes>>;
          name:
            (* models the name of the font of THIS(textStyle). *)
            (# theName: ^text;
            enter (# enter theName[] ... #)
            exit (#  ... exit theName[] #)
            #);
          size:
            (# value: @integer;
            enter (# enter value ... #)
            exit (# ... exit value #)
            #);
          face:
            (# value: @integer;
            enter (# enter value ... #)
            exit (# ... exit value #)
            #);
          ascent: integerValue
            (* ascent is the maximum amount of pixels a character
             * drawn in THIS(textStyle) will go above the base line
             *)
            (# ... #);
          descent: integerValue
            (* descent is the maximum amount of pixels a character
             * drawn in THIS(textStyle) will go below the base line
             *)
            (# ... #);
          leading: integerValue
            (* leading is the vertical distance between the descent
             * of one line and the ascent of the next line
             *)
            (# ... #);
          lineHeight: integerValue
            (* the line height (in pixels) is determined by adding
             * the ascent, descent, and leading
             *)
            (# ... #);
          maxChWidth: integerValue
            (* the greatest distance the pen will move when a
             * character is drawn
             *)
            (# ... #);
          widthOfChar: integerValue
            (* in most fonts the width of the characters
             * differs. This method returns the width of the character
             * "ch" when drawn in THIS(textStyle)
             *)
            (# ch: @char
            enter ch
            ...
            #);
          widthOfText: integerValue
            (* widthOfText returns the width of the given text
             * string, when drawn in THIS(textStyle), which it
             * calculates by adding the charWidths of all the
             * characters in the string
             *)
            (# str: ^text
            enter str[]
            ...
            #);
          availableSizes: 
            (* an INNER is executed for all available sizes in the
             * font of THIS(textStyle)
             *)
            (# thisSize: @integer;
            ...
            #);
          private: @...;
       #) (* textStyle *);
     color:
       (* A Color has three components: red, green and blue. *)
       (# <<SLOT colorLib: attributes>>;
          red,green,blue: @integer;
       enter (red,green,blue)
       exit (red,green,blue)
       #);
     
     timer:
       (# <<SLOT timerLib: attributes>>;
          once:< booleanValue;
          
          start:
            (# interval: @integer
            enter interval
            ...
            #);
          stop:
            (# ... #);
          action:<
            object;
          private: @...;
       #);

     clipboard: @
       (* models the clipboard, which is used to transport pictures
        * and text between applications
        *)
       (# <<SLOT clipBoardLib: attributes>>;
          hasText: booleanValue 
            (* returns true if the contents of the clipBoard is text
             *) 
            (# ... #);
          textContents: 
            (* evaluate the enter-part to set the clipboards
             * text-contents, and evaluate the exit-part to get the
             * clipboards text-contents.  If the clipboard doesn't
             * contain text, NONE is returned.  You can call hasText,
             * before calling getTextContents to determine if there is
             * text to get
             *)
            (# txt: ^text;
            enter (# enter txt[] ... #)
            exit (# ... exit txt[] #)
            #);
          clearContents:
            (* call this to empty all contents of the clipboard *)
            (# ... #);
       #) (* clipboard *);
     mouse: @
       (* models the mouse *)
       (# <<SLOT mouseLib: attributes>>;
          globalPosition: 
            (* the global position of the mouse is returned. You
             * can't set the position
             *)
            (# pt: @point;
            ...
            exit pt
            #);
          buttonState: integerValue
            (* the number designating the button, currently pressed
             * down - 0 means 'no button'.  This value depends on the
             * number of buttons on the mouse - Typically 1, 2 or 3.
             *) 
            (# 
            ...
            #);
          busyCursor:
            (* A busy cursor is a sign to the user that the
             * application are doing some processing. You will
             * normally use cursors.watch for this purpose. Set
             * busyCursor to none, when done processing.
             *)
            (# theCur: ^cursor;
            enter (#  enter theCur[] ... #)
            exit (# ... exit theCur[] #)
            #);
       #) (* mouse *);
     
     (* These models different properties of the current system 
      * next 5 patterns was formerly in a systempattern      
      *)
     
     screenRectangle: 
       (* the rectangle of the main screen. *)
       (# theRectangle: @rectangle;
       ...
       exit theRectangle
       #);
     screenRgn: 
       (* the region defining the screen(s) *)
       (# rgn: ^region;
       ...
       exit rgn[]
       #);
     standardTextStyle: 
       (* the textStyle used by the system to draw menutitles
        * etc.
        *)
       @textStyle;
     beep:
       (* beeps using the current beep in the system *)
       (# ... #);
     guienvWait: 
       (* delays the specified number of ticks (1 tick = 1/60
        * sec.)
        *)
       (# ticks: @integer;
       enter ticks
       ...
       #);
     transferModes: @
       (# copy: (# exit 0 #);
          invertCopy: (# exit 1 #);
          erase: (# exit 2 #);
          andBlend: (# exit 3 #);
          orBlend: (# exit 4 #);
          xorBlend: (# exit 5 #);
          notAndBlend: (# exit 6 #);
          notOrBlend: (# exit 7 #);
       #);
     textFaces: @
       (# <<SLOT textFacesLib: attributes>>;
          plain: (# exit  0 #);
          bold: (# exit  1 #);
          italic: (# exit  2 #);
       #);
     patterns: @
       (# black, dkGray, gray, ltGray, white: ^pixmap #);
     cursors: @
       (# arrow, iBeam, watch, cross, plus: @cursor #);
     borderStyles: @
       (# simple: (# exit 1 #);
          etchedOut: (# exit 2 #);
          etchedIn: (# exit 3 #);
          shadowIn: (# exit 4 #);
          shadowOut: (# exit 5 #);
       #);
     separatorStyles: @
       (# singleLine: (# exit 1 #);
          doubleLine: (# exit 2 #);
          singleDashedLine: (# exit 3 #);
          doubleDashedLine: (# exit 4 #);
          etchedIn: (# exit 5 #);
          etchedOut: (# exit 6 #);
       #);
     windowTypes: @
       (# normal: integerValue (# do 0 -> value #);
          dialog: integerValue (# do 1 -> value #);
          palette: integerValue (# do 2 -> value #);
          modelessDialog: integerValue (# do 3 -> value #);
       #);
     specKeys:@specialKeys;
     private: @...;
     trace:
       (* For debugging. If doTrace is true, INNER is called. *)
       (#
       do (if doTrace then INNER if);
       #);
     doTrace: @Boolean;
     (* Additions needed for bifrost *)
     bifrostprivate: @...;
     displaywarnings: @boolean
       (* If displayWarnings is true, various warnings about bifrost
        * errors that are not fatal, but may affect the behaviour, is
        * displayed. Defaults to true.
        *);
     warnStream: ^stream
       (* The stream bifrost warnings are put to. Defaults to
        * screen.
        *);
     
     (* Additions needed for systemenv *)
     doSetup: 
       (# 
       do (if not setupDone then
              ...; 
              true -> setupDone 
          if)
       #);
     setupDone: @Boolean;
     XsystemEnvPresent: @Boolean; 
     (* TRUE if this is a XsystemEnv program.  In this case,
      * callbacks are executed by a separate thread as synchronisation
      * via semaphores between x-callbacks and other coroutines would
      * not be possible otherwise. (It could lead to suspend of
      * coroutines with C stackparts.  If TRUE,
      * XsystemEnvHandleCallback should not be NONE.
      *)
     XsystemEnvHandleCallbackP: 
       (# cb: ^Object; enter cb[] do INNER #);
     XsystemEnvHandleCallback: 
       ^XsystemEnvHandleCallbackP;
  ...
  #)


20.8 Guienv Interface
© 1994-2002 Mjølner Informatics
[Modified: Tuesday March 21st 2000 at 12:28]