Class AbstractSpinnerDataBinding<V>
- Type Parameters:
V- The type of the model value being bound
- All Implemented Interfaces:
AbstractDataBinding<V>
- Direct Known Subclasses:
ContainerSpinnerDataBinding,SpinnerDataBinding
Spinner and a model value of type V.
The converter turns the value into a number, and the spinner shows it with digits places after the point.
The arrows and the Up, Down, Page Up and Page Down keys send the value to the model at once;
typed text is sent on Enter or when the spinner loses focus.
If the typed text is not a number, the number is out of range or the value fails the validation,
an error icon is shown next to the spinner, and after Enter or focus loss the spinner shows the model value again.
Spinner keeps an integer (the selection) and the number of digits after the point,
so the value is multiplied by 10 to the power of digits and rounded.
Integer, Double and other types differ only in the converter, so there are no separate classes for them.
What the SWT Spinner does on Windows
(SWT 3.134, Spinner.java) It is made of two Windows controls: a text field and the arrow buttons. The selection is kept in the buttons.- The text changes (
EN_CHANGEinwmCommandChild). If the text is a number in the range and differs from the selection, the spinner updates the selection and puts Selection in the queue. Then it sends Modify at once. If the text is not a number or the number is out of range, the selection stays the same and Selection is not sent, but Modify is sent anyway. - The Up, Down, Page Up and Page Down keys (
wmKeyDown). KeyDown comes first. Then the spinner takes the number from the text, or the previous selection if the text is not valid, adds the step, clips it to the range and callssetSelectionwith notify. That call writes the text, which brings Modify, and puts Selection in the queue. - A mouse click on an arrow (
UDN_DELTAPOSinwmNotifyChild). The same, without KeyDown. - Enter (
wmChar). Puts DefaultSelection in the queue; the text does not change. - Focus loss (
wmKillFocus). If the text is not valid, the spinner puts the text of the previous selection back. This brings Modify without Selection. Then FocusOut comes. setSelectioncalled from code. Writes the text; Modify comes, Selection does not.
sendSelectionEvent, which puts the event in the queue
(Widget.sendEvent with send = false), so it always comes after Modify.
The listeners of the binding (createBinding)
- KeyDown sets
isKeyPressedfor any key except Up, Down, Page Up and Page Down. - Modify stores in
isTypedModifywhether a key was pressed. If it was, this is typing:isKeyPressedis reset,isTypingis set, the text is parsed intotypedSelection(parseSelection), and the error icon is shown or hidden. - Selection calls
executeToModelonly if this is not typing (neitherisKeyPressednorisTypedModify), and resetsisTypingbefore that. Selection from typing is skipped because the spinner sends it for every valid intermediate number: typing "25" would send "2" to the model.isKeyPressedalone is not enough for the check: when Selection comes from the queue, Modify has already reset it. - DefaultSelection (Enter) and FocusOut call
executeToModel.
executeToModel
- takes
typedSelectionif the user was typing, otherwise the selection of the spinner. The selection of the spinner cannot be used after typing, because with invalid text the spinner keeps the last valid one. With the range from 0 to 10, after "1" and "11"getSelection()returns 1, and Enter would write 1; - resets the flags;
- writes to the model if the number is not null, differs from
shownSelectionand passes the validation; - always calls
executeToTargetat the end, which shows the model value again and storesshownSelection.
Selections, not values, are compared with shownSelection, because the spinner shows the value rounded
to digits places. If the model holds 1.234 and digits is 2, the spinner shows 1.23,
and comparing values would write 1.23 when the user just enters the field and leaves it.
For the same reason focus loss writes nothing when the model holds null (the spinner shows the minimum)
or a value out of range (the spinner shows the nearest bound).
parseSelection parses the text by the rules of the spinner. The decimal separator is taken from the text
of the spinner, because the spinner shows the separator from the Windows settings, and it may differ
from the Java locale. Extra digits after the separator are cut off the same way the spinner cuts them.
canBeNull only hides the icon for null. The icon is not shown while the spinner is disabled.
- Author:
- Ionov Ivan
- See Also:
-
Field Summary
FieldsModifier and TypeFieldDescriptionprotected BooleanSupplierWhether the model may hold null.protected org.eclipse.jface.fieldassist.ControlDecorationThe error icon of the spinner.protected intThe number of digits after the point.protected DoubleFunction<V> Turns a number of the spinner back into a model value.protected VThe upper bound of the value.protected VThe lower bound of the value.protected org.eclipse.swt.widgets.SpinnerThe spinner the value is bound to.protected ToDoubleFunction<V> Turns a model value into a number for the spinner.Check of the value.protected StringTooltip text of the error icon. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptioncanBeNull(BooleanSupplier canBeNull) converter(ToDoubleFunction<V> toNumber, DoubleFunction<V> fromNumber) voidCreates the error icon, sets the range anddigitsof the spinner, subscribes to its events and shows the model value.digits(int digits) voidenable(boolean enable) Enables or disables the bound control.voidSends the number the user set in the spinner to the model and shows the model value again.voidShows the model value in the spinner.voidsetControl(Object control) Sets the UI control for this binding.inttoSelection(V value) Converts a value into the spinner selection, taking the digits into account.validation(Predicate<V> validation, String message) Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface com.amalgamasimulation.desktop.binding.widgets.AbstractDataBinding
createControlDecoration, doAction, getValue
-
Field Details
-
spinner
protected org.eclipse.swt.widgets.Spinner spinnerThe spinner the value is bound to. Set by setControl. -
toNumber
Turns a model value into a number for the spinner. -
fromNumber
Turns a number of the spinner back into a model value. -
minimum
The lower bound of the value. createBinding makes it the minimum of the spinner. -
maximum
The upper bound of the value. createBinding makes it the maximum of the spinner. -
digits
protected int digitsThe number of digits after the point. -
validation
Check of the value. A value that fails it is not written to the model. If the model value fails it, the error icon is shown. By default the check accepts any value. -
validationMessage
Tooltip text of the error icon. The tooltip is set once in createBinding, so calling validation after it does not change the text. -
canBeNull
Whether the model may hold null. If it may, the error icon is not shown for null. The function is called every time the binding shows null from the model. By default null is not allowed. -
controlDecoration
protected org.eclipse.jface.fieldassist.ControlDecoration controlDecorationThe error icon of the spinner. createBinding creates it hidden.
-
-
Constructor Details
-
AbstractSpinnerDataBinding
protected AbstractSpinnerDataBinding()
-
-
Method Details
-
executeToTarget
public void executeToTarget()Shows the model value in the spinner. null is shown as the minimum of the spinner. The spinner clips a value out of range itself, soshownSelectionis read from the spinner aftersetSelectioninstead of being taken fromtoSelection. Ifdigitsis above zero, the decimal separator is read from the text of the spinner: it stands before the lastdigitscharacters. It is read here because the spinner takes the separator from the Windows settings, and the shown text is the only way to learn it. At the end the error icon is updated. Called at the end ofcreateBindingand of everyexecuteToModel, when the spinner is enabled (enable) and when the section is updated.- Specified by:
executeToTargetin interfaceAbstractDataBinding<V>
-
executeToModel
public void executeToModel()Sends the number the user set in the spinner to the model and shows the model value again. The typing flags are reset before the write becauseexecuteToTargetcallssetSelection, and its Modify must not count as typing. After Enter,isKeyPressedis still set by the Enter key itself. The number is not written if it is null (the text is not a number or the number is out of range), if it equalsshownSelection, or if the value fails the validation.executeToTargetis always called, even if nothing was written: it puts the model value back in place of invalid text and updates the icon. Where the number comes from and why is described in the class Javadoc.- Specified by:
executeToModelin interfaceAbstractDataBinding<V>
-
createBinding
public void createBinding()Creates the error icon, sets the range anddigitsof the spinner, subscribes to its events and shows the model value. The arrow step is set to 1 and the page step to 10 in selection units; the section may replace them with its own aftercreateBinding. Throws IllegalArgumentException ifdigitsis below 0 or the minimum is greater than the maximum, because the spinner would ignore such values without an error. The tooltip of the icon is set here once, sovalidationmust be called beforecreateBinding. The listeners and the order of their events are described in the class Javadoc.- Specified by:
createBindingin interfaceAbstractDataBinding<V>
-
toSelection
Converts a value into the spinner selection, taking the digits into account.- Parameters:
value- the value, notnull- Returns:
- the selection of the spinner
-
enable
public void enable(boolean enable) Description copied from interface:AbstractDataBindingEnables or disables the bound control.- Specified by:
enablein interfaceAbstractDataBinding<V>- Parameters:
enable- true to enable, false to disable
-
setControl
Description copied from interface:AbstractDataBindingSets the UI control for this binding.- Specified by:
setControlin interfaceAbstractDataBinding<V>- Parameters:
control- The control to bind to
-
converter
public AbstractSpinnerDataBinding<V> converter(ToDoubleFunction<V> toNumber, DoubleFunction<V> fromNumber) -
range
-
digits
-
validation
-
canBeNull
-