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

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

    Module  DMEditFields     ('Dialog Machine' DM_V3.0)

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

    Purpose   Manages modeless dialogs in any window
              offered by DMWindows.

    Remarks   Modeless dialogs allow the user to make
              entries any time he/she wishes, i.e. the user
              may turn his/her attention in the middle of
              data entries to other activities before
              actually completing the dialog by requesting
              the system to do something with the data
              entered.

              EditFields allows the user to enter data to
              an application program.  The entering of
              values for all elementary data types,
              characters, strings, numbers (integers,
              cardinals real), and so called controls
              (pushbuttons, radiobuttons, checkboxes
              scrollbars are supported.

              Method:  Any edit field may be defined by means
              of declarative procedure calls. They define size
              and position of editing fields and return a
              variable for later references to it.
              Fields may be used for the entry of characters,
              strings, and multi lined text, integers, cardinals,
              reals, and other input (e.g. pushbuttons,
              analog input by means of radio buttons, checkboxes
              and scrollbars). positions within the window
              are specified in the local window pixel coordinate
              system (see DMWindows and DMWindIO). DMEditFields
              uses the current window font for text in
              string based edit fields and the system font in
              buttons.

              Once the specification of an edit item has been
              made, it is displayed on the screen and the dialog
              with the user is handled automatically by the
              Dialog Machine.

              In Contrast to DMEntryForms, which offers so-called
              modal dialogs, DMEditFields supports modeless
              dialogs. In this form of dialog the completion of
              an user input is not defined exactly and there is
              no obvious moment for testing for proper syntax and
              correct range. For this reason in contrast to
              DMEntryForms the client program must get the values
              entered by the user and hereby specify the moment
              of testing.  DMEditFields will then test the input
              and display appropriate error messages.

              DMEditFields provides an automatic update mechanism
              for all exported items. But they are not protected
              from beeing overwritten, so this is your
              own responsibility.

              To support full text editing in text fields
              there exists the module DMMakeTextFields, which
              represents an extension of this module.

              This module belongs to the 'Dialog Machine'.


    Programming

      o Design
        Alex Itten                18/01/1987
        Andreas Fischlin          23/11/1989

      o Implementation
        Alex Itten                12/08/1987
        Andreas Fischlin          23/11/1989


    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:  06/09/1995  AF

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


  FROM SYSTEM IMPORT ADDRESS;
  FROM DMWindows IMPORT Window, WindowFrame;


  (*************************************)
  (*#####   Dialog Declarations   #####*)
  (*************************************)

  TYPE
    EditItem;
      (*
        Type used to reference an edit item. A variable of this
        type has to be associated with any edit item and its
        value will be initialized by any declarative
        procedure.
      *)

    RadioBut;  (* Type used to reference a radio button *)

    ItemType = (charField, stringField, textField,
                cardField, intField, realField,
                pushButton, radioButtonSet, checkBox, scrollBar);

  VAR
    EditFieldsDone: BOOLEAN;  (* returns success of any declaration *)
    notInstalledEditItem: EditItem;
    notInstalledRadioBut: RadioBut;
    (*
      Read only variables which may be used for variables of type
      EditItem or RadioBut to denote that the item has not yet been
      installed. It is a good programming practice to assign this
      value to all variables of type EditItem or RadioBut during
      the initialization phase.
    *)


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

   The following procedures provide mechanisms to declare within a
   window so-called edit fields.  Edit fields support the entry and
   editing of elementary data types, i.e.  CHAR, strings (1 or
   several lines of text), INTEGER, CARDINAL, and REAL (in form of
   a textual field or scrollbars), BOOLEAN (check box), sets (radio
   buttons) (number data types are also supported with long
   variants).

   The so-called make procedures used to declare edit fields
   typically define fields with a width fw (in char cells) at a
   particular position within the window given in pixel
   coordinates.  Such edit fields will be displayed by an
   enclosing, rectangular frame.  Every make procedure returns a
   variable of type EditItem which you must use for later
   references.  After the making of an edit item, the 'Dialog
   Machine' will automatically display and update it as needed.

   Furthermore the 'Dialog Machine' provides all editing within
   these fields without any further action of the client program up
   to the moment, whent the client program wishes to actually use
   the values the user has entered.  At that time the 'Dialog
   Machine' will test the data entries for correct syntax and range
   constraints as specified for each field during its declaration
   or making.  More details on this behavior can be found
   in comments below, e.g. in the comment on procedure IsChar.

   For numbers the syntax is that of Modula-2 and the
   ranges of the accepted values may be provided by entering
   appropriate values for the interval boundaries (the interval
   boundaries are also legal values).  An open interval may be
   created by assigning to either of the boundary values the system
   dependent values MIN(Type) or MAX(Type).  The application must
   always provide a default value, which is displayed when the edit
   item is drawn on screen for the first time.

   IMPORTANT NOTE: Due to an implementation restriction you must
     not call any make procedure within a window restore procedure,
     since it will trigger an additional update event, which would
     lead to a never ending chain of update events.  The need to
     call this routine in a restore procedure arises usually, if you
     wish to modify the position of an edit item within a window
     which has changed its size.  Use a redefine handler (see module
     DMWindows procedure AddWindowHandler) to program such a task.

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


  PROCEDURE MakeCharField(u: Window;
                          VAR ei: EditItem;
                          x,y: INTEGER;
                          ch: CHAR;
                          charset: ARRAY OF CHAR);
    (*
      Editing of a single character.  However, the character ch will
      only be accepted if its value is equal to one of the characters
      contained in the string charset (tests are made case sensitive,
      hence to allow for case insensitive entry you must specify in charset
      all possibilities, e.g. "AaBbCcDd..." etc.).  If any character is
      acceptable, pass an empty charset ("").  Normally exactly one character
      must be entered by the user, i.e. not none nor more than one character
      are acceptable.  There can be made an exception to this rule so
      that no entry becomes acceptable too, by listing the character
      ASCII DEL (177C) as the very first in charset.
    *)



  PROCEDURE MakeStringField(u: Window;
                            VAR ei: EditItem;
                            x,y: INTEGER;
                            fw: CARDINAL;
                            string: ARRAY OF CHAR);
    (* any string may be edited *)

  PROCEDURE MakeTextField(u: Window;
                          VAR ei: EditItem;
                          x,y: INTEGER;
                          fw,lines: CARDINAL;
                          text: ARRAY OF CHAR);
    (*
      Text fields differ from string fields only inasmuch as they offer
      more than a single line , i.e.  'lines' lines of editing.  There is
      an automatic word wrap arround and scrolling mechanism available.
      However note, for a full fledged editing of texts there are other
      routines available from module DMMakeTextFields, which allows to
      easily implement a full text editor.
    *)




  PROCEDURE MakeCardField(u: Window;
                          VAR ei: EditItem;
                          x,y: INTEGER;
                          fw: CARDINAL; (*maximum number of digits expected*)
                          card: CARDINAL;
                          minCard,maxCard: CARDINAL);
  PROCEDURE MakeLongCardField(u: Window;
                              VAR ei: EditItem;
                              x,y: INTEGER;
                              fw: CARDINAL; (*maximum number of digits expected*)
                              card: LONGCARD;
                              minCard,maxCard: LONGCARD);
    (*
      The cardinal is only accepted if its syntax is legal and if
      card falls within subrange [minCard..maxCard]
    *)

  PROCEDURE MakeIntField(u: Window;
                         VAR ei: EditItem;
                         x,y: INTEGER;
                         fw: CARDINAL; (*max number of digits+1 expected*)
                         int: INTEGER;
                         minInt,maxInt: INTEGER);
  PROCEDURE MakeLongIntField(u: Window;
                             VAR ei: EditItem;
                             x,y: INTEGER;
                             fw: CARDINAL; (*max number of digits+1 expected*)
                             int: LONGINT;
                             minInt,maxInt: LONGINT);
    (*
      The integer is only accepted if its syntax is legal and if it
      falls within subrange [minInt..maxInt]
    *)

  PROCEDURE MakeRealField(u: Window;
                          VAR ei: EditItem;
                          x,y: INTEGER;
                          fw: CARDINAL; (*max number of digits+4 expected*)
                          real: REAL;
                          minReal,maxReal: REAL);
  PROCEDURE MakeLongRealField(u: Window;
                              VAR ei: EditItem;
                              x,y: INTEGER;
                              fw: CARDINAL; (*max number of digits+4 expected*)
                              real: LONGREAL;
                              minReal,maxReal: LONGREAL);
    (*
      Real is only accepted if its syntax is legal and if its value
      falls within interval [minReal..maxReal]
    *)




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

    Graphical data entry facilities found in most graphical user
    interfaces, like scroll bars, check boxes etc., are supported by
    the following objects.

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


  PROCEDURE MakePushButton(u: Window;
                           VAR ei: EditItem;
                           x,y: INTEGER;
                           buttonWidth: CARDINAL;         (*in char cells*)
                           buttonText: ARRAY OF CHAR;
                           pushButtonAction: PROC);
    (*
      The pushbutton labelled with the text buttonText (displayed
      in the middle of the pushbutton in system font) is placed
      with its lower left point at x and y. buttonWidth defines the
      witdh of the pushbutton in character cells (ca. 8 pixel). If
      the pushbutton is pressed (mouse click within the button),
      the associated procedure pushButtonAction is called.
    *)

  PROCEDURE UseAsDefaultButton(pushButton: EditItem);
    (*
      The edit item pushButton is used as the so-called default button in a
      window during a modal dialog as run by procedure UseWindowModally
      from module DMWindows.  The default button has a thicker border and
      can be activated by pressing the Enter key or the Return key (the
      latter only in case that no MakeTextField is present) as an
      alternative to the activation by the mouse.
    *)




  PROCEDURE BeginRadioButtonSet(u: Window; VAR ei: EditItem);
    (*
      Radio buttons offers a selection of "one choice out of n
      possibilities". So every radio button is associated with its
      logical group called a "radio button set". This set is
      defined by BeginRadioButonSet and EndRadioButtonSet. Between
      them you may define as many RadioButtons as you like. Only
      complete RadioButtonSets may be removed or disabled, not any
      radio button seperatedly.
    *)

  PROCEDURE AddRadioButton(VAR radButt: RadioBut;
                           x,y: INTEGER;
                           text: ARRAY OF CHAR);
    (*
      The radio button is placed with its lower left point at x and
      y. The string text is written to the right of the radio
      button.
    *)

  PROCEDURE EndRadioButtonSet(selRadioButton: RadioBut);
    (*
      The initially selected button is defined by passing its
      reference variable radButt to selRadioButton.
    *)


  PROCEDURE MakeCheckBox(u: Window;
                         VAR ei: EditItem;
                         x,y: INTEGER;
                         text: ARRAY OF CHAR;
                         boxChecked: BOOLEAN);
    (*
      The check box is placed with its lower left point at x,y and
      the text is written to the right of the check box. The
      initial selection is determined by the value assigned to
      variable boxChecked.
    *)


  TYPE
    Direction = (horizontal, vertical);

  PROCEDURE MakeScrollBar(u: Window;
                          VAR ei: EditItem;
                          x, y, length: INTEGER;
                          sbd: Direction;
                          minVal,maxVal: REAL;
                          smallStep, bigStep: REAL;
                          curVal: REAL;
                          actionProc: PROC);
    (*
      Scrollbars are located by specifying their lower left point
      (x,y), their direction (sbd) and  their length. A minimum
      length of 60 pixel must be specified for correct appearance
      and the width is always set to 16 pixel. smallStep defines
      the intervall which the thumb (white caret in the scrollbar)
      is moved, when the user clicks within the up or down arrow.
      bigStep is used when he clicks inside the grey (dotted)
      "page-up" or "page-down" region. The initial setting of the
      scroll box is determined by the value assigned to curVal. The
      action procedure is called once or repeatedly when the user
      keeps the mouse button pressed. This procedure may be used
      for example to write the current value anywhere on the screen
      using standart window IO procedures offered by DMWindIO.
    *)




  (************************************************)
  (*#####   EditItem Access and Activation   #####*)
  (************************************************)

  PROCEDURE EditItemExists(ei: EditItem) : BOOLEAN;
    (* returns TRUE if edit item ei exists.  *)

  PROCEDURE RadioButtonExists(rb: RadioBut) : BOOLEAN;
    (* returns TRUE if radio button rb exists.  *)

  PROCEDURE EditItemLevel(ei: EditItem): CARDINAL;
    (*
      Returns the level of the sub-program on which the edit item
      ei has been created. If ei does not exist
      DMSystem.startUpLevel-1, i.e. 0 is returned.
    *)

  PROCEDURE RadioButtonLevel(rb: RadioBut): CARDINAL;
    (*
      Returns the level of the sub-program on which the radio
      button rb has been created. If rb does not exist
      DMSystem.startUpLevel-1, i.e. 0 is returned.
    *)


  (*
    Each edit item is initially enabled so the user may fully edit
    their current values. For temporarily disabling resp.
    reenabling of the editing of items the following two procedures
    are offered.

    Note, for easier recognition by the user disabled items are
    displayed differently, i.e. for string based edit fields such as char,
    string, text, and all number fields, their frame is dotted; for push
    buttons, for check-boxes and radio buttons their text is
    dimmed, for scroll bars their grey-dotted area is blanked and
    the scroll box is no longer visible.  Note however, that the
    programmer has still full access to disabled items via the Set-
    and Get/Is-procedures (see below). Only the user has restricted
    access, i.e. he/she cannot modify the current content of a
    disabled item. However, he/she can still access the content of
    a disabled item for transferring it into the clipboard, i.e.
    the user can make selections in fields which contain text and
    copy the selected characters into the clipboard by pressing the
    command-key simultaneously with the key "C".
  *)

  PROCEDURE DisableItem(ei: EditItem);
  PROCEDURE EnableItem(ei: EditItem);
  PROCEDURE IsEnabled(ei: EditItem): BOOLEAN;

  PROCEDURE SelectField(ei: EditItem);
  PROCEDURE ClearFieldSelection (u: Window);
  (*
    For string based edit fields the entire content of the field
    may be selected (hilited) respectively deselected by these
    procedures. You may use these procedures in a keyboard handler
    (see DMMaster) to use other keys than the tab-key to allow
    him/her to change the current selected edit field via the
    keyboard instead of clicking with the mouse. For example, in
    tables the "User Interface Guidelines" which are published by
    AppleŠ recommend to use a combination of the option and one of
    the arrow keys to skip to adjacent fields. SelectField of a new
    field implies always the deselection of an eventually
    previously selected field.
  *)


  (***********************************************************)
  (*#####   Associating Client Objects with EditItems   #####*)
  (***********************************************************)

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


  (**********************************************)
  (*#####   Altering Values in EditItems   #####*)
  (**********************************************)

  (*
    The current setting or value of edit items may also be changed
    under program control. The reference variable ei is used for
    specifing the item. The edit item will be redrawn to reflect
    the change. If ei does not exist then the current value remains
    unchanged.
  *)

  PROCEDURE SetChar(ei: EditItem; newCh:CHAR);
  PROCEDURE SetString(ei: EditItem; newStr: ARRAY OF CHAR);
  PROCEDURE SetText(ei: EditItem; VAR text: ARRAY OF CHAR);

  PROCEDURE SetCardinal(ei: EditItem;  newValue: CARDINAL);
  PROCEDURE SetLongCardinal(ei: EditItem;  newValue: LONGCARD);
  PROCEDURE SetInteger(ei: EditItem;  newValue: INTEGER);
  PROCEDURE SetLongInteger(ei: EditItem;  newValue: LONGINT);
  PROCEDURE SetReal(ei: EditItem; newValue: REAL);
  PROCEDURE SetLongReal(ei: EditItem; newValue: LONGREAL);

  PROCEDURE SetRadioButtonSet(ei: EditItem;  selRadioButton: RadioBut);
  PROCEDURE SetCheckBox(ei: EditItem; boxChecked: BOOLEAN);
  PROCEDURE SetScrollBar(ei: EditItem; r: REAL);



  (************************************************)
  (*#####   Fetching Values from EditItems   #####*)
  (************************************************)

  PROCEDURE GetEditItemType(ei: EditItem; VAR it: ItemType);

  PROCEDURE IsChar(ei: EditItem; VAR ch:CHAR): BOOLEAN;
    (*
      If ei exists and its type is charField, the procedure tests whether
      exactly one character has been entered and whether it is contained in
      charset as specified during field installation (for more informations
      about how legal characters are tested please refer to the comments of
      procedure MakeCharField).  If the test is passed IsChar returns TRUE,
      else it will display an error message, asking the user to modify the
      character to match a character from charset and then return FALSE.  In
      the latter case the charField will also be selected to give the user
      a hint, which field was accessed; an important information in case of
      multiple edit fields within the same window.  If ei does not exist or
      is not of the proper type an error message will be displayed.
    *)


  PROCEDURE GetString(ei: EditItem; VAR string: ARRAY OF CHAR);
    (*
      Procedure GetString returns the content from a stringField.  All
      characters entered are accepted.  In case that ei does not exist or
      is not of the proper type an error message will be displayed.
    *)


  PROCEDURE GetText(ei: EditItem; VAR text: ARRAY OF CHAR);
    (*
      Procedure GetText returns the text from a textField.  All characters
      entered are accepted.  In case that ei does not exist or is not of
      the proper type an error message will be displayed.
    *)


  PROCEDURE IsCardinal(ei: EditItem; VAR c: CARDINAL): BOOLEAN;
  PROCEDURE IsLongCardinal(ei: EditItem; VAR c: LONGCARD): BOOLEAN;
    (*
      If ei exists and its type is cardField, this procedure tests the
      current field content for correct syntax and range as specified
      during field installation.  If the test is passed the procedure
      returns TRUE, else it will display an error message and then return
      FALSE similar as described under procedure IsChar.  In case that the
      ei does not exist or is not of the proper type an error message will
      be displayed.
    *)



  PROCEDURE IsInteger(ei: EditItem; VAR i: INTEGER): BOOLEAN;
  PROCEDURE IsLongInteger(ei: EditItem; VAR i: LONGINT): BOOLEAN;
    (*
      If ei exists and its type is intField, this procedure tests the
      current field content for correct syntax and range as specified
      during field installation.  If the test is passed the procedure
      returns TRUE, else it will display an error message and then return
      FALSE similar as described under procedure IsChar.  In case that ei
      does not exist or is not of the proper type an error message will be
      displayed.
    *)



  PROCEDURE IsReal(ei: EditItem; VAR r: REAL): BOOLEAN;
  PROCEDURE IsLongReal(ei: EditItem; VAR r: LONGREAL): BOOLEAN;
    (*
      If ei exists and its type is realField, this procedure tests the
      current field content for correct syntax and range as specified
      during field installation.  If the test is passed the procedure
      returns TRUE, else it will display an error message and then return
      FALSE similar as described under procedure IsChar.  In case that ei
      does not exist or is not of the proper type an error message will be
      displayed.
    *)



  PROCEDURE GetRadioButtonSet(ei: EditItem;
                              VAR selRadioButton: RadioBut);
    (*
      If ei is of type radioButtonSet the currently selected radio
      button is returned.  In case that ei does not exist or is
      not of the proper type an error message will be displayed.
    *)

  PROCEDURE GetCheckBox(ei: EditItem; VAR boxChecked: BOOLEAN);
    (*
      If ei is of type checkBox the current state of the checkbox,
      i.e. whether it is checked (TRUE) or not (FALSE) is returned.
      In case that ei does not exist or is not of the proper
      type an error message will be displayed.
    *)

  PROCEDURE GetScrollBar(ei: EditItem; VAR r: REAL);
    (*
      If ei is of type scrollbar, the value r corresponding to the current
      setting of the scrollbar is returned.  In case that ei does not exist
      or is not of the proper type an error message will be displayed.
    *)



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

  Modeless Dialog

  Modeless dialog allows the user to make his entries
  any time he wishes, i.e. he may turn his attention
  in the middle of data entries to other activities
  before he actually terminates the dialog by requesting
  the system to do something with his data entered
  during the dialog.

  DMEditFields offers two possibilities to sample the entered input:

  1. When an application needs the entered value to do the job the
     user has told him, it can get it by the following procedures:

     GetChar, GetString, GetInteger, GetCardinal, GetReal,
     GetCheckbox and GetRadioButtonSet (see below).

     DMEditFields tests in this moment the input for proper syntax
     and correct range. In case of an error DMEditFields displays
     an appropriate error message like this:

     +-----------------------------------------------------+
     |                                                     |
     |   Your entry "1.2b43" is syntactically incorrect !  |
     |                                                     |
     |   Please enter a number of type REAL...             |
     |                                                     |
     |                                    +=========+      |
     |                                    |   O K   |      |
     |                                    +=========+      |
     |                                                     |
     +-----------------------------------------------------+


     The Get…(…) routine returnes FALSE and the returned value
     is UNDEFINED (it remaines unchanged). In this case you
     should cancel the current task. The owner window of the
     erroneous edit field will be brought to the front if
     necessary and erroneous EditField itself  will be selected
     (hilited) and the user may correct the input while the
     program is in the same state as before.

     If there are more than one input needed for a specific
     task then you may use the following construction:

     IF Get…(…) AND Get…(…) AND ... THEN
       DoTheTask
     END; (* IF *)

     MODULA-2 evaluates the second and following expressions
     only if the first or all previous calls have returned TRUE.
     This method guarantees that no more than one error message
     will be displayed before the user may correct the input.


  2. To prevent confusing situations, the application may
     test the input either when the input window is removed from
     front or if the user selects another string based edit field
     (e.g. presing the tab-key or clicking inside another field).
     For the first case the application can call Get…(…) inside a
     mouse handler routine of kind "RemoveFromFront" offered by
     DMMaster. For the second case this module offers a handler
     mechanism called an "EditHandler" (see below). It reports
     (only) elementary input activities  such as a mouse click
     (mouse-up event) or pressing a key (a key-down event). The
     handler routine returns the engaged edit item and you may
     determine its type by calling the procedure GetEditItemType
     (see below). Knowing the item type you are enabled to get the
     value with one of the procedures listed above.

     The program structure may look like this:

     =============== Example ===============

     MODULE MyProgram;
     …
     FROM DMWindows    IMPORT Window, CreateWindow,…;
     FROM DMEditFields IMPORT notInstalledEditItem, EditItem, ItemType, RadioBut,…
                              InstallEditHandler, GetItemType,
                              GetReal, MakeRealField, GetRadioButtonSet,…;
     FROM DMMaster     IMPORT RunDialogMachine,…;
     …

     (* global variables *)

     VAR myWindow         : Window;   (* owner window of edit fields *)
         lastEditField,               (* last active (string based) field *)
         myMakeRealField,             (* an EditField for REAL's *)
         myRadioButtonSet : EditItem; (* a radio button set (see above) *)
         rb,rb2           : RadioBut; (* with two radio buttons *)
     …
     PROCEDURE CheckIfFieldChanged(VAR ei: EditItem);
        VAR it: ItemType;
     BEGIN
       GetEditItemType(ei,it);
       IF (ei <> lastEditField) THEN
          (* first test if it is a string based edit field
             and test their value by Get…(…) procedures *)
         IF (it = realField) AND GetReal(ei,r) THEN
           …
         ELSIF (it = …) AND Get…(ei,…) THEN
           (* test other string based fields *)
           …
         END;
       ELSE
         (* Get input from so called "controls" *)
         IF (it = radioButtonSet) THEN
           GetRadioButtonSet(ei,crb)
           …
         END; (* IF *)
         …
       END; (* IF *)
       IF (it <= realField) OR (lastEditField = notInstalledEditItem) THEN
         lastEditField:= ei   (* init or adjust global variable *)
       END; (* IF *)
     END CheckIfFieldChanged;
     …
     PROCEDURE SetUpWindow;
     BEGIN
       …
       CreateWindow(myWindow,…);
       …
       MakeRealField(myWindow,myMakeRealField,…,100.0,100.0,200.0);
       BeginRadioButtonSet(myWindow,myRadioButonSet);
         AddRadioButton(rb1,…,"AddRadioButton 1");
         AddRadioButton(rb2,…,"AddRadioButton 2");
       EndRadioButtonSet(rb2);
       …
       InstallEditHandler(myWindow, CheckIfFieldChanged);
       …
     END SetUpWindow;
     …
     BEGIN (* MAIN *)
       myWindow:= notExistingWindow; lastEditField := notInstalledEditItem;
       myMakeRealField:= notInstalledEditItem;
       myRadioButtonSet:= notInstalledRadioBut;
       SetUpWindow;
       …
       RunDialogMachine;
     END MyProgram.

     ============= End of example =============

     CAUTION:

     Be awared that in string based edit fields it is possible,
     that the user enters intermediate syntactically uncorrect
     strings or values which are outside the specified ranges. In
     this case the calling of a Get…(…) procedure within an edit
     handler will cause a (eventually unwanted) error message. With
     the following EditHandler it would be impossible to enter a
     correct number if the user has deleted the input once. It will
     produce an error message after every key stroke:

     ============== Bad EditHandler ==============

     PROCEDURE BadEditHandler(VAR ei: EditItem);
        VAR it: ItemType; r: REAL;
     BEGIN
       GetEditItemType(ei,it);
       CASE it OF
           realField :  IF GetReal(ei,r) THEN … END;
         | …
       END; (* CASE *)
     END BadEditHandler;

     =========== End of bad EditHandler ===========


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


  TYPE EditHandler = PROCEDURE(EditItem);
    (*
      EditHandler will be called if an elementary user dialog is
      finished (e.g. mouse buttom released) or a key pressed.
      Activities on every type of edit items are reported except
      those on pushbuttons.

      If you want to select specific parts of an EditField in the
      EditHandler procedure, this can be done using the procedure
      DMMakeTextFields.SetSelection. Selecting is possible for
      (Long)Card, (Long)Int, (Long)Real, String and Text Fields.
      Three cases are to be distinguished depending on procedure arguments:
        - beforeCh ≤ afterCh     : The characters in between are selected;
        - beforeCh > afterCh ≥ 0 : The cursor is inserted at afterCh;
        - beforeCh > afterCh < 0 : The characters from afterCh to the end
                                   of the field are selected.
    *)

  PROCEDURE InstallEditHandler(u: Window; eh: EditHandler);
  PROCEDURE GetEditHandler(u: Window; VAR eh: EditHandler);
    (* at a time every window may support only one EditHandler
    routine *)



  (**********************************)
  (*#####   EditItem Removal   #####*)
  (**********************************)

  PROCEDURE RemoveEditItem(VAR ei: EditItem);
    (*
      Remove the edit item ei from the screen and distroyes its
      associated memory representation. "notInstalledEditItem" is
      assigned to ei.

      IMPORTANT NOTE: Due to an implementation restriction you must
      not call this procedure within a window restore procedure,
      since RemoveEditItem will trigger an additional update event,
      which leads to a never ending chain of update events.  The
      need to call this routine in a restore procedure arises
      usually, if you wish to modify the position of an edit item
      within a window which has changed its size.  Use a redefine
      handler (see module DMWindows procedure AddWindowHandler) to
      program such a task.
    *)

  PROCEDURE RemoveAllEditItems(u: Window);
    (*
      Removes every edit item which is associated with the window
      u. (DMWindows RemoveWindow calls this procedure when a window
      is removed from the screen).
    *)


END DMEditFields.

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