Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display: Support 'class' for array/struct properties #2302

Merged
merged 7 commits into from
Jun 21, 2022
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
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017-2020 Oak Ridge National Laboratory.
* Copyright (c) 2017-2022 Oak Ridge National Laboratory.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand All @@ -22,6 +22,7 @@
import org.csstudio.display.builder.editor.EditorGUI;
import org.csstudio.display.builder.editor.EditorUtil;
import org.csstudio.display.builder.editor.Messages;
import org.csstudio.display.builder.editor.WidgetSelectionHandler;
import org.csstudio.display.builder.editor.actions.ActionDescription;
import org.csstudio.display.builder.model.DisplayModel;
import org.csstudio.display.builder.model.ModelPlugin;
Expand Down Expand Up @@ -386,9 +387,20 @@ void loadWidgetClasses()
ModelThreadPool.getExecutor().execute(() ->
{
// get widget classes and apply to model
// (which triggers editor UI updates, so perform in UI thread)
final DisplayModel model = editor_gui.getDisplayEditor().getModel();
if (model != null)
WidgetClassesService.getWidgetClasses().apply(model);
Platform.runLater( () ->
{
// Save/restore selection to force update of property panel
final WidgetSelectionHandler selection = editor_gui.getDisplayEditor().getWidgetSelectionHandler();
final List<Widget> save = selection.getSelection();
selection.clear();
// Apply class settings
WidgetClassesService.getWidgetClasses().apply(model);
// Restore selection
selection.setSelection(save);
});
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2015-2018 Oak Ridge National Laboratory.
* Copyright (c) 2015-2022 Oak Ridge National Laboratory.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -499,19 +499,22 @@ else if (property instanceof PointsWidgetProperty)
* @param property Property (on primary widget)
* @param other Zero or more additional widgets that have same type of property
* @param structureIndex Index of the array structure (element) being added. It is meaningful
* only for properties instance of {@link StructuredWidgetProperty}.
* only for properties instance of {@link StructuredWidgetProperty}
* @param indentationLevel Indentation level
*/
private void createPropertyUI(
final UndoableActionManager undo,
final WidgetProperty<?> property,
final List<Widget> other,
final int structureIndex,
final int indentationLevel
) {
final int indentationLevel)
{
// Skip runtime properties
if (property.getCategory() == WidgetPropertyCategory.RUNTIME)
return;

// System.out.println("Index " + structureIndex + ", level " + indentationLevel + ": " + property.getPath());

final Label label = new Label(property.getDescription());
label.setMaxWidth(Double.MAX_VALUE);
final String tooltip = property.getDescription() + " (" + property.getPath() + ")";
Expand Down Expand Up @@ -567,9 +570,7 @@ else if (property instanceof RulesWidgetProperty)
field = rules_field;
}
else if (property instanceof StructuredWidgetProperty)
{ // Don't allow editing structures and their elements in class mode
if (class_mode)
return;
{
final StructuredWidgetProperty struct = (StructuredWidgetProperty) property;
final Label header = new Label(struct.getDescription() + ( structureIndex > 0 ? " " + String.valueOf(1 + structureIndex) : ""));
header.getStyleClass().add("structure_property_name");
Expand All @@ -589,9 +590,7 @@ else if (property instanceof StructuredWidgetProperty)
return;
}
else if (property instanceof ArrayWidgetProperty)
{ // Don't allow editing arrays and their elements in class mode
if (class_mode)
return;
{
@SuppressWarnings("unchecked")
final ArrayWidgetProperty<WidgetProperty<?>> array = (ArrayWidgetProperty<WidgetProperty<?>>) property;

Expand All @@ -611,6 +610,28 @@ else if (property instanceof ArrayWidgetProperty)

fillHeaderIndent(indentationLevel, row);
add(label, indentationLevel, row, 4 - indentationLevel, 1);

if (class_mode)
{ // Checkbox to select if array is included in class definition
final CheckBox check = new CheckBox();
check.setPadding(new Insets(0, 5, 0, 0));
check.setTooltip(use_class_tooltip);
final WidgetPropertyBinding<?,?> binding = new UseWidgetClassBinding(undo, check, spinner, property, other);
bindings.add(binding);
binding.bind();
add(check, 3, row);
}
else
{ // Show if property is set by the class, not editable.
final Label indicator = new Label();
indicator.setPadding(new Insets(0, 5, 0, 0));
indicator.setTooltip(using_class_tooltip);
final WidgetPropertyBinding<?,?> binding = new ShowWidgetClassBinding(spinner, property, indicator);
bindings.add(binding);
binding.bind();
add(indicator, 3, row);
}

add(spinner, 4, row, 2 - indentationLevel, 1);

Separator separator = new Separator();
Expand Down Expand Up @@ -683,14 +704,20 @@ else if (property instanceof ArrayWidgetProperty)
{
if (class_mode)
{ // Class definition mode:
// Check box for 'use_class'
final CheckBox check = new CheckBox();
check.setPadding(new Insets(0, 5, 0, 0));
check.setTooltip(use_class_tooltip);
final WidgetPropertyBinding<?,?> binding = new UseWidgetClassBinding(undo, check, field, property, other);
bindings.add(binding);
binding.bind();
add(check, 3, row);
// Check box for 'use_class', but only on the top level
// For nested properties inside an array or struct,
// the class behavior is controlled at the top-level
// for the complete array or struct
if (indentationLevel == 0)
{
final CheckBox check = new CheckBox();
check.setPadding(new Insets(0, 5, 0, 0));
check.setTooltip(use_class_tooltip);
final WidgetPropertyBinding<?,?> binding = new UseWidgetClassBinding(undo, check, field, property, other);
bindings.add(binding);
binding.bind();
add(check, 3, row);
}
}
else
{ // Display file mode:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2015-2017 Oak Ridge National Laboratory.
* Copyright (c) 2015-2022 Oak Ridge National Laboratory.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -55,13 +55,14 @@ public void bind()
updateFromModel();
jfx_node.setOnAction(event ->
{
final boolean use_class = jfx_node.isSelected();
updating = true;
property_field.setDisable(! jfx_node.isSelected());
undo.execute(new UseClassAction(widget_property, jfx_node.isSelected()));
property_field.setDisable(! use_class);
undo.execute(new UseClassAction(widget_property, use_class));
for (Widget w : other)
{
final WidgetProperty<?> other_prop = w.getProperty(widget_property.getName());
undo.execute(new UseClassAction(other_prop, jfx_node.isSelected()));
undo.execute(new UseClassAction(other_prop, use_class));
}
updating = false;
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2015-2016 Oak Ridge National Laboratory.
* Copyright (c) 2015-2022 Oak Ridge National Laboratory.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -111,15 +111,6 @@ protected ArrayWidgetProperty(final Descriptor<WPE> descriptor,
value = new CopyOnWriteArrayList<>(elements);
}

@Override
public boolean isUsingWidgetClass()
{ // Array uses class if any elements use it
for (WidgetProperty<?> element : value)
if (element.isUsingWidgetClass())
return true;
return false;
}

@Override
public boolean isDefaultValue()
{
Expand All @@ -130,6 +121,15 @@ public boolean isDefaultValue()
value.get(0).isDefaultValue();
}

@Override
public void useWidgetClass(boolean use_class)
{
// Update overall array as well as each element
super.useWidgetClass(use_class);
for (WPE element : value)
element.useWidgetClass(use_class);
}

@Override
protected List<WPE> restrictValue(final List<WPE> requested_value)
{
Expand Down Expand Up @@ -195,6 +195,8 @@ public WPE removeElement()
/** @param element Element to add to end of list */
public void addElement(final WPE element)
{
// New elements get same class behavior as the array
element.useWidgetClass(use_class);
value.add(element);
firePropertyChange(null, Arrays.asList(element));
}
Expand Down Expand Up @@ -239,8 +241,7 @@ public void setValueFromObject(final Object value) throws Exception
element.setValueFromObject(el_value);
}

// Notify listeners of the whole array
firePropertyChange(this, null, this.value);
// Listeners already received remove/add/set events
}
catch (Throwable ex)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2015-2016 Oak Ridge National Laboratory.
* Copyright (c) 2015-2022 Oak Ridge National Laboratory.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -66,16 +66,6 @@ protected StructuredWidgetProperty(final Descriptor descriptor,
super(descriptor, widget, elements);
}

/** @return <code>true</code> if any element is using class support */
@Override
public boolean isUsingWidgetClass()
{
for (WidgetProperty<?> element : value)
if (element.isUsingWidgetClass())
return true;
return false;
}

/** @return <code>true</code> if all elements have default value */
@Override
public boolean isDefaultValue()
Expand All @@ -86,6 +76,15 @@ public boolean isDefaultValue()
return true;
}

@Override
public void useWidgetClass(boolean use_class)
{
// Update overall structure as well as each element
super.useWidgetClass(use_class);
for (WidgetProperty<?> element : value)
element.useWidgetClass(use_class);
}

/** @return <code>true</code> if all elements are read-only */
@Override
public boolean isReadonly()
Expand Down Expand Up @@ -142,35 +141,42 @@ public void setValue(final List<WidgetProperty<?>> value)
@Override
public void setValueFromObject(final Object new_value) throws Exception
{
if (new_value instanceof List)
{ // Allow assignment of another structure's value, i.e. list with same elements
final List<?> new_elements = (List<?>)new_value;
if (new_elements.size() != value.size())
throw new Exception("Elements of structure " + getName() + " must provide " + value.size() + " elements, got " + new_elements.size());
for (int i=0; i<value.size(); ++i)
{
final WidgetProperty<?> element = value.get(i);
final Object new_object = new_elements.get(i);
if (element.getClass() != new_object.getClass())
throw new Exception("Cannot set structure " + getName() + "." + element.getName() + " to " + new_object);

final WidgetProperty<?> new_element = (WidgetProperty<?>)new_object;
if (element.getName() != new_element.getName())
throw new Exception("Cannot set structure " + getName() + "." + element.getName() + " to " + new_element.getName());
try
{
element.setValueFromObject(new_element.getValue());
}
catch (Exception ex)
{
throw new Exception("Cannot set structure " + getName() + "." + element.getName() + " to " + new_element, ex);
}
}
// Notify listeners of the whole array
firePropertyChange(this, null, this.value);
final List<?> new_elements;

// May use other struct or list with elements
if (new_value instanceof StructuredWidgetProperty)
{
final StructuredWidgetProperty other = (StructuredWidgetProperty) new_value;
new_elements = other.value;
}
else if (new_value instanceof List)
new_elements = (List<?>)new_value;
else
throw new Exception("Elements of structure " + getName() + " cannot be assigned from " + new_value);

// Either way, element count and names of elements must match this struct
if (new_elements.size() != value.size())
throw new Exception("Elements of structure " + getName() + " must provide " + value.size() + " elements, got " + new_elements.size());
for (int i=0; i<value.size(); ++i)
{
final WidgetProperty<?> element = value.get(i);
final Object new_object = new_elements.get(i);
if (element.getClass() != new_object.getClass())
throw new Exception("Cannot set structure " + getName() + "." + element.getName() + " to " + new_object);

final WidgetProperty<?> new_element = (WidgetProperty<?>)new_object;
if (element.getName() != new_element.getName())
throw new Exception("Cannot set structure " + getName() + "." + element.getName() + " to " + new_element.getName());
try
{
element.setValueFromObject(new_element.getValue());
}
catch (Exception ex)
{
throw new Exception("Cannot set structure " + getName() + "." + element.getName() + " to " + new_element, ex);
}
}
// Listeners have been notified about each element in setValueFromObject
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2015-2016 Oak Ridge National Laboratory.
* Copyright (c) 2015-2022 Oak Ridge National Laboratory.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -227,15 +227,7 @@ public boolean isDefaultValue()
*/
public void useWidgetClass(final boolean use_class)
{
if (this.use_class == use_class)
return;

this.use_class = use_class;

// Editor for class model needs update, runtime doesn't
final DisplayModel model = getWidget().checkDisplayModel();
if (model != null && model.isClassModel())
firePropertyChange(null, null);
}

/** @return Is value of this property following
Expand Down
Loading