2.40 :set()

This method can set attributes of an object. It is predefined for all objects, Models and Defaults.

Furthermore, it is possible to overwrite this method and thus to extend the way attributes are set by further actions (e.g. consistency checks).

You can find the attributes available for the relevant object type in the “Object Reference”.

Definition

boolean :set
(
      attribute Attribute input,
      anyvalue  Value     input
  { , anyvalue  Index     input }
  { , boolean   SendEvent := true input }
)

Parameters

attribute Attribute input
This parameter informs the method which attribute shall be set.
anyvalue Value input
In this parameter, the new value for the attribute is passed.
anyvalue Index input
This optional parameter needs to be specified if an indexed attribute shall be set. Its data type must match the index data type of the attribute. Thus, if a one-dimensional attribute should be set, an integer value is expected here. However, if the attribute is two-dimensional, an index value has to be passed here.
boolean SendEvent := true input
This optional parameter controls whether a changed event should be sent or not when the attribute is successfully set. If no event should be sent, false must be passed here. The default value is true so an event will be sent if nothing is specified here.

Return value

true
The method returns true if setting the attribute has been successful.
false
If setting the attribute was refused (either by the IDM or the IDM programmer), false is returned.

Implicit Invocation

The :set() method is also invoked implicitly. When an attribute (predefined or user-defined) is changed from the Rule Language (by assignment with := respectively ::= or the built-in function setvalue()) or with an interface function (e.g. DM_SetValue()), the :set() method is called, which then actually sets the attribute. The method :set() is invoked in the middle and does the actual assignment of the new value.

Redefinition

To redefine the :set() method it is sufficient to simply write the following at an object:

window W {
  :set(<no parameters!>)
  {
    ...
    Actions to set an attribute.
    ...
  }
}

Within the method definition, the parameters Attribute, Value, Index and SendEvent can be queried and set, in order to then call e.g. with this:super() the method :set() of the superclass with the accordingly changed parameters. However, changing the parameters such as Attribute and Index is not useful because such code would be difficult to understand.

Suppression of Recursive Calls

If within the method :set() any attribute of the same object for which the :set() method has already been called is set, then the method :set() should actually be invoked implicitly again for the same object. Since the danger of an infinite recursion is very high in this case, such a recursive call is suppressed.

Example

window {
  :set()
  {
    case (Attribute)
    in .title:
      this.title := "<" + Value + ">";
        // No implicit call of :set().
        // Due to ":=" a "changed" event is sent.
        // With "::=" the IDM programmer could also suppress this.
      OtherObject.title := "<" + Value + ">";
        // :set() of OtherObject is invoked.
        // The SendEvent parameter of :set() is set to "true".
    otherwise:
      this:super();
    endcase
  }
}

In this example, the :set() method monitors the setting of the window title and the title is enclosed in <> brackets. During the assignment this.title := … the method :set() is not called again. However, the method :set() for another object will still be invoked.

Call of the :set() Method on the Superclass

The above example also shows how to use this:super(). All attributes for which the overwritten method :set() does not feel responsible should be delegated to the superclass, so that the predefined method :set() will set these attributes at some point.

The value of the Value parameter is always taken into account and assigned to the attribute at the end. The example above could therefore also be written like this:

Example

window {
  :set()
  {
    if Attribute = .title then
      Value := “<” + Value + “>”;
      OtherObject.title := “<” + Value + “>”;
    endif
    this:super();
  }
}

Enforcing Recursive Calls

If the method :set() should be called again for the same object with the changed values, the :recall() method can be used to enforce that the :set() method passed as parameter is also invoked recursively. Caution should be taken, however, as this can very easily lead to infinite recursions.

Example

dialog SET

model record MRec {
  integer MaxCount:=100;
  integer Count:=0;
  :set()
  {
    variable boolean RetVal := true;

    case (Attribute)
    in .Count:
      if this.MaxCount < Value then  // Consistency check.
        Value := this.MaxCount;      // Correct Value.
      endif;
      RetVal := this:super();
    in .MaxCount:
      if this.MaxCount > Value then
        this.MaxCount := Value;
        this:recall(:set, .Count, Value);
          // Set .Count to Value, calling :set() again.
        RetVal := true;
      else
        RetVal := false;             // Decline setting.
      endif
    otherwise:
      RetVal := this:super();
    endcase
    return RetVal;
  }
}

MRec Rec {
}

on dialog start {
  print Rec.Count;      // set value = 0
  Rec.Count := 110;
  print Rec.Count;      // set value = 100

  print Rec.MaxCount;   // set value = 100
  Rec.MaxCount := 200;
  print Rec.MaxCount;   // set value = 100
  Rec.MaxCount := 10;
  print Rec.MaxCount;   // set value = 10
  print Rec.Count;      // set value = 10
  exit();
}

See also

Built-in function setvalue() in manual “Rule Language”

C function DM_SetValue in manual “C Interface - Functions”