Changing a component
depending on the value of another one:
You can tie components together with listeners to the SettingsModel.
You can change the value of a component or en-/disable it depending on the value of another.
You always go through the SettingsModels to do that. If a SettingsModel
is disabled the corresponding component is disabled too (in the
dialog). The settings model stores the enable status and if the workflow is loaded and the dialog
is opened again, the enable status is
restored.
Lets look at the
following example:
This is the dialog we are creating. It has a selection box with three
choices. Depending on the selection we want to set a value in the
parameter field. The parameter is only user editable, if the
corresponding box is checked. Otherwise the editfield is disabled.

Creating the dialog:
We need three SettingsModels to store the three values. In the
NodeModel (we named the class TestNodeModel)
we create factory methods:
static
SettingsModelString
createSettingsModelSelection() {
return new
SettingsModelString("SELECTION",
"");
}
static
SettingsModelInteger
createSettingsModelValue() {
return
new
SettingsModelInteger("VALUE",
0);
}
static
SettingsModelBoolean
createSettingsModelEnabled() {
return new
SettingsModelBoolean("ENABLE",
false);
}
In the NodeDialog's constructor we instantiate the three settings models
and assign them to local variables, because we need to register
listeners with them later on:
SettingsModelString
selection =
TestNodeModel.createSettingsModelSelection();
SettingsModelBoolean enabled =
TestNodeModel.createSettingsModelEnabled();
SettingsModelInteger parameter =
TestNodeModel.createSettingsModelValue();
We use these settings models with a StringSelection component (a
ComboBox), a Boolean component (a CheckBox), and with a NumberEdit
component (a text field to enter numbers). We create two groups and
also change the orientation to arrange them nicely:
createNewGroup("Your choice");
addDialogComponent(new DialogComponentStringSelection(selection,
"Select one:", TestNodeModel.SELECTION));
createNewGroup("Parameter");
setHorizontalPlacement(true);
addDialogComponent(new DialogComponentBoolean(enabled, "edit
manually"));
addDialogComponent(new DialogComponentNumberEdit(parameter, "", 15));
Adding listeners to the SettingsModel:
Now, in order to enable the parameter edit field if (and
only if) the checkbox is marked, add a listener to the boolean settings
model:
enabled.addChangeListener(new ChangeListener() {
public void stateChanged(final ChangeEvent e) {
// if enabled is true, the parameter field should be enabled
parameter.setEnabled(enabled.getBooleanValue());
}
});
When notified (i.e. when the user changes the checkbox) it
reads the value from the boolean settings
model and enables the parameter settings model accordingly. Whenever
the settings model changes (the value or the enable status) it is being
forwarded to the dialog component.
You can not only change the enable status of a component in a listener
- you can also change another component's value depending on the value
of the notifier, e. g.:
selection.addChangeListener(new ChangeListener() {
public void stateChanged(final ChangeEvent e) {
int param = selection.getStringValue().hashCode();
// we override any previously entered value!
parameter.setIntValue(param);
}
});
Whenever the selection changes, this listener is called and sets a new
parameter value depending on the current selection. (To make the code
simple we just set the hash code...which fails, if the string value is
null, btw.)
Important Note:
There is a very important detail, that, if you forget it it will cause
the
components to appear in the dialog in an "invalid" state (in the
example the edit field might be enabled even though the checkbox is not
marked): You must
maintain dependencies at all time.
That is, whenever a value is set in the settings model and no listener
is (yet) installed the enable status or value of the settings model
that should be tight to the first one must be adapted. In the
example that is the case at construction time of the settings models.
We instantiate the settings model for the boolean value with the
initial value false.
Thus, the parameter settings model should be disabled at the same time.
If you run the example with the code from above and open the dialog for
the first time, you will notice that the parameter editfield is
enabled, even though the check mark is not set. Only after you changed
the checkbox it maintains the correct status dependency.
To fix this, we can either initialize the settings model in a consistent way (e. g. init the enable model with true, or disable the parameter value model in its factory method), or set the correct states when we use them (in the constructors).
It is also very important to do this in the NodeModel.
If you are not planning on modifying the values in your node model (if
you just want to read user settings from them), then there is no real
need to install listeners in the settings models instances used in your
NodeModel. But you need to make sure that they are initialized
consistently. If you find - when you open the dialog for the first time
- that your
component is enabled, even though the check mark that should disable it
is set, then your settings in the NodeModel probably don't
reflect the dependencies in the correct way.
(Even though the values are loaded into the node dialog each time it opens
you must maintain this. You may expect that if the values are loaded
the listeners will take care of setting the correct status - which is true. But the
order in which the values are loaded is not defined. It happens that
the value determining the status of another component is loaded before
the (wrong) status of the dependant is loaded, overloading the correct
status.)
Get the fragmentary source code of the example here: exampleSource.zip