Skip to content

Commit 89c9591

Browse files
committed
Update the widget info to allow simpler selection of PV's
1 parent 5b5ed1f commit 89c9591

File tree

2 files changed

+76
-17
lines changed

2 files changed

+76
-17
lines changed

app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/WidgetInfoDialog.java

Lines changed: 73 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,14 @@
1818
import java.util.Objects;
1919
import java.util.logging.Level;
2020
import java.util.logging.Logger;
21-
21+
import java.util.stream.Collectors;
22+
23+
import javafx.event.EventHandler;
24+
import javafx.scene.control.ContextMenu;
25+
import javafx.scene.control.MenuItem;
26+
import javafx.scene.control.SelectionMode;
27+
import javafx.scene.control.cell.PropertyValueFactory;
28+
import javafx.scene.input.ContextMenuEvent;
2229
import org.csstudio.display.builder.model.DisplayModel;
2330
import org.csstudio.display.builder.model.Widget;
2431
import org.csstudio.display.builder.model.WidgetDescriptor;
@@ -31,8 +38,12 @@
3138
import org.epics.vtype.AlarmSeverity;
3239
import org.epics.vtype.VNumberArray;
3340
import org.epics.vtype.VType;
41+
import org.phoebus.core.types.ProcessVariable;
3442
import org.phoebus.core.vtypes.VTypeHelper;
43+
import org.phoebus.framework.adapter.AdapterService;
3544
import org.phoebus.framework.macros.Macros;
45+
import org.phoebus.framework.selection.SelectionService;
46+
import org.phoebus.ui.application.ContextMenuService;
3647
import org.phoebus.ui.dialog.DialogHelper;
3748
import org.phoebus.ui.dialog.ExceptionDetailsErrorDialog;
3849
import org.phoebus.ui.javafx.ReadOnlyTextCell;
@@ -61,6 +72,7 @@
6172
import javafx.scene.layout.Priority;
6273
import javafx.scene.layout.VBox;
6374
import javafx.stage.FileChooser;
75+
import org.phoebus.ui.spi.ContextMenuEntry;
6476

6577
/** Dialog for displaying widget information
6678
* @author Kay Kasemir
@@ -75,16 +87,14 @@ public class WidgetInfoDialog extends Dialog<Boolean>
7587
private DisplayWidgetStats stats;
7688

7789
/** PV info */
78-
public static class NameStateValue
90+
public static class NameStateValue extends ProcessVariable
7991
{
80-
/** PV Name */
81-
public final String name;
8292
/** State, incl. read-only or writable? */
83-
public final String state;
93+
private final String state;
8494
/** Last known value */
85-
public final VType value;
95+
private final VType value;
8696
/** Path to Widget within display that uses the PV */
87-
public final String path;
97+
private final String path;
8898

8999
/** @param name PV Name
90100
* @param state State, incl. read-only or writable?
@@ -93,11 +103,23 @@ public static class NameStateValue
93103
*/
94104
public NameStateValue(final String name, final String state, final VType value, final String path)
95105
{
96-
this.name = name;
106+
super(name);
97107
this.state = state;
98108
this.value = value;
99109
this.path = path;
100110
}
111+
112+
public String getState() {
113+
return state;
114+
}
115+
116+
public VType getValue() {
117+
return value;
118+
}
119+
120+
public String getPath() {
121+
return path;
122+
}
101123
}
102124

