Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,17 @@ private ButtonBase makeBaseButton() {
final Button button = new Button();
button.setOnAction(event -> confirm(() -> handleActions(actions.getActions())));
result = button;
if (actions.getActions().size() == 1) {
// If the ActionButton only has a single action and that is to
// write to a PV then is_writePV should be true.
// This means that if the PV is non-writable then the
// ActionButton will be disabled.
if (actions.getActions().get(0).getType().equals("write_pv"))
is_writePV = true;
}
} else {
// If there is at least one non-WritePVAction then is_writePV should be false
is_writePV = !has_non_writePVAction;
is_writePV = has_non_writePVAction;

final MenuButton button = new MenuButton();

Expand Down Expand Up @@ -461,11 +469,7 @@ public void updateChanges() {
// Don't disable the widget, because that would also remove the
// tooltip
// Just apply a style that matches the disabled look.
Styles.update(base, Styles.NOT_ENABLED, !enabled);
// Apply the cursor to the pane and not to the button
if (!toolkit.isEditMode()) {
jfx_node.setCursor(enabled ? Cursor.HAND : Cursors.NO_WRITE);
}
setDisabledLook(enabled, jfx_node.getChildren());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public class BoolButtonRepresentation extends RegionBaseRepresentation<Pane, Boo
private volatile String value_label;
private volatile ImageView[] state_images;
private volatile ImageView value_image;
protected volatile boolean enabled = true;

private final UntypedWidgetPropertyListener imagesChangedListener = this::imagesChanged;
private final UntypedWidgetPropertyListener representationChangedListener = this::representationChanged;
Expand Down Expand Up @@ -138,8 +139,10 @@ protected void attachTooltip()
*/
private void handlePress(final boolean pressed)
{
logger.log(Level.FINE, "{0} pressed", model_widget);
Platform.runLater(() -> confirm(pressed));
if (enabled) {
logger.log(Level.FINE, "{0} pressed", model_widget);
Platform.runLater(() -> confirm(pressed));
}
}

/** Check for confirmation, then perform the button action
Expand Down Expand Up @@ -403,10 +406,9 @@ public void updateChanges()
}
if (dirty_enablement.checkAndClear())
{
final boolean enabled = model_widget.propEnabled().getValue() &&
enabled = model_widget.propEnabled().getValue() &&
model_widget.runtimePropPVWritable().getValue();
button.setDisable(! enabled);
Styles.update(button, Styles.NOT_ENABLED, !enabled);
setDisabledLook(enabled, jfx_node.getChildren());
}
if (update_value)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ public void updateChanges()
// Just apply a style that matches the disabled look.
enabled = model_widget.propEnabled().getValue() &&
model_widget.runtimePropPVWritable().getValue();
Styles.update(jfx_node, Styles.NOT_ENABLED, !enabled);
setDisabledLook(enabled, jfx_node.getChildrenUnmodifiable());
if (model_widget.propAutoSize().getValue())
sizeChanged(null, null, null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ private void selectionChanged(final ObservableValue<? extends Toggle> obs, final
{
active = false;
}
}
else if (!enabled && newval == null)
{
// If the choice button is not enabled (no write allowed)
// we still have to ensure the 'oldval' stays selected
// as otherwise clicking on the same value will set an
// unselected look on the ChoiceButton.
toggle.selectToggle(oldval);
}
}

Expand Down Expand Up @@ -332,8 +340,7 @@ public void updateChanges()
// Just apply a style that matches the disabled look.
enabled = model_widget.propEnabled().getValue() &&
model_widget.runtimePropPVWritable().getValue();
Styles.update(jfx_node, Styles.NOT_ENABLED, !enabled);
jfx_node.setCursor(enabled ? Cursor.DEFAULT : Cursors.NO_WRITE);
setDisabledLook(enabled, jfx_node.getChildren());
for (Node node : jfx_node.getChildren())
{
final ButtonBase b = (ButtonBase) node;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,7 @@ public void updateChanges()
// and the cursor will be ignored
// jfx_node.setDisable(! enabled);
// So keep enabled, but indicate that trying to operate the widget is futile
Styles.update(jfx_node, Styles.NOT_ENABLED, !enabled);
jfx_node.setCursor(enabled ? Cursor.DEFAULT : Cursors.NO_WRITE);
setDisabledLook(enabled, jfx_node.getChildrenUnmodifiable());
if (model_widget.propEditable().getValue())
{
jfx_node.getEditor().setEditable(enabled ? model_widget.propEditable().getValue() : false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,17 @@
import org.csstudio.display.builder.model.widgets.TabsWidget;
import org.csstudio.display.builder.model.widgets.TabsWidget.TabItemProperty;
import org.csstudio.display.builder.representation.WidgetRepresentation;
import org.csstudio.display.builder.representation.javafx.Cursors;
import org.csstudio.display.builder.representation.javafx.JFXRepresentation;

import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.Parent;
import org.phoebus.core.types.ProcessVariable;
import org.phoebus.ui.dnd.DataFormats;
import org.phoebus.ui.javafx.Styles;

/** Base class for all JavaFX widget representations
* @param <JFX> JFX Widget
Expand Down Expand Up @@ -356,4 +359,22 @@ public void updateOrder()
addToParent(parent);
}
}

/**
* We do not want to disable widgets if they cannot be written to as this
* removes the context menu. Instead we replicate the disabled look from Java FX
* and set the cursor to the 'NO_WRITE' cursor to indicate this.
*
* @param enabled boolean as to whether widget interaction is allowed
* @param children list of children nodes under the parent widget
*/
public void setDisabledLook(Boolean enabled, ObservableList<Node> children) {
jfx_node.setCursor(enabled ? Cursor.DEFAULT : Cursors.NO_WRITE);
if (children != null) {
for (Node node : children)
{
Styles.update(node, Styles.NOT_ENABLED, !enabled);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ public void updateChanges()
// Just apply a style that matches the disabled look.
enabled = model_widget.propEnabled().getValue() &&
model_widget.runtimePropPVWritable().getValue();
Styles.update(jfx_node, Styles.NOT_ENABLED, !enabled);
setDisabledLook(enabled, jfx_node.getChildren());
for (Node rb_node : jfx_node.getChildren())
{
final RadioButton rb = (RadioButton) rb_node;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,11 @@ private void valueChanged(final WidgetProperty<? extends VType> property, final
public void updateChanges()
{
super.updateChanges();
if (dirty_enablement.checkAndClear())
if (dirty_enablement.checkAndClear()) {
slider.setDisable(!enabled);
setDisabledLook(enabled, jfx_node.getChildrenUnmodifiable());
}

if (dirty_layout.checkAndClear())
{
final boolean horizontal = model_widget.propHorizontal().getValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,8 +335,7 @@ public void updateChanges()
// Don't disable the widget, because that would also remove the
// context menu etc.
// Just apply a style that matches the disabled look.
Styles.update(jfx_node, Styles.NOT_ENABLED, !enabled);
jfx_node.setCursor(enabled ? Cursor.DEFAULT : Cursors.NO_WRITE);
setDisabledLook(enabled, jfx_node.getChildrenUnmodifiable());
}
if (dirty_size.checkAndClear())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public void updateChanges ( ) {
// Just apply a style that matches the disabled look.
enabled = model_widget.propEnabled().getValue() && model_widget.runtimePropPVWritable().getValue();

Styles.update(jfx_node, Styles.NOT_ENABLED, !enabled);
setDisabledLook(enabled, jfx_node.getChildren());

// Since jfx_node.isManaged() == false, need to trigger layout
jfx_node.layout();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class SpinnerRepresentation extends RegionBaseRepresentation<Spinner<Stri
{
/** Is user actively editing the content, so updates should be suppressed? */
private volatile boolean active = false;
private volatile boolean enabled = true;

private final DirtyFlag dirty_style = new DirtyFlag();
private final DirtyFlag dirty_content = new DirtyFlag();
Expand Down Expand Up @@ -167,40 +168,42 @@ private void restore()
/** Submit value entered by user */
private void submit()
{
//The value factory retains the old values, and will be updated as scheduled below.
final String text = jfx_node.getEditor().getText();
Object value =
FormatOptionHandler.parse(model_widget.runtimePropValue().getValue(), text, model_widget.propFormat().getValue());
if (value instanceof Number)
{
if (((Number)value).doubleValue() < value_min)
value = value_min;
else if (((Number)value).doubleValue() > value_max)
value = value_max;
if (enabled) {
//The value factory retains the old values, and will be updated as scheduled below.
final String text = jfx_node.getEditor().getText();
Object value =
FormatOptionHandler.parse(model_widget.runtimePropValue().getValue(), text, model_widget.propFormat().getValue());
if (value instanceof Number)
{
if (((Number)value).doubleValue() < value_min)
value = value_min;
else if (((Number)value).doubleValue() > value_max)
value = value_max;
}
logger.log(Level.FINE, "Writing '" + text + "' as " + value + " (" + value.getClass().getName() + ")");
toolkit.fireWrite(model_widget, value);

// Wrote value. Expected is either
// a) PV receives that value, PV updates to
// submitted value or maybe a 'clamped' value
// --> We'll receive contentChanged() and update the value factory.
// b) PV doesn't receive the value and never sends
// an update. The value factory retains the old value,
// --> Schedule an update to the new value.
//
// This could result in a little flicker:
// User enters "new_value".
// We send that, but retain "old_value" to handle case b)
// PV finally sends "new_value", and we show that.
//
// In practice, this rarely happens because we only schedule an update.
// By the time it executes, we already have case a.
// If it does turn into a problem, could introduce toolkit.scheduleDelayedUpdate()
// so that case b) only restores the old 'value_text' after some delay,
// increasing the chance of a) to happen.
dirty_content.mark();
toolkit.scheduleUpdate(this);
}
logger.log(Level.FINE, "Writing '" + text + "' as " + value + " (" + value.getClass().getName() + ")");
toolkit.fireWrite(model_widget, value);

// Wrote value. Expected is either
// a) PV receives that value, PV updates to
// submitted value or maybe a 'clamped' value
// --> We'll receive contentChanged() and update the value factory.
// b) PV doesn't receive the value and never sends
// an update. The value factory retains the old value,
// --> Schedule an update to the new value.
//
// This could result in a little flicker:
// User enters "new_value".
// We send that, but retain "old_value" to handle case b)
// PV finally sends "new_value", and we show that.
//
// In practice, this rarely happens because we only schedule an update.
// By the time it executes, we already have case a.
// If it does turn into a problem, could introduce toolkit.scheduleDelayedUpdate()
// so that case b) only restores the old 'value_text' after some delay,
// increasing the chance of a) to happen.
dirty_content.mark();
toolkit.scheduleUpdate(this);
}

private SpinnerValueFactory<String> createSVF()
Expand Down Expand Up @@ -349,18 +352,20 @@ public void increment(int steps)

private void writeResultingValue(double change)
{
double value;
if (!(getVTypeValue() instanceof VNumber))
{
scheduleContentUpdate();
return;
if (enabled) {
double value;
if (!(getVTypeValue() instanceof VNumber))
{
scheduleContentUpdate();
return;
}
value = ((VNumber)getVTypeValue()).getValue().doubleValue();
if (Double.isNaN(value) || Double.isInfinite(value)) return;
value += change;
if (value < getMin()) value = getMin();
else if (value > getMax()) value = getMax();
toolkit.fireWrite(model_widget, value);
}
value = ((VNumber)getVTypeValue()).getValue().doubleValue();
if (Double.isNaN(value) || Double.isInfinite(value)) return;
value += change;
if (value < getMin()) value = getMin();
else if (value > getMax()) value = getMax();
toolkit.fireWrite(model_widget, value);
}
};

Expand Down Expand Up @@ -505,11 +510,10 @@ public void updateChanges()
jfx_node.resize(model_widget.propWidth().getValue(), model_widget.propHeight().getValue());

// Enable if enabled by user and there's write access
final boolean enabled = model_widget.propEnabled().getValue() &&
enabled = model_widget.propEnabled().getValue() &&
model_widget.runtimePropPVWritable().getValue();
Styles.update(jfx_node, Styles.NOT_ENABLED, !enabled);
setDisabledLook(enabled, jfx_node.getChildrenUnmodifiable());
jfx_node.setEditable(!toolkit.isEditMode() && enabled);
jfx_node.getEditor().setCursor(enabled ? Cursor.DEFAULT : Cursors.NO_WRITE);

jfx_node.getEditor().setFont(JFXUtil.convert(model_widget.propFont().getValue()));

Expand Down
Loading