ETHZ_Logo RAMSES_Logo_Right   RAMSES   RAMSES_Logo_Left Systems Ecology  
Start    search button      Modules:   A-Z   Function   Layer        QuickRefs:   DM   AuxLib   AuxLibE   SciLib   EasyMW   MW   ISIS   RMSLib

DEFINITION MODULE DMWindows;

  (*******************************************************************

    Module  DMWindows     ('Dialog Machine' DM_V3.0)

      Copyright (c) 1985-2006 by Andreas Fischlin, Alex Itten and
      ETH Zurich.

    Purpose   Manages windows on behalf of a 'Dialog Machine' 
              program.

    Remarks   Windows give the user a particular view onto
              any type of objects the application program
              creates or manages, such as a portion of a
              graph or a text.  Multiple windows may coexist
              on the same screen.  They may overlap and can
              be moved, resized, rearranged in their sequence
              by bringing a partially overlapped window to
              the front (= window activation) implies the
              simultaneous removing of the previously
              frontmost window from the front (= window
              deactivation).  A window's content can be
              scrolled, so that other parts of the
              displayedobject may become visible.

              Method:  Windows may be created, repositioned,
              activated, or removed under program control exerted
              by the application.  However, typically an
              application only creates windows (procedure
              DMWindows.CreateWindow) and specifies its
              properties.  Once created, the window management is
              left to module DMMaster, i.e. clicking the mouse
              button in the content region or the close box of a
              window results in an automatical call to the
              corresponding window management procedure.  Except
              for the window creation, all window management
              functions can be left to the 'Dialog Machine' and
              must not be dealt with by the application program.
              An exception to this is the updating of the window
              content necessary after an event causing a
              previously covered window portion to become visible
              again.  The client program has to provide a
              so-called re- store procedure
              (DMWindows.RestoreProc) which redraws the whole
              window content.  The calling of this procedure and
              the restriction of the drawing area to window areas
              currently really visible (not covered by other
              windows) are automatically provided by the 'Dialog
              Machine' and the restore procedure need not to be
              concerned with this problem.

              This module belongs to the 'Dialog Machine'.


    Programming

      o Design
        Andreas Fischlin          16/12/1985

      o Implementation
        Andreas Fischlin          16/12/1985
        Alex Itten                22/12/1986


    ETH Zurich
    Systems Ecology
    CHN E 35.1
    Universitaetstrasse 16
    8092 Zurich
    SWITZERLAND

    URLs:
        <mailto:RAMSES@env.ethz.ch>
        <http://www.sysecol.ethz.ch>
        <http://www.sysecol.ethz.ch/SimSoftware/RAMSES>


    Last revision of definition:  05/08/1991  AF

  *******************************************************************)


  FROM SYSTEM IMPORT ADDRESS;


  TYPE
    Window;
      (*
        Variables of this type are needed to identify particular
        windows. Always(!) declare such variables on a global
        level, since the window management routines attempt to
        update your variables.  E.g. when closing a window by
        clicking the close box contained in the window title bar,
        the "Dialog Machine" assigns to your window variable the
        value nonexistent.
      *)


    (*
      types of application windows (document windows with a title
      bar except for FixedLocation) are distinguished as follows:
    *)

    WindowKind = (GrowOrShrinkOrDrag, (*resizing and dragging permitted*)
                  FixedSize,          (*no resizing, dragging permitted*)
                  FixedLocation,      (*no resizing, no dragging. no title bar*)
                  FixedLocTitleBar);  (*no resizing, no dragging*)

    ModalWindowKind = (DoubleFrame, SingleFrameShadowed);

    ScrollBars = (WithVerticalScrollBar, WithHorizontalScrollBar,
                  WithBothScrollBars, WithoutScrollBars);

    CloseAttr = (WithCloseBox, WithoutCloseBox);

    ZoomAttr = (WithZoomBox, WithoutZoomBox); (*only meaningful on >= Mac+*)

    RectArea = RECORD x,y,w,h: INTEGER END;   (*Rectangular area with
                                              lower left corner (x,y)
                                              and width w and height h*)

    WindowFrame = RectArea;     (*Determines size and position of a
                                window relative to the background
                                coordinates. It frames just the
                                working area in which output
                                takes place, i.e. the title bar or
                                any scrollbars are excluded.  Note,
                                when you create a window, that these
                                areas are added on the outside of
                                the WindowFrame.*)

    WFFixPoint = (bottomLeft, topLeft); (* Fixpoint on the window frame
                                        (corner) relative to which the
                                        window content is positioned
                                        after a redefinition of the
                                        window size (redefine event). *)


    RestoreProc = PROCEDURE (Window);
      (*
        Procedure to redraw the whole content of a window. A
        procedure of this type is called by the "Dialog Machine"
        after a portion of a window's content region becomes
        uncovered (for instance if the window becomes the frontmost
        window after having been partially overlapped by other
        windows).  Its purpose is to simply redraw the whole
        content of the window.  Typically this is done without
        being concerned about the visibility of the window's
        content region or other similar issues; the "Dialog
        Machine's" window management takes care of that. Given the
        current arrangement of windows, only the visible portions
        of the drawing will be displayed.
      *)

    CloseProc = PROCEDURE (Window, VAR BOOLEAN);
      (*
        Procedure called if the window is about to be closed by the
        user when clicking into the close box, just before it is
        actually closed.  This happens before any eventually
        installed window handlers (see below WindowHandlers) and
        before the global MouseHandler for closing events from
        DMMaster are called. This is the right moment to save
        objects associated with the closing window or eventually to
        suppress the closing of the window by returning FALSE.
        Typically the latter case is used if it has not been
        possible to complete successfully the handling procedure,
        for instance if errors have been detected in the entry of
        an edit field maintained by module DMEditFields requesting
        from the user a value necessary for any further meaningful
        use of the program. If FALSE is returned the global
        MouseHandler CloseWindow is not called and the window
        remains open as it was before the user attempted to close
        it.  The default close procedure returns always TRUE. (see
        also SetCloseProc (this module) and
        DMWindows.CloseHandler).  Note that RemoveWindow will not
        call such a close procedure, assuming that the programmer
        calls the procedure only after having done any houskeeping.
        In case you need to receive a message when RemoveWindow is
        called, installed a WindowHandler closed.
      *)

    WindowProc = PROCEDURE (Window);
      (*
        Type of an action procedure to be performed with a window
        (s.a. procedures DoForAllWindows, AddWindowHandler, and
        RemoveWindowHandler).
      *)

    WindowHandlers = (clickedInContent, broughtToFront, removedFromFront,
                     redefined, onlyMoved, disappeared, reappeared, closing);

      (*
        Possible window related events.  Some of these events may
        be produced by the user via mouse or keyboard (user event)
        or also by the running program (software event). The events
        are:

        Event               type            description
        -----------------------------------------------------------
        clickedInContent    mouse, user     User clicked into the content
                                            region of the window (controls
                                            and edit fields excluded)
        broughtToFront      mouse, user,    The window has been brought
                            software        to the front, i.e. it has just
                                            become the frontmost window.
        removedFromFront    mouse, user,    the opposite of broughtToFront
                            software
        redefined           mouse, user,    The window size or position has
                            software        been changed
        onlyMoved           mouse, user,    The window's position has been
                            software        changed but not its size
        disappeared         software        The window has been made invisible
        reappeared          software        the opposite of disappeared
        closing             mouse, user,    The window is to be closed,
                            software        i.e. completely removed
                                            from the screen.  Note, that
                                            this event is handled
                                            specially: This handler is
                                            called before the denoted
                                            action has actually taken
                                            place (hence named closing not
                                            closed). Note also, that it is
                                            called after the CloseProc of
                                            the involved window and before
                                            the global MouseHandler
                                            (CloseWindow).  When called
                                            you may safely assume that the
                                            window still exists.  Note
                                            also, that this is the only
                                            closing events related handler
                                            which is callable via
                                            software, i.e. by a call to
                                            RemoveWindow or RemoveAllWindows.

        Window handlers are owned by a single window and are only
        called by the Dialog Machine if an event of the
        corresponding class involves the particular window. See the
        procedures AddWindowHandler and RemoveWindowHandler.

        IMPORTANT NOTE:  A closing window handler MUST NOT call
        RemoveWindow nor RemoveAllWindows, since it is called by
        these procedures (otherwise you will obtain an infinite loop)!

        IMPORTANT RECOMMENDATION:  It is highly recommended and a
        safe programming practice to set your window variable (not
        the actual argument passed to your closing handler, which
        is only a value parameter) to the value notExistingValue
        within the body of your closing handler routine.
        Example code of a GOOD closing handler which you have
        added to window myWindow:

           PROCEDURE GoodClosingHandler(u: Window);
           BEGIN
             (* do cleaning up of objects associated with myWindow *)
             myWindow := notExistingWindow;
           END GoodClosingHandler;

        Note, the value argument passed to your closing handler by
        the 'Dialog Machine', i.e. u, always points properly at the
        window object, which still exists, since the 'Dialog
        Machine' will only really discard the instantiation of this
        object after the last closing handler had a chance to
        properly handle its closing task. This technique allows to
        associate as many handlers as you wish to the particular
        instantiation of a particular window object. Each closing
        handler should then find the same preconditions, i.e. the
        existence of the object while handling its closing task.
        Hence, you can program every handler as if it would be
        alone and set your opaque window variable to
        notExistingWindow (as an important side effect of your
        closing handler) and leave the rest to the 'Dialog
        Machine'. This programing technique makes it less likely
        that you have dangling pointers to no longer existing
        objects.

        The only situation in which you have to be more cautios is
        the case where you have several handlers which all operate
        on the same master instantiation of the variable of type
        Window (instead of keeping a separate copy). Once a handler
        (the first one), has set this variable to
        notExistingWindow, the closing handlers subsequently called
        by the Dialog Machine will of course no longer have proper
        access to this variable, since the first handler which set
        it to notExistingWindow has cleared it. In this case you
        need to be aware of the coesticence of these handlers and
        you have to program them such, that the first one leaves
        the opaque variable intact and that only the last one does
        actually assign notExistingWindow. Alternatively you can
        use the actual argument passed to you by the 'Dialog
        Machine' to access the object and perform the specific
        cleaning up task and simply assign notExistingWindow to the
        master variable (regardless of any sequence).  In the
        latter case it is NOT a safer programing practice to test
        within the closing handler whether the actual argument and
        your window variable (which you consider to be the same)
        are equal. Example code of a BAD closing handler in a
        multiple handler situation operating on the same window:

           PROCEDURE BadClosingHandler(u: Window);
           BEGIN
             IF u=myWindow THEN
               (* do cleaning up of objects associated with myWindow *)
               myWindow := notExistingWindow;
             ELSE
               (* do nothing *)
             END(*IF*);
           END BadClosingHandler;

        Since the test u=myWindow is likely to fail in a multiple
        handler situation. However it is perfectly ok to do the following:

          PROCEDURE AnotherGoodClosingHandler(u: Window);
          BEGIN
            myWindow := u;
            (* do cleaning up of objects associated with myWindow *)
            myWindow := notExistingWindow;
          END AnotherGoodClosingHandler;


        NOTE: In case there is also a global handler
        (DMMaster.MouseHandler) installed for the particular event,
        that a window handler is normally called before the global
        handler.  Note also that these window handlers are always
        called, regardless whether the event was caused by a user
        or software.  This behavior is different from that of the
        global handlers, which are only called if the event is
        caused by a user event.  Howeve, the use of global handlers
        via DMMaster is discouraged, since it runs contrary to
        information hiding.
      *)



  VAR
    notExistingWindow: Window;  (* read only var! *)
      (*
        Read only variable which may be used for variables of type
        Window to denote that the associated window is actually
        not existing, i.e. not displayed on the screen.  It is a
        good programming practice to assign this value to all
        window variables during the initialization phase of the
        "Dialog Machine", i.e. before calling procedure
        DMMaster.RunDialogMachine.
      *)

    background: Window;
      (*
        This is a predefined window covering the whole screen
        except for the menu bar.  It is always provided
        automatically by the "Dialog Machine" and cannot be
        removed, dragged, put on top, nor resized.  The origin of
        its pixel coordinate system cannot be moved and is at the
        lower left corner of the screen. The background window has
        no title bar and it's content is by default filled with the
        DMWindIO. GreyContent grey. The background resembles the
        desktop; however, it is different in the following respect:
        It is possible to make output in the background like in any
        other ordinary window maintained by the "Dialog Machine".
        To better support the new operating systems on the Macintosh,
        the background is initially no longer visible unless you call
        ReshowBackground.
      *)

    WindowsDone: BOOLEAN;  (*indicates success of a window
                           management procedure*)



  PROCEDURE NoBackground;
      (* Call this procedure if your application does not need the
         background window (is initially default). *)

  PROCEDURE ReshowBackground;
      (* Call this procedure if your application needs the
         background again, e.g. after NoBackground. *)

  PROCEDURE OuterWindowFrame(innerf: WindowFrame; wk: WindowKind;
                             s: ScrollBars; VAR outerf: RectArea);
    (*
      Calculates from the working area f within a window the outer
      frame of the window of kind wk and with scrollbars s (reverse
      of procedure InnerWindowFrame). Typically this procedure is
      called before calling CreateWindow in order to determine the
      exact position of the window relative to the background. This
      routine does not work on a modal window. A modal window of
      kind DoubleFrame which has no scroll bars has an outer frame
      of 7 pixels larger than the innerf.

    *)

  PROCEDURE InnerWindowFrame(outerf: WindowFrame; wk: WindowKind;
                             s: ScrollBars; VAR innerf: RectArea);
    (*
      Calculates from the outer window frame outerf from a window
      of kind wk and with scrollbars s the inner working area
      innerf (reverse of procedure OuterWindowFrame). Typically
      this procedure is called before calling CreateWindow in order
      to determine the parameter f of type WindowFrame used in
      parameter list of CreateWindow given a particular outer size
      of the window. This routine does not work on a modal window.
    *)

  PROCEDURE CreateWindow(VAR u: Window; wk: WindowKind;
                         s: ScrollBars; c: CloseAttr; z: ZoomAttr;
                         fixPoint: WFFixPoint; f: WindowFrame;
                         title: ARRAY OF CHAR;
                         Repaint: RestoreProc);
    (*
      Creates and opens a window of kind wk, titlestring title,
      with its lower left corner at position (f.x,f.y) and with
      width f.w and height f.h.  Attribute wk specifies whether the
      window may be resized or has to keep its size always, plus
      whether it may be dragged or has to stay at the same screen
      location for its whole existence.  Attribute s determines the
      type of ScrollBars of the window, i.e. vertical and/or
      horizontal scroll bars. Attribute c specifies whether the
      window may be closed via a close box shown in the upper left
      corner of a window's title bar. Windows of type
      "GrowORShrinkOrDrag" may have a so called zoom box in the upper
      right corner of the window's title bar. By clicking inside this zoom
      box, the window will be enlarged to the entier screen size or
      (with a second click) resized to it's original size before the
      zooming. fixPoint denotes the point of the window content, which
      will stay at it's position if the window grows or shrinks.
      By default it specifies the origin (0,0) of the local window
      coordinate system.
      A window identifier u is returned for future references. Procedure
      Repaint will be invoked in case the window has to be restored, i.e.
      its whole content has to be redrawn.
    *)

  PROCEDURE CreateModalWindow(VAR u: Window; wk: ModalWindowKind; s: ScrollBars;
                              f: WindowFrame; Repaint: RestoreProc);
    (*
      Creates and opens a window of kind wk with its lower left
      corner at position (f.x,f.y) and with width f.w and height
      f.h.  In case f.x or f.y define a point outside the main
      screen the window will be automatically centered in the
      middle of the screen.  Attribute wk specifies whether the
      window will have a double frame (recommended standard type
      for modal dialogs) or will have a simple frame and a shadow.
      Modal windows are typically used for modal dialogs (see
      procedure UseWindowModally), i.e. during a modal dialog such
      a window can't be dragged, nor zoomed, nor closed via
      clicking into the close box. Attribute s determines the type
      of ScrollBars of the window, i.e. vertical and/or horizontal
      scroll bars. The origin (0,0) of the local window coordinate
      system is always at the lower left corner. A window
      identifier u is returned for future references. Procedure
      Repaint will be invoked in case the window has to be
      restored, i.e. its whole content has to be redrawn.
    *)

  PROCEDURE UsePredefinedWindow(VAR u: Window;
                                fileName: ARRAY OF CHAR;
                                windowID: INTEGER;
                                fixPoint: WFFixPoint;
                                Repaint : RestoreProc);
    (*
      Creates a predefined window read from a Macintosh resource of
      the type "WIND" with ID = windowID contained in the resource
      fork of the file fileName.  In case that the fileName passed
      is empty, the default search strategy to find the resource is
      followed.  For the other parameters see procedure
      CreateWindow.
      The following rules apply when mapping Macintosh procIDs with
      the type WindowKind from DMWindows (see also Inside Macintosh
      I-273, Fig.4):

      procID                WindowKind              Resize  drag    title
      ------                ----------              ------  ----    -----
      documentProc (0)      GrowOrShrinkOrDrag      yes     yes     yes
      noGrowDocProc (4)     FixedSize               no      yes     yes
      plainDBox† (2)        FixedLocation†          no      no      no
      - (not available)     FixedLocTitleBar        no      no      yes

                            ModalWindowKind
                            ---------------
      dBoxProc° (1)         DoubleFrame°            no      no      no
      altDBoxProc (3)       SingleFrameShadowed     no      no      no

      † This type is used by the Dialog Machine for modal entry forms
        (see DMEntryForms)
      ° This type is used by the Dialog Machine for the modal alerts
        (see DMAlerts)

      procID values different from any of those values given above (i.e.
      0..4) are interpreted to code for WindowKind FixedLocTitleBar.
    *)


  CONST
    DoubleFrameTitled = 3;

  PROCEDURE CreateTitledModalWindow(VAR u: Window; title: ARRAY OF CHAR;
                                    f: WindowFrame);
    (*
      Creates a double framed but titled and movable modal dialog
      window. This function is only available under system 7.0.
      The value for argument wk (see GetWindowCharacteristics)
      returned is DoubleFrameTitled.
    *)



  PROCEDURE AttachWindowObject(u: Window; obj: ADDRESS);
  PROCEDURE WindowObject(u: Window): ADDRESS;
    (*
      Attaches to the window u an object in memory at address obj.
      The attach allows the calling program to associate its own
      objects, e.g. a data structure with a window for reference to
      that object.  Typically a mouse handler (see DMMaster) may
      profit from this mechanism, since it returns the window in
      which the user event has taken place, which allows the
      programer to access directly the associated object by calling
      procedure WindowObject from within the mouse handler
      procedure without having frist to search the object. Attach
      NIL to detach an object.
    *)

  PROCEDURE RedefineWindow(u: Window; f: WindowFrame);
    (* Change size or position of window *)

  PROCEDURE RedrawTitle(u: Window; title: ARRAY OF CHAR);

  PROCEDURE MakeWindowInvisible(u: Window);
  PROCEDURE MakeWindowVisible  (u: Window);
  PROCEDURE IsNowVisible       (u: Window): BOOLEAN;

  PROCEDURE WindowLevel(u: Window): CARDINAL;
    (*
      Returns the level of the sub-program on which the window u
      has been created. If the window does not exist it returns
      DMSystem.startUpLevel-1, i.e. 0.
    *)

  PROCEDURE GetWindowCharacteristics(u: Window;
                         VAR wk: INTEGER; VAR modalKind: BOOLEAN;
                         VAR s: ScrollBars; VAR c: CloseAttr; VAR z: ZoomAttr;
                         VAR fixPoint: WFFixPoint; VAR f: WindowFrame;
                         VAR title: ARRAY OF CHAR);
    (*
      Returns the characteristics of the window u.  Note that wk
      either holds the ORD(WindowKind) or ORD(ModalWindowKind) value,
      depending whether the window is an ordinary window (modalKind
      = FALSE) or a modal window (modalKind = TRUE).
    *)



  (*********************************************************************

     Window Updating:

     If a part of a window becomes visible again after beeing covered
     by another window or Desk Acessory, this part of the window content
     must be restored.
     The best way to do this is to pack all drawing procedures (offered by
     DMWindIO) into a procedure of type RestoreProc (see above) and to
     pass it eigther by procedure CreateWindow or SetRestoreProc to the
     Dialog Machine. In this case the Dialog Machine cares about the entier
     restoring of a window in the way that only the just discovered
     part(s) of the window will actually been drawn (necessary for drawing
     with mode invert).

     On the other hand this module offers an automatic restore mechanism,
     wich will maintain a copy in memory (bit map) of all drawings into the
     specified window. This mechanism is very fast but needs quit a lot of
     memory (default on Mac Plus and Mac SE apr. 22 kBytes and on Mac II
     36 kBytes). This update mechanism may only restore in one single color,
     mainly in the last assigned window color by DMWindIO.SetColor.

     This procedure should be used in case the recalculation of the window
     content takes a long time and would slow down execution speed
     dramatically or in simple programs to minimize devellopement expense.

     The automatic restore mechanism my be used in two different ways:

     1. By simple assigning the procedure AutoRestoreProc to the Dialog Machine
        by procedure CreateWindow or SetRestoreProc default hidden bit map size
        is used which is as large as the  maximum possible window size ( Size =
        (ScreenHeight - MenuBarHeigth) * ScreenWidth ). This guarantees that the
        whole window content may automatically be restored if the window content
        will never be scrolled.

     2. With the procedure StartAutoRestoring you may assign a rectangle area
        to the auto restore mechanism in which the mechanism will maintain any
        restoring. This is very usefull in the case of very large video displays
        or if multiple video displays are used simultaneously. Then you may
        combine the auto update mechanism inside this RectArea together with
        your own (written) restore procedure for the rest of the window. To do
        this you FIRST assign your update procedure which itself calls the
        procedure AutoRstoreProc to the Dialog Machine and SECOND you define
        the rect area to be maintained by calling the procedure StartAutoRestring
        (which will not change the assigned RestoreProc but will allocate the
        hidden bit map).

     The restore procedure may be changed any time but this will cause the loss
     of the content in the hidden bit map.


  *********************************************************************)



  PROCEDURE DummyRestoreProc(u: Window);
    (*using this restore procedure results in no updating at all*)

  PROCEDURE AutoRestoreProc(u: Window);
    (*
      Assigning this restore procedure directly to the Dialog
      Machine results in an automatic updating, i.e. no application
      provided restore procedure is called.  Note, that this update
      mechanism uses memory space, since for every window updated,
      a bitmap accommodating the maximum window size has to be
      provided (on older Macintosh with built in screens (e.g. Mac
      Plus) approximately 22KBytes). NOTE:  This procedure is not
      capable to restore the window content if it contained
      different colors!
    *)



  PROCEDURE SetRestoreProc(u: Window; r: RestoreProc);
    (*
      Sets r as the new restore procedure.  If r is equal the
      AutoRestoreProc a hidden bit map is allocated and if r is
      different to AutoRestoreProc an eventually allocated hidden
      bit map is removed.
      NOTE:  Calling this procedure will result in an eventual
      reinitialization, hence clearing of the hidden bit map if it
      has been used previously.  r is called once immediately after
      the installation.
    *)

  PROCEDURE GetRestoreProc(u: Window; VAR r: RestoreProc);
    (*
      Returns the current used Restore procedure of the window u.
    *)


  PROCEDURE StartAutoRestoring(u: Window; r: RectArea);
    (*
      It is possible to maintain the rectangle area r by the auto
      restore mechanism, while restoring the rest of the window by
      your own restore procedure previously assigned by
      SetRestoreProc. If there is enough memory available, the rect
      area r may be set equal to the content size of your document
      and the auto scroll mechanism (see DMWindIO) may be used
      together with the auto restoring. If you dynamically change
      the size of r with this procedure the previous content of the
      hidden bit map is destroyed.
    *)


  PROCEDURE StopAutoRestoring(u: Window);
    (*
      stops the autorestore mechanism for this window u and
      deallocates the used hidden bit map.
    *)

  PROCEDURE AutoRestoring(u: Window): BOOLEAN;
    (*
      returns TRUE if current restore mechanism of window u is
      performed by procedure DMWindows.AutoRestoreProc
    *)


  PROCEDURE GetHiddenBitMapSize(u: Window; VAR r: RectArea);
    (*
      Returns the current Size of the used hidden bit map.
    *)

  PROCEDURE UpdateWindow(u: Window);
    (*
      This procedure forces the update of the window u. The standard
      update mechanism is used which guarantees that only an eventually
      newly become discovered part of the window will actually beeing
      drawn.

      NOTE: The usage of this procedure is ONLY necessary if you want a
      window beeing updated earlier than the 'Dialog Machine' would do it.
      In the Batch 'Dialog Machine' this routine does flush the standard
      output and standard error if you use the 'background' for the actual
      argument.
    *)

  PROCEDURE InvalidateContent(u: Window);
    (*
      In contrast to the procedure UpdateWindow, this procedure declares
      the entier window content as invalid, just like it would have got
      visible after beeing totally covered by another window. It does not
      call the window update procedure directly, but the Dialog Machine
      will, when it handles the update event, call the window specific
      update procedure. Then the entire content will be redrawn.

      This procedure is very useful in case the information visible in a
      window should be changed. Then all drawing routines may be packed
      into a own written update procedure, which will update the
      information on screen.
    *)

  PROCEDURE UpdateAllWindows;   (*only used by the "Dialog Machine"*)
  PROCEDURE RedrawBackground;   (*only used by the "Dialog Machine"*)



  PROCEDURE SetCloseProc(u: Window; cp: CloseProc);
  PROCEDURE GetCloseProc(u: Window; VAR cp: CloseProc);
    (*
      Sets or gets cp as the close procedure for window u.  Note
      that a close procedure asks the user for confirmation before
      actually closing the window.
    *)


  PROCEDURE AddWindowHandler(u: Window; wh: WindowHandlers; wp: WindowProc;
                             priority: INTEGER);
  PROCEDURE RemoveWindowHandler(u: Window; wh: WindowHandlers; wp: WindowProc);
    (*
      Adds or removes a so-called window handler to a particular
      window. Each handler handles only a particular class of
      events; for a description of the events see above comment for
      type WindowHandlers. Each time the Dialog Machine detects an
      event involving a window, it checks whether any handlers are
      installed for that window.  In case it finds one for the
      given class of event, it calls it by passing the involved
      window u as the actual argument.  Multiple handlers can be
      installed, even for the same class of events.  In case of the
      latter situation, the priority decides which handler will be
      called first (0 = highest priority).  In case there should
      still be a conflict (same event class, same priority), the
      handler installed last will be called first (LIFO-queue).  To
      remove a handler, you must be the "owner" of the window
      procedure; i.e. only if exactly the same wp is passed as
      actual argument during removal as was used when installing
      it, RemoveWindowHandler will succesfully remove the handler.
    *)

  PROCEDURE GetWFFixPoint(u: Window; VAR loc: WFFixPoint);
    (*
      Returns loc as the fixpoint on the window frame relative to
      which the window content is positioned during all subsequent
      redefinitions of the window size (redefine event). This point
      is by default equal the origin (0,0) of the local window
      coordinate system.
    *)



  PROCEDURE DoForAllWindows(action: WindowProc);
    (* Execute procedure action for all windows *)


  PROCEDURE GetWindowFrame(u: Window; VAR f: WindowFrame);


  PROCEDURE PutOnTop(u: Window);
    (*
      Put window u in front of all other windows and make it the
      active window by deactivating the previously frontmost
      window
    *)

  PROCEDURE UseWindowModally(u: Window;
                             VAR terminateModalDialog,
                             cancelModalDialog: BOOLEAN);
    (*
      Use the window u for a modal dialog which implies the
      following action taken by the Dialog Machine:  In case u is a
      draggable window it will be placed in the centre of the main
      screen, put on top of all windows, terminateModalDialog and
      cancelModalDialog will be set to FALSE.  Then all user events
      other than mouse clicks in the content of u or in the close
      box of u (if it has one), or keyboard events, are not
      accepted. In particular user events such as dragging, menu
      selection, clicking in another window etc. are ignored and
      the Dialog Machine will sound a beep instead.  This behavior
      is typical for a modal dialog, i.e. such a dialog does not
      allow the user to proceed with anything than what is allowed
      in the modal dialog.  Hence, try to avoid modal dialogs, use
      so-called modeless dialogs instead.  The latter allow the
      user to divert his attention away from the dialog and
      complete first another task before resuming the original
      dialog. This may be quite important, for instance if the user
      wishes to look up a number before he makes an entry etc. On
      the other hand, experience shows that reasonably used, modal
      dialogs can be very effective and simple to comprehend, not
      only for the programmer but also for the user!

      It is important to ensure that the window contains an
      appropriate push buttons, or content handlers which are
      capable of setting either terminateModalDialog or
      cancelModalDialog to TRUE.  This is because the "Dialog
      Machine" allows to terminate the modal dialog only if one of
      the following conditions is satisfied:

        o the calling program sets terminateModalDialog to
          TRUE (e.g. via a push button). Note that installing a
          so-called default push button (see module DMEditFields
          procedure UseAsDefaultButton) allows to select that
          button also via the keyboard, i.e. by typing Return (in
          case no text field is currently selected) or via the
          Enter key, or

        o the calling program sets cancelModalDialog to
          TRUE (e.g. via a push button), or

        o the user presses the Command-key simultaneously with the
          period "." ("Dialog Machine" sets cancelModalDialog
          to TRUE), or

        o the user types Escape ("Dialog Machine" sets
          cancelModalDialog to TRUE), or

        o if the window has a close box the user closes it
          via its close box ("Dialog Machine" sets
          cancelModalDialog to TRUE).

      Note that in the first two cases the client program is
      causing the dialog termination, in the latter cases the
      "Dialog Machine" will assign a value to the variable
      cancelModalDialog without any intervention by the client
      program.  Otherwise the "Dialog Machine" won't have any
      effect on the values of terminateModalDialog or
      cancelModalDialog.  This allows the calling program to detect
      always how the dialog has been terminated.

      In order to avoid user confusion you can apply such modal
      dialogs only to windows which have been created by
      calling

          CreateModalWindow

      or then to a window of one of the following tyes:

        - FixedSize and WithoutZoomBox
        - FixedLocation
        - FixedLocTitleBar and WithoutZoomBox

      If you call this procedure with a window different from any
      of the types listed the procedure will immediately return and
      have no effect except that it sets dialogAborted to TRUE. It
      is recommended not to run modal dialogs on windows with a
      close box.

      Here a sample program text demonstrating the use of procedure
      UseWindowModally by implementing an entry form (see module
      DMEntryForms) containing one integer field:

        VAR
          myEntryForm: DMWindows.Window;  wf: DMWindows.WindowFrame;
          acceptIt, cancelled, entryFormOk:     BOOLEAN;
          theInt1, origInt1, theInt2, origInt2: INTEGER;
          intF1, intF2, okBut, cancelBut:       DMEditFields.EditItem;
        ...
        PROCEDURE DoOk;
        BEGIN
          acceptIt := DMEditFields.IsInteger(intF1, theInt1) AND
                      DMEditFields.IsInteger(intF2, theInt2);
        END DoOk;

        PROCEDURE DoCancel;
        BEGIN
          cancelled:=TRUE;  theInt1:=origInt1;  theInt2:=origInt2;
        END DoCancel;
        ...
        origInt1:=theInt1;  origInt2:=theInt2;  wf.w:=360;  wf.h:=120;
        wf.x := (DMWindIO.BackgroundWidth()-wf.w) DIV 2;
        wf.y := (DMWindIO.BackgroundHeight()-wf.h) DIV 2;
        DMWindows.CreateModalWindow(myEntryForm, DMWindows.SingleFrameShadowed,
                                    DMWindows.WithoutScrollBars, wf,
                                    DMWindows.AutoRestoreProc);
        DMWindIO.SetWindowFont(DMWindIO.Chicago, 12, DMWindIO.FontStyle{});
        DMEditFields.MakeIntField(myEntryForm,
                                 intF1, (wf.w-6*DMWindIO.CellWidth()) DIV 2,
                                 88, 6, theInt1, MIN(INTEGER), MAX(INTEGER));
        DMEditFields.MakeIntField(myEntryForm,
                                  intF2, (wf.w-6*DMWindIO.CellWidth()) DIV 2,
                                  66, 6, theInt2, MIN(INTEGER), MAX(INTEGER));
        DMEditFields.MakePushButton(myEntryForm, okBut, wf.w-75-14,
                                    22, 75 DIV DMWindIO.CellWidth(),
                                    DMLanguage.okButtonText, DoOk);
        DMEditFields.UseAsDefaultButton(okBut);
        DMEditFields.MakePushButton(myEntryForm, cancelBut, 14, 22,
                                    75 DIV DMWindIO.CellWidth(),
                                    DMLanguage.cancelButtonText, DoCancel);
        DMEditFields.SelectField(intF1);
        DMWindows.UseWindowModally(myEntryForm, acceptIt, cancelled);
        DMWindows.RemoveWindow(myEntryForm);
        entryFormOk := NOT cancelled;

      Above code is equivalent to:

        VAR ef: DMEntryForms.FormFrame; entryFormOk: BOOLEAN; theInt1,theInt2: INTEGER;
        ...
        DMEntryForms.IntField(2, 20, 7, theInt1, useAsDeflt, MIN(INTEGER), MAX(INTEGER));
        DMEntryForms.IntField(3, 20, 7, theInt2, useAsDeflt, MIN(INTEGER),MAX(INTEGER));
        ef.x:=0;  ef.y:=-1;  ef.lines:=5;  ef.columns:=45;
        DMEntryForms.UseEntryForm(ef, entryFormOk);

    *)


  PROCEDURE FrontWindow(): Window;
    (* returns currently frontmost window *)

  PROCEDURE WindowExists(u: Window): BOOLEAN;
    (*tests whether window u currently exists*)


  PROCEDURE RemoveWindow(VAR u: Window); (*upon returning u = nonexistent*)
  PROCEDURE RemoveAllWindows;

END DMWindows.

  Contact RAMSES@env.ethz.ch Last updated: 25-Jul-2011 [Top of page]