103125
/** Cell with text colored based on alarm severity */
@@ -209,8 +231,8 @@ private void exportToCSV(File file){
209231

210232
buffer.append("PVS (name, state, value, widget path)").append(System.lineSeparator())
211233
.append(horizontalRuler).append(System.lineSeparator());
212-
pvs.stream().sorted(Comparator.comparing(pv -> pv.name)).forEach(pv -> {
213-
buffer.append(pv.name).append(itemSeparator)
234+
pvs.stream().sorted(Comparator.comparing(pv -> pv.getName())).forEach(pv -> {
235+
buffer.append(pv.getName()).append(itemSeparator)
214236
.append(pv.state)
215237
.append(itemSeparator)
216238
.append(getPVValue(pv.value))
@@ -292,16 +314,13 @@ private Tab createPVs(final Collection<NameStateValue> pvs)
292314
{
293315
// Use text field to allow users to copy the name, value to clipboard
294316
final TableColumn<NameStateValue, String> name = new TableColumn<>(Messages.WidgetInfoDialog_Name);
295-
name.setCellFactory(col -> new ReadOnlyTextCell<>());
296-
name.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().name));
317+
name.setCellValueFactory(new PropertyValueFactory<NameStateValue, String>("name"));
297318

298319
final TableColumn<NameStateValue, String> state = new TableColumn<>(Messages.WidgetInfoDialog_State);
299-
state.setCellFactory(col -> new ReadOnlyTextCell<>());
300-
state.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().state));
320+
state.setCellValueFactory(new PropertyValueFactory<NameStateValue, String>("state"));
301321

302322
final TableColumn<NameStateValue, String> path = new TableColumn<>(Messages.WidgetInfoDialog_Path);
303-
path.setCellFactory(col -> new ReadOnlyTextCell<>());
304-
path.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().path));
323+
path.setCellValueFactory(new PropertyValueFactory<NameStateValue, String>("path"));
305324

306325
final TableColumn<NameStateValue, String> value = new TableColumn<>(Messages.WidgetInfoDialog_Value);
307326
value.setCellFactory(col -> new AlarmColoredCell());
@@ -312,14 +331,51 @@ private Tab createPVs(final Collection<NameStateValue> pvs)
312331
});
313332

314333
final ObservableList<NameStateValue> pv_data = FXCollections.observableArrayList(pvs);
315-
pv_data.sort(Comparator.comparing(a -> a.name));
334+
pv_data.sort(Comparator.comparing(a -> a.getName()));
316335
final TableView<NameStateValue> table = new TableView<>(pv_data);
317336
table.getColumns().add(name);
318337
table.getColumns().add(state);
319338
table.getColumns().add(value);
320339
table.getColumns().add(path);
321340
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
322341

342+
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
343+
table.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSelection) -> {
344+
if (newSelection != null) {
345+
SelectionService.getInstance().setSelection(table, table.getSelectionModel().getSelectedItems());
346+
}
347+
});
348+
349+
table.setOnContextMenuRequested(event -> {
350+
351+
final ContextMenu contextMenu = new ContextMenu();
352+
353+
List<ContextMenuEntry> contextEntries = ContextMenuService.getInstance().listSupportedContextMenuEntries();
354+
355+
contextEntries.forEach(entry -> {
356+
MenuItem item = new MenuItem(entry.getName(), new ImageView(entry.getIcon()));
357+
item.setOnAction(e -> {
358+
try {
359+
ObservableList<NameStateValue> old = table.getSelectionModel().getSelectedItems();
360+
361+
List<Object> selectedPVs = SelectionService.getInstance().getSelection().getSelections().stream().map(s -> {
362+
return AdapterService.adapt(s, entry.getSupportedType()).get();
363+
}).collect(Collectors.toList());
364+
// set the selection
365+
SelectionService.getInstance().setSelection(table, selectedPVs);
366+
entry.call(SelectionService.getInstance().getSelection());
367+
// reset the selection
368+
SelectionService.getInstance().setSelection(table, old);
369+
} catch (Exception ex) {
370+
//logger.log(Level.WARNING, "Failed to execute action " + entry.getName(), ex);
371+
}
372+
});
373+
contextMenu.getItems().add(item);
374+
});
375+
376+
table.setContextMenu(contextMenu);
377+
});
378+
323379
return new Tab(Messages.WidgetInfoDialog_TabPVs, table);
324380
}
325381

core/types/src/main/java/org/phoebus/core/types/TimeStampedProcessVariable.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import java.time.Instant;
44

5+
/**
6+
* A PV with a Timestamp
7+
*/
58
@SuppressWarnings("nls")
69
public class TimeStampedProcessVariable extends ProcessVariable {
710

0 commit comments

Comments
 (0)