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 Buttons;

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

    Module  Buttons     (Version 2.0)

      Copyright (c) 1990-2006 by Olivier Roth, Frank Thommen, Andreas
      Fischlin and ETH Zurich.

    Purpose   Installation and usage of custom push buttons, such
              as button palettes.

    Remarks   Buttons function similar to DMEditFields.Button
              but are
                - not restricted to text
                - not restricted to system font (Chicago 12)
                - not framed with rounded corner rectangles.
              Any content of a button has to be drawn/
              written by an installed draw procedure.


    Programming

      o Design
        Olivier Roth              17/04/1990 (V1.0)
        Frank Thommen             25/03/1994 (V2.0)
        Andreas Fischlin          25/03/1994 (V2.0)

      o Implementation
        Olivier Roth              17/04/1990
        Frank Thommen             25/03/1994 (V2.0)
        Andreas Fischlin          25/03/1994 (V2.0)


    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:  08/01/1998  FG

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


  FROM DMWindows IMPORT RectArea, Window;

  TYPE
    Button;
    ButtonActionProc =   PROCEDURE( Button );
    (*
     *   Buttons belong to a window and may be installed in any number.
     *   Each button is associated with an action, implemented
     *   as a client procedure, which is called by this module as
     *   soon as the button is clicked via the mouse or if an
     *   associated keyboard equivalent is pressed. *)

    ButtonDrawProc   =   PROCEDURE( Button, RectArea );
    (*
     *   Individual buttons are typically drawn similar to the technique
     *   demonstrated by the following button drawing procedure:
     *
     *     PROCEDURE MyButtonDrawing( button: Button; btnFrame: RectArea );
     *     BEGIN
     *       SelectForOutput(buttonOwnerWindow);
     *       DisplayPredefinedPicture(buttonPicFile,butPictID,btnFrame);
     *     END MyButtonDrawing;
     *
     *   See also auxiliary procedure DrawTextButton below for further
     *   techniques to draw buttons and the concept of palettes, in
     *   particular PaletteDrawProc and AggregatePalette. *)

    PaletteDrawProc  =   PROCEDURE( INTEGER );
    (*
     *   Buttons may be grouped into palettes which are typically
     *   drawn by the following palette drawing procedure:
     *
     *     PROCEDURE MyPaletteDrawing( palNr: INTEGER );
     *       VAR palPictID: INTEGER;
     *     BEGIN
     *       SelectForOutput(paletteOwnerWindow);
     *       palPictID := palNr;
     *       DisplayPredefinedPicture(palettePicFile,palPictID,paletteFrame);
     *     END MyPaletteDrawing;
     *
     *   For more details on the concept of palettes, see procedure
     *   AggregatePalette. *)


  VAR
    notInstalledButton: Button;
      (* READ ONLY variable which may be used for variables of
       * type Button to denote that it has not yet been installed,
       * i.e. InstallButton has not been called.  It is a good
       * programming practice to assign this value to all Button
       * variables during the initialization phase.  *)



  PROCEDURE InstallButton ( VAR btn     : Button;
                            btnFrame    : RectArea;
                            buttonAction: ButtonActionProc;
                            drawButton  : ButtonDrawProc   );
    (* Buttons are always associated to the current output window!
     * When installed the "drawButton" procedure is called to draw the
     * button's content. "drawButton" is also called after the termination
     * of the "buttonAction" procedure.
     * Removal of the owner window will remove all installed buttons
     * automatically without writing back into the variable btn;
     * NOTE that the btn keeps a value different from
     * notInstalledButton! *)

  PROCEDURE ButtonExists( btn: Button ): BOOLEAN;
    (* Returns wether button btn currently exists *)

  PROCEDURE RemoveButton( VAR btn: Button );
    (* Frees the allocated memory, blanks the area of button btn and ceases
     * to react on clicks into the former button's area. The variable
     * btn becomes the value notInstalledButton. *)


  PROCEDURE RemoveAllButtonsOfWindow( w: Window );
    (* Removes all buttons of the specified window as described by
     * "RemoveButton" but the clients button variables are not updated,
     * i.e. not set to notInstalledButton!! *)


  PROCEDURE SetToDefaultButton ( w              : Window;
                                 btn            : Button;
                                 drawDefltButton: ButtonDrawProc );
    (* Declares the button btn as default button.  This affects first the
     * display of btn as follows:
     *
     * 1. the button is redrawn with procedure drawDefltButton (see special
     *    procedures for text buttons below.
     *
     * 2. an alias char or keyboard equivalent is installed, so that
     *    button can be activated via the enter or return key. Note that
     *    keyboard equivalents are only accepted if the owner window is the
     *    active window. In case the owner window already knows a default
     *    button, the old one ceases to function as a default button and btn
     *    becomes the new default button. *)

  PROCEDURE NoDefaultButton ( w: Window );
    (* Reverts the effect of procedure SetToDefaultButton, i.e. the
     * current default button of window w is no longer displayed with the
     * special procedure drawDefltButton (the area passed in drawDefltButton
     * is cleared, and the button redrawn with it's normal ButtonDrawProc)
     * and neither the enter nor return keys execute the associated button
     * action any more. *)

  PROCEDURE GetDefaultButton( w: Window; VAR btn: Button );
    (* Returns in btn the default button of window w.  In case
     * w has no default button, btn is set to notInstalledButton. *)


  PROCEDURE SetButtonAliasChar ( btn: Button; modif: BITSET; aliasChar: CHAR );
    (* The character aliasChar serves as a keyboard equivalent while the
     * window of the button btn is active, e.g. is the topmost window.
     * Use 0C to denote a button without a keyboard equivalent. modif are
     * modifiers and designate whether aliasChar has to be pressed simultaneously
     * with so called modifier keys such as the Command key (For further
     * details of modifiers see procedure InspectKey from module DMMaster).
     * Note that menu commands with a conflicting alias character are
     * executed first; moreover, if several buttons within the same
     * window have the same alias character, that button is executed
     * which has been installed first. *)

  PROCEDURE DisableButton( btn : Button );
  PROCEDURE EnableButton ( btn : Button );
    (* Dis/enables the specified button's function and dimms/redraws
     * its content. *)

  PROCEDURE IsEnabled ( btn: Button ): BOOLEAN;
    (* Returns wether or not the button btn is enabled.  Returns FALSE
     * for not installed buttons. *)



  (*========================*)
  (* Additional procedures: *)
  (*========================*)

  PROCEDURE SetButtonNr ( btn: Button;  btnNr: INTEGER );
    (* Allows to associate the number btnNr with button btn. *)

  PROCEDURE ButtonNr ( btn: Button ): INTEGER;
    (* Returns the chronological or explicitely set number of button btn.
     * If a nonexisting button is passed MIN(INTEGER) is returned. *)

  (*
    The feature of associating a btnNr with buttons may be used
    to maintain an array of buttons, e.g.

       myBtns: ARRAY [1..maxBtn] OF RECORD btn: Button; myField: ...

    procedure ButtonNr may then be used to find the
    corresponding index of btn and loops operating on the
    whole array can be programmed.
  *)


  PROCEDURE OwnerWindow( btn: Button): Window;
    (* Returns the window owning the button btn.  In case the button
     * does not exist, the value DMWindows.notExistingWindow is returned. *)


  PROCEDURE SetButtonAttr( btn : Button;
                           btnFrame    : RectArea;
                           btnAction   : ButtonActionProc;
                           drawButton  : ButtonDrawProc   );

  PROCEDURE GetButtonAttr( btn : Button;
                           VAR btnFrame    : RectArea;
                           VAR btnAction   : ButtonActionProc;
                           VAR drawButton  : ButtonDrawProc   );


  PROCEDURE DrawTextButton ( btnFrame: RectArea; butText: ARRAY OF CHAR );
    (* Typically this procedure is called from within the drawButton
     * procedure (type ButtonDrawProc) installed via InstallButton.
     * This procedure is useful when the button does not feature
     * an iconic picture, but is labelled by a string and framed
     * by an oval rectangle.  The font, size and style of the label is
     * determined by the current font, size and style defined for the
     * current output window.  Thus use routines from DMWindIO to
     * change these settings according to your needs.  A typical example
     * of such a procedure follows:

        PROCEDURE DrawMyButton(btn: Button; btnFrame: RectArea);
          VAR saveFnt: WindowFont; saveSize: CARDINAL; saveStyle: FontStyle;
        BEGIN
          GetWindowFont(saveFnt,saveSize,saveStyle);
          SetWindowFont( Chicago, 12, FontStyle{} );
          DrawTextButton(btnFrame,"Push me!");
          SetWindowFont(saveFnt,saveSize,saveStyle);
        END DrawMyButton;
     *)

  PROCEDURE DrawDefltButtonFrame ( frame: RectArea );
    (* This procedure draws a bold border around the frame.  It assumes,
     * that frame encloses a button, i.e. corresponds to btnFrame of the button
     * to be marked as the default button. Typically this procedure is used
     * for text buttons, and is called from within your drawDefltButton
     * procedure (see SetToDefaultButton). If the current output window
     * has no default button, this procedure will have no effect.  Example:

        PROCEDURE DrawMyDfltButton(btn: Button; btnFrame: RectArea);
          VAR saveFnt: WindowFont; saveSize: CARDINAL; saveStyle: FontStyle;
        BEGIN
          GetWindowFont(saveFnt,saveSize,saveStyle);
          SetWindowFont( Chicago, 12, FontStyle{} );
          DrawTextButton(btnFrame,"Push me!");
          DrawDefltButtonFrame(btnFrame);
          SetWindowFont(saveFnt,saveSize,saveStyle);
        END DrawMyDfltButton;
     *)

  PROCEDURE AggregatePalette( palNr                : INTEGER;
                              fstBtn,lstBtn: Button;
                              drawPalette  : PaletteDrawProc );
    (* aggregates all buttons from fstBtn to lstBtn into a palette
     * with number palNr. Typical usage of this routines is when a
     * palette is to be drawn as a whole, i.e. it encloses many
     * buttons at once, and which is drawn by means of routine
     * DisplayPredefinedPicture. The drawing procedure might then
     * look similar to this:
     *
     *    PROCEDURE MyPaletteDrawing( palNr: INTEGER );
     *    BEGIN
     *      DisplayPredefinedPicture(palettePicFile,palNr,paletteRect);
     *    END MyPaletteDrawing;
     *
     * And a typical program code using MyPaletteDrawing might look as this:
     *    ...
     *    CreateWindow(paletteOwnerWindow,...
     *    InstallButton( btn1, btnFrame1, btnAction1, DummyButtonDrawing);
     *    InstallButton( btn2, btnFrame2, btnAction2, DummyButtonDrawing);
     *    InstallButton( btn3, btnFrame3, btnAction3, DummyButtonDrawing);
     *    AggregatePalette(btn1,btn3,paletteRect,MyPaletteDrawing);
     *    ...
     *
     * The main reasons for introducing palettes is the following:
     * Redrawing of buttons which are members of a palette is
     * noticably more efficient, since it requires just a single
     * call to the procedure MyPaletteDrawing.  Note, without
     * aggregation the palette would have to be drawn as many times
     * as there are buttons in the palette, since every button to
     * be installed by InstallButton requires an individual button
     * drawing procedure to be called individually, e.g. after
     * activation or during partial updates of the window. To
     * profit from palettes also during updates, call RedrawAllButtons
     * (see below) from within the restore procedure of the owner window.
     * It is highly recommended to call RedrawAllButtons
     * in the restore procedure of the owner window.
     *
     * palNr serves the identification of a particular palette (see
     * below procedures OwnerPalette or DisaggregatePalette). There
     * may be as many palettes you wish and a palette may also
     * consist of just a single button, but you must not use MIN(INTEGER)
     * as a palNr.
     *
     * Important restrictions: fstBtn and lstBtn must belong to the
     * same window and must have been installed in chronological
     * order.  In particular note, removing and reinstalling an
     * individual button disrupts the original sequence; therefore,
     * in case of dynamic palettes, it is recommended to remove and
     * reinstall all palette buttons at once, to ensure always a
     * well defined sequence.
     * palNr must be globally unique in order to identify a
     * particular palette correctly.
     * Finally, SetButtonAttr must use MyPaletteDrawing as actual
     * argument for the formal parameter drawButton when setting the
     * attributes of a palette button, or alternatively, it must also
     * disaggregate and reaggregate the palette as a whole. *)


  PROCEDURE DummyButtonDrawing( dummyBtn: Button; dummyBtnFrame: RectArea );
    (* Recommended drawing procedure to be used as actual parameter when
     * installing individual buttons which belong to a palette. The
     * actual drawing procedure will be installed only when the buttons
     * are aggregated to a palette by a call to AggregatePalette. *)

  PROCEDURE OwnerPalette(btn: Button): INTEGER;
    (* Returns the number of the palette to which button btn belongs.
     * Returns MIN(INTEGER) if btn does not exist. *)

  PROCEDURE GetPaletteDrawProc( palNr: INTEGER;
                                                        VAR pdp: PaletteDrawProc; VAR done: BOOLEAN );
    (* Returns the palette drawing procedure of the palette palNr.  done = TRUE
     * if a palette with number palNr is currently known. *)

  PROCEDURE DisaggregatePalette( palNr: INTEGER );
    (* Reverts for palette palNr the effect of AggregatePalette *)


  PROCEDURE RedrawAllButtons ( w: Window );
    (* Redraws all buttons of window w.  This procedure is typically
     * called by a window restore procedure.  The possibly
     * present default button is automatically redrawn with the
     * drawDefltButton procedure. *)

  PROCEDURE DimmAllDisabledButtons ( w: Window );
    (* Dimms all disabled buttons of the window w.  This procedure
     * is typically called by a window restore procedure. *)

  PROCEDURE DoForAllButtonsOfWindow ( w: Window; proc: ButtonActionProc );
    (* Executes the action procedure proc for all Buttons associated
     * with the window w.  WARNING: Calling RemoveButton within
     * proc may cause problems, if the callee does not assign the
     * value of notInstalledButton to the corresponding opaque
     * master variable of type Button; use RemoveAllButtonsOfWindow
     * instead. *)


END Buttons.

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