From 2df512af6a9a084641eff536c71b0521cde1add9 Mon Sep 17 00:00:00 2001 From: ksaintin Date: Fri, 10 Jan 2025 20:19:55 +0100 Subject: [PATCH] Get the description from VType first or PV using DisplayProvider interface, add a list of PV in the PVTable using TextArea --- .../pvtable/model/PVTableItem.java | 88 ++++++++++++------- .../applications/pvtable/ui/Messages.java | 1 + .../applications/pvtable/ui/PVTable.java | 39 ++++++-- .../pvtable/ui/messages.properties | 1 + .../pvtable/ui/messages_fr.properties | 1 + 5 files changed, 92 insertions(+), 38 deletions(-) diff --git a/app/pvtable/src/main/java/org/phoebus/applications/pvtable/model/PVTableItem.java b/app/pvtable/src/main/java/org/phoebus/applications/pvtable/model/PVTableItem.java index c6a8e9e6de..213376134d 100644 --- a/app/pvtable/src/main/java/org/phoebus/applications/pvtable/model/PVTableItem.java +++ b/app/pvtable/src/main/java/org/phoebus/applications/pvtable/model/PVTableItem.java @@ -18,6 +18,8 @@ import org.epics.vtype.Alarm; import org.epics.vtype.AlarmSeverity; import org.epics.vtype.AlarmStatus; +import org.epics.vtype.Display; +import org.epics.vtype.DisplayProvider; import org.epics.vtype.Time; import org.epics.vtype.VByteArray; import org.epics.vtype.VEnum; @@ -30,6 +32,7 @@ import org.phoebus.core.vtypes.VTypeHelper; import org.phoebus.pv.PV; import org.phoebus.pv.PVPool; +import org.phoebus.pv.PVPool.TypedName; import io.reactivex.rxjava3.disposables.Disposable; @@ -51,7 +54,7 @@ public class PVTableItem private volatile VType value; /** Value of the PV's description */ - private volatile String desc_value = ""; + private volatile String desc_value = null; private volatile String desc_name = ""; /** Saved (snapshot) value */ @@ -126,16 +129,24 @@ private void createPVs(final String name) updateValue(null); return; } + PV new_pv = null; try { updateValue(VString.of("", Alarm.disconnected(), Time.now())); - final PV new_pv = PVPool.getPV(name); + new_pv = PVPool.getPV(name); value_flow = new_pv.onValueEvent() .throttleLatest(Settings.max_update_period_ms, TimeUnit.MILLISECONDS) .subscribe(this::updateValue); permission_flow = new_pv.onAccessRightsEvent() .subscribe(writable -> listener.tableItemChanged(PVTableItem.this)); pv.set(new_pv); + // read the value for getting description + if (new_pv != null) { + VType newVal = new_pv.read(); + if(newVal != null){ + updateValue(newVal); + } + } } catch (Exception ex) { @@ -145,28 +156,23 @@ private void createPVs(final String name) Time.now())); } - // For CA PVs, check the .DESC field - // Hardcoded knowledge to avoid non-record PVs. - if (Settings.show_description && - ! (name.startsWith("sim:") || - name.startsWith("loc:"))) - { - // Determine DESC field. - //Bug when a pv name contains a . caracters - desc_name = name + DOT + DESC_FIELD; - if(!name.endsWith(DOT + DESC_FIELD) && name.contains(DOT)) { - // If name already includes a field - // It can be a EPICS fields such as .VAL .EGU ... - // EPICS fields are always in Upper Case - // EPICS fields are 4 characters length max + // First try to get description from value or pv + updateDescription(); + // If still no description found and channel access source + final TypedName type_name = TypedName.analyze(name); + String dataType = type_name != null ? type_name.type : null; + boolean channelAccess = dataType.equals("ca"); + if (Settings.show_description && desc_value == null && channelAccess) { + // For CA PVs, check the .DESC field + // Hardcoded knowledge to avoid non-record PVs. + // First get default datasource + desc_name = name + DOT + DESC_FIELD; // by default add .DESC + if (!name.endsWith(DOT + DESC_FIELD) && name.contains(DOT)) { final int sep = name.lastIndexOf('.'); String fieldVal = name.substring(sep + 1); - //System.out.println("fieldVal=" + fieldVal); - //Test if it in uppercase and max length 4 - boolean isEpicsField = fieldVal.toUpperCase().equals(fieldVal) && fieldVal.length() < 5; - if(isEpicsField) { - desc_name = name.replace(fieldVal, DESC_FIELD); - } + // then replace by .DESC + // Determine DESC field include dot in case of variable name such as variableEGUName + desc_name = name.replace(DOT + fieldVal, DOT + DESC_FIELD); } try @@ -190,6 +196,24 @@ private void createPVs(final String name) } } } + + private void updateDescription() { + if(desc_value == null) { + //update description from value or pv + VType currentValue = getValue(); + if(currentValue != null) { + PV thePV = pv.get(); + Display display = thePV instanceof DisplayProvider ? ((DisplayProvider) thePV).getDisplay() : null; + display = display == null && currentValue instanceof DisplayProvider ? ((DisplayProvider) currentValue).getDisplay(): display; + if (display != null) { + String description = display.getDescription(); + desc_value = description != null ? description : null; + desc_name = desc_value != null ? "Description of " + name + " PV" : "no description"; + desc_flow = value_flow; + } + } + } + } /** @return true if item is selected to be restored */ public boolean isSelected() @@ -255,9 +279,8 @@ public VType getValue() } /** @return Description */ - public String getDescription() - { - return desc_value; + public String getDescription() { + return desc_value == null ? "" : desc_value; } /** @return description pv name **/ @@ -305,14 +328,17 @@ public void setValue(String new_value) throw new Exception("Not connected"); final VType pv_type = the_pv.read(); - if (pv_type instanceof VNumber) - { - if (Settings.show_units) - { // Strip units so that only the number gets written - final String units = ((VNumber)pv_type).getDisplay().getUnit(); - if (units.length() > 0 && new_value.endsWith(units)) + Display display = the_pv instanceof DisplayProvider ? ((DisplayProvider) the_pv).getDisplay() : null; + display = display == null && pv_type instanceof DisplayProvider ? ((DisplayProvider) pv_type).getDisplay():null; + + if (display != null && Settings.show_units) { + // Strip units so that only the number gets written + final String units = display.getUnit(); + if (units.length() > 0 && new_value.endsWith(units)) new_value = new_value.substring(0, new_value.length() - units.length()).trim(); } + if (pv_type instanceof VNumber) + { the_pv.write(Double.parseDouble(new_value)); } else if (pv_type instanceof VEnum) diff --git a/app/pvtable/src/main/java/org/phoebus/applications/pvtable/ui/Messages.java b/app/pvtable/src/main/java/org/phoebus/applications/pvtable/ui/Messages.java index 493c06469e..527faafafa 100644 --- a/app/pvtable/src/main/java/org/phoebus/applications/pvtable/ui/Messages.java +++ b/app/pvtable/src/main/java/org/phoebus/applications/pvtable/ui/Messages.java @@ -14,6 +14,7 @@ public class Messages { /** Externalized strings */ public static String Alarm, + AddPVList, Description, CheckAll, CheckAll_TT, diff --git a/app/pvtable/src/main/java/org/phoebus/applications/pvtable/ui/PVTable.java b/app/pvtable/src/main/java/org/phoebus/applications/pvtable/ui/PVTable.java index 7699b736db..f2d2103800 100644 --- a/app/pvtable/src/main/java/org/phoebus/applications/pvtable/ui/PVTable.java +++ b/app/pvtable/src/main/java/org/phoebus/applications/pvtable/ui/PVTable.java @@ -69,7 +69,9 @@ import javafx.scene.control.TableRow; import javafx.scene.control.TableView; import javafx.scene.control.TableView.TableViewSelectionModel; +import javafx.scene.control.TextArea; import javafx.scene.control.TextField; +import javafx.scene.control.TextInputControl; import javafx.scene.control.ToolBar; import javafx.scene.control.Tooltip; import javafx.scene.control.cell.TextFieldTableCell; @@ -93,6 +95,7 @@ public class PVTable extends VBox private static final String comment_style = "-fx-text-fill: blue;"; private static final String new_item_style = "-fx-text-fill: gray;"; private static final String changed_style = "-fx-background-color: -fx-table-cell-border-color, cyan;-fx-background-insets: 0, 0 0 1 0;"; + private static final String SPLIT_PV = "[ \\t\\n\\r,]+"; /** When sorting, keep the 'NEW_ITEM' row at the bottom **/ private static final Comparator SORT_NEW_ITEM_LAST = (a, b) -> @@ -184,8 +187,9 @@ protected void updateItem(final String item, final boolean empty) /** Table cell for 'name' column, colors comments */ private static class PVNameTableCell extends TextFieldTableCell { - private TextField textField; - + private TextInputControl textField; + private static ContextMenu contextMenu; + public PVNameTableCell() { super(new DefaultStringConverter()); @@ -195,11 +199,26 @@ public PVNameTableCell() public void startEdit() { super.startEdit(); - textField = new TextField(); - textField.setOnAction(event -> commitEdit(textField.getText())); + final int index = getIndex(); + boolean newPv = index == getTableView().getItems().size() - 1; + if(newPv) { + textField = new TextArea(); + textField.setMaxHeight(100); + if(contextMenu == null) { + MenuItem addPVMenu = new MenuItem(Messages.AddPVList); + addPVMenu.setOnAction(event -> commitEdit(textField.getText())); + contextMenu = new ContextMenu(addPVMenu); + } + textField.setContextMenu(contextMenu); + } + else { + textField = new TextField(); + ((TextField)textField).setOnAction(event -> commitEdit(textField.getText())); + } PVAutocompleteMenu.INSTANCE.attachField(textField); showCurrentValue(); } + private void showCurrentValue() { @@ -775,8 +794,14 @@ private void createTableColumns() final TableItemProxy proxy = event.getRowValue(); if (proxy == TableItemProxy.NEW_ITEM) { - if (!new_name.isEmpty()) - model.addItem(new_name); + if (!new_name.isEmpty()) { + //Can be a list of pv + final String[] pvs = new_name.split(SPLIT_PV); + //Add a list + for(String pv : pvs) { + model.addItem(pv); + } + } // else: No name entered, do nothing } else @@ -976,7 +1001,7 @@ else if (db.hasString()) private void addPVsFromString(final PVTableItem existing, final String pv_text) { - final String[] pvs = pv_text.split("[ \\t\\n\\r,]+"); + final String[] pvs = pv_text.split(SPLIT_PV); for (String pv : pvs) if (! pv.isEmpty()) model.addItemAbove(existing, pv); diff --git a/app/pvtable/src/main/resources/org/phoebus/applications/pvtable/ui/messages.properties b/app/pvtable/src/main/resources/org/phoebus/applications/pvtable/ui/messages.properties index 43e0e1dde9..ab62a29720 100644 --- a/app/pvtable/src/main/resources/org/phoebus/applications/pvtable/ui/messages.properties +++ b/app/pvtable/src/main/resources/org/phoebus/applications/pvtable/ui/messages.properties @@ -1,4 +1,5 @@ Alarm=Alarm +AddPVList=Add a list of pv Description=Description CheckAll=Check All CheckAll_TT=Check all PVs in table diff --git a/app/pvtable/src/main/resources/org/phoebus/applications/pvtable/ui/messages_fr.properties b/app/pvtable/src/main/resources/org/phoebus/applications/pvtable/ui/messages_fr.properties index 64a1976d73..7b069fb941 100644 --- a/app/pvtable/src/main/resources/org/phoebus/applications/pvtable/ui/messages_fr.properties +++ b/app/pvtable/src/main/resources/org/phoebus/applications/pvtable/ui/messages_fr.properties @@ -1,4 +1,5 @@ Alarm=Alarme +AddPVList=Ajout d une liste de pv Description=Description CheckAll=Tout sélectionner CheckAll_TT=Sélectionner tous les PVs dans le tableau