diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/util/ModelResourceUtil.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/util/ModelResourceUtil.java
index 3cc941179f..f2f3831391 100644
--- a/app/display/model/src/main/java/org/csstudio/display/builder/model/util/ModelResourceUtil.java
+++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/util/ModelResourceUtil.java
@@ -258,6 +258,7 @@ private static String URLdecode(final String text)
}
catch (UnsupportedEncodingException ex)
{
+ logger.log(Level.SEVERE, "Impossible to decode {0} because {1}", new Object[] { text, ex.getMessage() });
return text;
}
}
@@ -299,6 +300,7 @@ private static String doResolveResource(final String parent_display, final Strin
}
// Give up
+ logger.log(Level.WARNING, " {0} is not resolved ", new Object[] { resource_name});
return null;
}
@@ -319,12 +321,15 @@ private static boolean canOpenUrl(final String resource_name)
}
catch (Exception ex)
{
+ logger.log(Level.SEVERE, "Impossible to open stream on {0} because of {1}", new Object[] { resource_name, ex.getMessage() });
return false;
}
}
- if (! isURL(resource_name))
+ if (! isURL(resource_name)) {
+ logger.log(Level.WARNING, "URL {0} is not a URL", new Object[] { resource_name });
return false;
+ }
// This implementation is expensive:
// On success, caller will soon open the URL again.
// In practice, not too bad because second time around
@@ -344,12 +349,17 @@ private static boolean canOpenUrl(final String resource_name)
try
{
- final InputStream stream = openURL(resource_name);
- stream.close();
+// final InputStream stream = openURL(resource_name);
+// stream.close();
+ //Test only if the page exist and not read the content
+ final String escaped = resource_name.replace(" ", "%20");
+ URL resource = new URL(escaped);
+ resource.openConnection();
return true;
}
catch (Exception ex)
{
+ logger.log(Level.SEVERE, "Impossible to open connection on URL {0} because of {1}", new Object[] { resource_name, ex.getMessage() });
return false;
}
}
@@ -397,7 +407,7 @@ public static File getFile(final URI resource) throws Exception
// .. but once examples are inside the jar,
// we can only read them as a stream.
// There is no File access.
- logger.log(Level.WARNING, "Cannot get `File` for " + url);
+ logger.log(Level.WARNING, "Cannot get `File` for " + url + " " + ex.getMessage());
return null;
}
}
@@ -488,7 +498,6 @@ public static InputStream openURL(final String resource_name) throws Exception
private static final byte[] readUrl(final String url) throws Exception
{
- // System.out.println("Actually reading " + url + ", not cached");
final InputStream in = openURL(url, timeout_ms);
final ByteArrayOutputStream buf = new ByteArrayOutputStream();
IOUtils.copy(in, buf);
diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/Messages.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/Messages.java
index 9f0b610d55..a3192c175e 100644
--- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/Messages.java
+++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/Messages.java
@@ -130,6 +130,9 @@ public class Messages
ShowErrorDialogTitle,
ShowMessageDialogTitle,
ShowSaveAsDialogTitle,
+ WebPageErrorDetails,
+ WebPageErrorLoading,
+ WebPageErrorMessage,
WidgetColorPopOver_Alpha,
WidgetColorPopOver_Blue,
WidgetColorPopOver_Color,
diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/WebBrowserRepresentation.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/WebBrowserRepresentation.java
index 046b7ecfbf..de226ffae3 100644
--- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/WebBrowserRepresentation.java
+++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/WebBrowserRepresentation.java
@@ -18,6 +18,7 @@
import org.csstudio.display.builder.model.WidgetPropertyListener;
import org.csstudio.display.builder.model.util.ModelResourceUtil;
import org.csstudio.display.builder.model.widgets.WebBrowserWidget;
+import org.csstudio.display.builder.representation.javafx.Messages;
import org.phoebus.framework.jobs.JobManager;
import org.phoebus.framework.util.IOUtils;
import org.phoebus.ui.javafx.ImageCache;
@@ -102,7 +103,22 @@ protected void goToURL(String url)
// still defaulting to "http://".
else if (url.indexOf("://") < 0)
url = "http://" + url;
- webEngine.load(url);
+
+ //Try to open page to test if we can open page
+ try {
+ InputStream openURL = ModelResourceUtil.openURL(url, 0);
+ openURL.close();
+ webEngine.load(url);
+ }
+ catch (Exception e) {
+ //if there is an error display a error page in engine
+ StringBuilder errorMessage = new StringBuilder();
+ errorMessage.append(""+Messages.WebPageErrorLoading+" :
");
+ errorMessage.append(""+url+"
");
+ errorMessage.append(""+Messages.WebPageErrorMessage+" : " + e.getMessage() + "
");
+ errorMessage.append(""+Messages.WebPageErrorDetails+" : " + e.toString());
+ webEngine.loadContent(errorMessage.toString());
+ }
}
private void download(final String url, final String file)
diff --git a/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages.properties b/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages.properties
index d0a178c137..dea595c601 100644
--- a/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages.properties
+++ b/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages.properties
@@ -120,6 +120,9 @@ ShowConfirmationDialogTitle=Please Confirm
ShowErrorDialogTitle=Error
ShowMessageDialogTitle=Message
ShowSaveAsDialogTitle=Save As
+WebPageErrorDetails=Error details
+WebPageErrorLoading=Error when loading page
+WebPageErrorMessage=Error message
WidgetColorPopOver_Hex=Hex Value:
WidgetColorPopOver_Alpha=Alpha:
WidgetColorPopOver_Blue=Blue:
diff --git a/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages_fr.properties b/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages_fr.properties
index 20776d4b50..a0fbc701ae 100644
--- a/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages_fr.properties
+++ b/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages_fr.properties
@@ -2,18 +2,18 @@ ActionButton_N_ActionsAsOneFmt={0} actions
ActionButton_N_ActionsFmt=Choisissez 1 parmi {0}
ActionButton_NoActions=VIDE
ActionsDialog_Actions=Actions :
-ActionsDialog_Detail=Détail de l’action :
+ActionsDialog_Detail=D\u00E9tail de l’action :
ActionsDialog_DisplayPath=Chemin de l’affichage :
-ActionsDialog_ExecuteAll=Exécuter toutes les actions en une seule fois
+ActionsDialog_ExecuteAll=Ex\u00E9cuter toutes les actions en une seule fois
ActionsDialog_FilePath=Chemin du fichier :
-ActionsDialog_Info=Configurer les actions qui ouvrent des affichages, écrivent des PV, etc.
+ActionsDialog_Info=Configurer les actions qui ouvrent des affichages, \u00E9crivent des PV, etc.
ActionsDialog_PVName=Nom du PV :
ActionsDialog_ScriptPath=Fichier de script :
-ActionsDialog_ScriptText=Texte du script intégré :
+ActionsDialog_ScriptText=Texte du script int\u00E9gr\u00E9 :
ActionsDialog_Title=Actions
Add=Ajouter
-AddEmbeddedJavaScript=Ajouter JavaScript intégré\u2026
-AddEmbeddedPython=Ajouter Python intégré\u2026
+AddEmbeddedJavaScript=Ajouter JavaScript int\u00E9gr\u00E9\u2026
+AddEmbeddedPython=Ajouter Python int\u00E9gr\u00E9\u2026
AddJavaScriptFile=Ajouter un fichier JavaScript
AddPythonFile=Ajouter un fichier Python
Alpha=Alpha
@@ -21,24 +21,24 @@ Blue=Bleu
BoolButtonError_Body=Le dialogue de confirmation est pris en charge uniquement pour le mode toggle.
BoolButtonError_Title=Configuration non prise en charge
ColorDialog_Current=Actuel
-ColorDialog_Custom=Couleur personnalisée
-ColorDialog_Default=Défaut
-ColorDialog_Info=Séléctionnez une couleur prédéfinie, ou une couleur personnalisée
+ColorDialog_Custom=Couleur personnalis\u00E9e
+ColorDialog_Default=D\u00E9faut
+ColorDialog_Info=S\u00E9l\u00E9ctionnez une couleur pr\u00E9d\u00E9finie, ou une couleur personnalis\u00E9e
ColorDialog_Original=Original
-ColorDialog_Predefined=Couleurs prédéfinies
+ColorDialog_Predefined=Couleurs pr\u00E9d\u00E9finies
ColorDialog_Title_FMT=Choisir {0}
-ColorMap_Custom=Carte de couleurs personnalisée
+ColorMap_Custom=Carte de couleurs personnalis\u00E9e
ColorMapDialog_Add=Ajouter une couleur
ColorMapDialog_Color=Couleur
-ColorMapDialog_Info=Séléctionnez une carte de couleurs prédéfinie. Optionnellement, personnalisez-la.
-ColorMapDialog_PredefinedMap=Carte de couleurs prédéfinie
+ColorMapDialog_Info=S\u00E9l\u00E9ctionnez une carte de couleurs pr\u00E9d\u00E9finie. Optionnellement, personnalisez-la.
+ColorMapDialog_PredefinedMap=Carte de couleurs pr\u00E9d\u00E9finie
ColorMapDialog_Remove=Supprimer la couleur
-ColorMapDialog_Result=Résultat
+ColorMapDialog_Result=R\u00E9sultat
ColorMapDialog_Title=Carte de couleurs
ColorMapDialog_Value=Valeur (0-255)
Column=Colonne
-ConvertToEmbeddedJavaScript=Convertir en JavaScript intégré\u2026
-ConvertToEmbeddedPython=Convertir en Python intégré\u2026
+ConvertToEmbeddedJavaScript=Convertir en JavaScript int\u00E9gr\u00E9\u2026
+ConvertToEmbeddedPython=Convertir en Python int\u00E9gr\u00E9\u2026
ConvertToScriptFile=Convertir en fichier script
Copy=Copier
Duplicate=Dupliquer
@@ -46,14 +46,14 @@ Edit=Modifier\u2026
ExportWidgetInfo=Exporter vers un fichier
CopyWidgetInfo=Afficher liste des Pv
CopyButton =Copier dans le press-papier
-ExportDone=Informations sur le widget exportées dans le fichier {0}.
-ExportFailed=Échec de l’exportation.
+ExportDone=Informations sur le widget export\u00E9es dans le fichier {0}.
+ExportFailed=\u00C9chec de l’exportation.
FileTypeAll=Tous les fichiers (*.*)
FileTypeDisplays=Affichages (*.bob)
FontDialog_ExampleText=Texte exemple
-FontDialog_Family=Police personnalisée :
-FontDialog_Info=Séléctionnez une police prédéfinie, ou une police personnalisée
-FontDialog_Predefined=Polices prédéfinies
+FontDialog_Family=Police personnalis\u00E9e :
+FontDialog_Info=S\u00E9l\u00E9ctionnez une police pr\u00E9d\u00E9finie, ou une police personnalis\u00E9e
+FontDialog_Predefined=Polices pr\u00E9d\u00E9finies
FontDialog_Preview=Aperçu :
FontDialog_Size=Taille :
FontDialog_Style=Style :
@@ -67,17 +67,17 @@ MacrosDialog_NameCol=Nom de la macro
MacrosDialog_Title=Macros
MacrosDialog_ValueCol=Valeur
MacrosTable_NameHint=
-MacrosTable_ToolTip=Modifier les noms ou les valeurs. Ajouter une nouvelle macro dans la dernière ligne
+MacrosTable_ToolTip=Modifier les noms ou les valeurs. Ajouter une nouvelle macro dans la derni\u00E8re ligne
MacrosTable_ValueHint=
MoveDown=Vers le bas
MoveUp=Vers le haut
-NotSet=Non défini
-OpenInExternalEditor=Ouvrir dans un éditeur externe
+NotSet=Non d\u00E9fini
+OpenInExternalEditor=Ouvrir dans un \u00E9diteur externe
Password=Mot de passe
Password_Caption=Mot de passe :
Password_Error=Mot de passe incorrect
Password_Prompt=Entrer le mot de passe
-PointsDialog_Info=Modifier les coordonnées des points
+PointsDialog_Info=Modifier les coordonn\u00E9es des points
PointsDialog_Title=Modifier les points
PointsTable_Empty=Pas de points
PointsTable_X=X
@@ -85,80 +85,83 @@ PointsTable_Y=Y
Red=Rouge
Remove=Supprimer
Row=Ligne
-RulesDialog_ColName=Règle
-RulesDialog_ColBoolExp=Expression booléenne
+RulesDialog_ColName=R\u00E8gle
+RulesDialog_ColBoolExp=Expression bool\u00E9enne
RulesDialog_ColValExp=Expression de valeur
-RulesDialog_DefaultRuleName=Nouvelle règle
+RulesDialog_DefaultRuleName=Nouvelle r\u00E8gle
RulesDialog_ExpressionsTT=Modifier les expressions
-RulesDialog_Info=Modifier les règles pour le widget
+RulesDialog_Info=Modifier les r\u00E8gles pour le widget
RulesDialog_NoExpressions=Pas d’expressions dans le tableau.
RulesDialog_NoPVs=Pas de PVs dans le tableau.
-RulesDialog_NoRules=Pas de règles dans le tableau.
-RulesDialog_PVsTT=Modifier les noms des PV et sélectionner si les changements de leur valeur déclenchent l’exécution de la règle
-RulesDialog_RulesTT=Modifier les règles
-RulesDialog_SelectRule=Séléctionner la règle pour voir/ajouter PV/Expression
+RulesDialog_NoRules=Pas de r\u00E8gles dans le tableau.
+RulesDialog_PVsTT=Modifier les noms des PV et s\u00E9lectionner si les changements de leur valeur d\u00E9clenchent l’ex\u00E9cution de la r\u00E8gle
+RulesDialog_RulesTT=Modifier les r\u00E8gles
+RulesDialog_SelectRule=S\u00E9l\u00E9ctionner la r\u00E8gle pour voir/ajouter PV/Expression
RulesDialog_ShowScript=Afficher le script
-RulesDialog_Title=Règles
-ScriptsDialog_BtnEmbedJS=Intégrer JS
-ScriptsDialog_BtnEmbedPy=Intégrer Py
+RulesDialog_Title=R\u00E8gles
+ScriptsDialog_BtnEmbedJS=Int\u00E9grer JS
+ScriptsDialog_BtnEmbedPy=Int\u00E9grer Py
ScriptsDialog_BtnFile=Fichier
-ScriptsDialog_CheckConnections=Déclencher uniquement lorsque tous les PVs sont connectés
+ScriptsDialog_CheckConnections=D\u00E9clencher uniquement lorsque tous les PVs sont connect\u00E9s
ScriptsDialog_ColPV=Nom du PV
ScriptsDialog_ColScript=Script
-ScriptsDialog_ColTrigger=Déclencheur
+ScriptsDialog_ColTrigger=D\u00E9clencheur
ScriptsDialog_DefaultScriptFile=mon_script.py
ScriptsDialog_Info=Modifier les scripts et leurs PVs
ScriptsDialog_JavaScriptScriptFile=mon_script.js
ScriptsDialog_NoScripts=Pas de scripts dans le tableau.
ScriptsDialog_NoPVs=Pas de PVs dans le tableau.
-ScriptsDialog_PVsTT=Modifier les noms des PV et sélectionner si les changements de leur valeur déclenchent l’exécution du script
+ScriptsDialog_PVsTT=Modifier les noms des PV et s\u00E9lectionner si les changements de leur valeur d\u00E9clenchent l’ex\u00E9cution du script
ScriptsDialog_PythonScriptFile=mon_script.py
-ScriptsDialog_ScriptsTT=Séléctionner le fichier script externe ou modifier le texte du script intégré
+ScriptsDialog_ScriptsTT=S\u00E9l\u00E9ctionner le fichier script externe ou modifier le texte du script int\u00E9gr\u00E9
ScriptsDialog_Title=Scripts
-Select=Séléctionner\u2026
+Select=S\u00E9l\u00E9ctionner\u2026
ShowConfirmationDialogTitle=Veuillez confirmer
ShowErrorDialogTitle=Erreur
ShowMessageDialogTitle=Message
ShowSaveAsDialogTitle=Enregistrer sous
+WebPageErrorDetails=D\u00E9tails de l\u0027erreur
+WebPageErrorLoading=Erreur au chargement de la page
+WebPageErrorMessage=Message d\u0027erreur
WidgetColorPopOver_Hex=Valeur Hex :
WidgetColorPopOver_Alpha=Alpha :
WidgetColorPopOver_Blue=Bleu :
WidgetColorPopOver_Color=Couleur :
-WidgetColorPopOver_CustomColor=Couleur personnalisée
-WidgetColorPopOver_Default=défaut
-WidgetColorPopOver_DefaultButton=Défaut
-WidgetColorPopOver_Info={0} \u2013 Séléctionnez une couleur prédéfinie et/ou personnalisez-la.
+WidgetColorPopOver_CustomColor=Couleur personnalis\u00E9e
+WidgetColorPopOver_Default=d\u00E9faut
+WidgetColorPopOver_DefaultButton=D\u00E9faut
+WidgetColorPopOver_Info={0} \u2013 S\u00E9l\u00E9ctionnez une couleur pr\u00E9d\u00E9finie et/ou personnalisez-la.
WidgetColorPopOver_Green=Vert :
WidgetColorPopOver_Original=original
-WidgetColorPopOver_PredefinedColors=Couleurs prédéfinies
+WidgetColorPopOver_PredefinedColors=Couleurs pr\u00E9d\u00E9finies
WidgetColorPopOver_Red=Rouge :
WidgetColorPopOver_SearchField=Rechercher
WidgetColorPopOver_SearchFieldTT=Filtrer les couleurs par nom
WidgetFontPopOver_ExampleText=Texte exemple
WidgetFontPopOver_FontsFamilies=Familles de polices
-WidgetFontPopOver_Info={0} \u2013 Séléctionnez une police prédéfinie et/ou personnalisez-la.
-WidgetFontPopOver_PredefinedFonts=Polices prédéfinies
+WidgetFontPopOver_Info={0} \u2013 S\u00E9l\u00E9ctionnez une police pr\u00E9d\u00E9finie et/ou personnalisez-la.
+WidgetFontPopOver_PredefinedFonts=Polices pr\u00E9d\u00E9finies
WidgetFontPopOver_Preview=Aperçu
WidgetFontPopOver_PreviewPrompt=Entrez votre texte pour un aperçu.
WidgetFontPopOver_SearchPrompt=Rechercher
WidgetFontPopOver_SearchPromptTT=Filtrer les polices par nom
WidgetFontPopOver_SizeCaption=Taille :
-WidgetFontPopOver_SizePrompt=Entrez ou séléctionnez la taille de la police
+WidgetFontPopOver_SizePrompt=Entrez ou s\u00E9l\u00E9ctionnez la taille de la police
WidgetFontPopOver_Sizes=Tailles
WidgetFontPopOver_StyleCaption=Style :
-WidgetFontPopOver_StylePrompt=Séléctionnez le style de la police
+WidgetFontPopOver_StylePrompt=S\u00E9l\u00E9ctionnez le style de la police
WidgetFontPopOver_Styles=Styles
-WidgetInfoDialog_Category=Catégorie
+WidgetInfoDialog_Category=Cat\u00E9gorie
WidgetInfoDialog_Count=Nombre
-WidgetInfoDialog_Disconnected=Déconnecté
+WidgetInfoDialog_Disconnected=D\u00E9connect\u00E9
WidgetInfoDialog_Info_Fmt=Widget "{0}" ({1})
WidgetInfoDialog_Name=Nom
WidgetInfoDialog_Path=Chemin du widget
-WidgetInfoDialog_Property=Propriété
-WidgetInfoDialog_State=État
+WidgetInfoDialog_Property=Propri\u00E9t\u00E9
+WidgetInfoDialog_State=\u00C9tat
WidgetInfoDialog_WidgetStats=Statistiques des widgets
WidgetInfoDialog_TabMacros=Macros
-WidgetInfoDialog_TabProperties=Propriétés
+WidgetInfoDialog_TabProperties=Propri\u00E9t\u00E9s
WidgetInfoDialog_TabPVs=PV
WidgetInfoDialog_Title=Infos du widget
WidgetInfoDialog_Total=Total
@@ -167,4 +170,4 @@ WidgetInfoDialog_WidgetType=Type de widget
Zoom_All=Tout
Zoom_Height=Hauteur
Zoom_Width=Largeur
-Reset_Axis_Ranges=Réinitialiser les axes
+Reset_Axis_Ranges=R\u00E9initialiser les axes
\ No newline at end of file
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 6e902bb4b9..d9f8f4b009 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
@@ -20,7 +20,9 @@
import org.epics.vtype.AlarmStatus;
import org.epics.vtype.Display;
import org.epics.vtype.DisplayProvider;
+import org.epics.vtype.EnumDisplay;
import org.epics.vtype.Time;
+import org.epics.vtype.VBoolean;
import org.epics.vtype.VByteArray;
import org.epics.vtype.VEnum;
import org.epics.vtype.VEnumArray;
@@ -82,6 +84,8 @@ public class PVTableItem
/** Listener to description PV */
private volatile Disposable desc_flow;
+ private volatile String[] valueOptions = null;
+
private static final String DESC_FIELD = "DESC";
private static final String DOT = ".";
@@ -202,18 +206,23 @@ private void updateDescription() {
//update description from value or pv
VType currentValue = getValue();
if(currentValue != null) {
- PV thePV = pv.get();
- // DisplayProvider is an optional interface for VType values,
- // not PVs, but the custum datasource as Muscade happens to implement
- // DisplayProvider for enum and bool PVs, so check for that here
- Display display = thePV instanceof DisplayProvider ? ((DisplayProvider) thePV).getDisplay() : null;
- display = display == null && currentValue instanceof DisplayProvider ? ((DisplayProvider) currentValue).getDisplay(): display;
+ String description = null;
+ // DisplayProvider is an optional interface for VType values,
+ // not PVs, but the custum datasource as Muscade happens to implement
+ // DisplayProvider for enum and bool PVs, so check for that here
+ Display display = currentValue instanceof DisplayProvider ? ((DisplayProvider) currentValue).getDisplay(): null;
+ if(display == null && currentValue instanceof VEnum){
+ EnumDisplay enumdisplay = ((VEnum) currentValue).getDisplay();
+ if(enumdisplay instanceof DisplayProvider){
+ display = ((DisplayProvider)enumdisplay).getDisplay();
+ }
+ }
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;
+ description = display.getDescription();
}
+ desc_value = description != null ? description : null;
+ desc_name = desc_value != null ? "Description of " + name + " PV" : "no description";
+ desc_flow = value_flow;
}
}
}
@@ -283,6 +292,7 @@ public VType getValue()
/** @return Description */
public String getDescription() {
+ updateDescription();
return desc_value == null ? "" : desc_value;
}
@@ -294,11 +304,34 @@ public String getDescriptionName() {
/** @return Enum options for current value, null if not enumerated */
public String[] getValueOptions()
{
+ if(valueOptions == null) {//To avoid to get choices each times
+ final VType copy = value;
+ EnumDisplay enumDisplay = null;
+ if (copy instanceof VEnum) {
+ enumDisplay = ((VEnum) copy).getDisplay();
+ if(enumDisplay != null) {
+ final List options = enumDisplay.getChoices();
+ valueOptions = options.toArray(new String[options.size()]);
+ }
+ }
+ else if(copy instanceof VBoolean) {
+ valueOptions = new String[] {"0", "1"};
+ }
+ }
+ return valueOptions;
+ }
+
+ /** @return index in case of Enum value */
+ public int getIndex() {
+ int index = - 1;
final VType copy = value;
- if (!(copy instanceof VEnum))
- return null;
- final List options = ((VEnum) copy).getDisplay().getChoices();
- return options.toArray(new String[options.size()]);
+ if (copy instanceof VEnum) {
+ index = ((VEnum) copy).getIndex();
+ }
+ else if(copy instanceof VBoolean) {//To manage index for ZNAM & ONAM value
+ index = ((VBoolean)copy).getValue() ? 1 : 0;
+ }
+ return index;
}
/** @return true when PV is writable */
diff --git a/app/pvtable/src/main/java/org/phoebus/applications/pvtable/model/SavedScalarValue.java b/app/pvtable/src/main/java/org/phoebus/applications/pvtable/model/SavedScalarValue.java
index ea51f1000b..12bac572da 100644
--- a/app/pvtable/src/main/java/org/phoebus/applications/pvtable/model/SavedScalarValue.java
+++ b/app/pvtable/src/main/java/org/phoebus/applications/pvtable/model/SavedScalarValue.java
@@ -9,6 +9,7 @@
import java.util.concurrent.TimeUnit;
+import org.epics.vtype.VBoolean;
import org.epics.vtype.VDouble;
import org.epics.vtype.VEnum;
import org.epics.vtype.VFloat;
@@ -59,6 +60,13 @@ public boolean isEqualTo(final VType current_value, final double tolerance) thro
final int v2 = Integer.parseInt(saved_value);
return Math.abs(v2 - v1) <= tolerance;
}
+ if (current_value instanceof VBoolean)
+ {
+ boolean boolVal = ((VBoolean) current_value).getValue();
+ final int v1 = boolVal ? 1 : 0;
+ final int v2 = Integer.parseInt(saved_value);
+ return Math.abs(v2 - v1) <= tolerance;
+ }
throw new Exception("Cannot compare against unhandled type " + current_value.getClass().getName());
}
diff --git a/app/pvtable/src/main/java/org/phoebus/applications/pvtable/model/VTypeFormatter.java b/app/pvtable/src/main/java/org/phoebus/applications/pvtable/model/VTypeFormatter.java
index 0c61a80338..3fe909b92a 100644
--- a/app/pvtable/src/main/java/org/phoebus/applications/pvtable/model/VTypeFormatter.java
+++ b/app/pvtable/src/main/java/org/phoebus/applications/pvtable/model/VTypeFormatter.java
@@ -8,12 +8,15 @@
package org.phoebus.applications.pvtable.model;
import java.text.NumberFormat;
+import java.util.List;
import java.util.stream.Collectors;
import org.epics.util.array.IteratorNumber;
import org.epics.util.array.ListByte;
import org.epics.vtype.Alarm;
import org.epics.vtype.AlarmSeverity;
+import org.epics.vtype.EnumDisplay;
+import org.epics.vtype.VBoolean;
import org.epics.vtype.VByteArray;
import org.epics.vtype.VDoubleArray;
import org.epics.vtype.VEnum;
@@ -69,16 +72,34 @@ final public static String toString(final VType value)
}
if (value instanceof VEnum)
{
- final VEnum ev = (VEnum) value;
- try
- {
- return ev.getIndex() + " = " + ev.getValue();
+ String strValue = null;
+ EnumDisplay enumDisplay = null;
+ int index = -1;
+ strValue = ((VEnum) value).getValue();
+ enumDisplay = ((VEnum) value).getDisplay();
+ try {
+ index = ((VEnum) value).getIndex();
}
- catch (ArrayIndexOutOfBoundsException ex)
- {
- return ev.getIndex() + " = ?";
+ catch (ArrayIndexOutOfBoundsException e) {
+ index = -1;
}
+
+ if(enumDisplay!= null && strValue == null) {
+ List choices = enumDisplay.getChoices();
+ if(choices != null && index > -1 && index < choices.size()) {
+ strValue = choices.get(index);
+ }
+ }
+ strValue = strValue == null ? "?":strValue;
+ String strIndex = index >= 0 ? String.valueOf(index): "?";
+ return strIndex + " = " +strValue;
+ }
+ if(value instanceof VBoolean) {
+ //Add Boolean type to get true or false instead of VBoolean.toString()
+ //TODO Manage ONAM ZNAM for CA
+ return String.valueOf(((VBoolean)value).getValue());
}
+
if (value instanceof VString)
return ((VString) value).getValue();
if (value instanceof VByteArray && Settings.treat_byte_array_as_string)
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 6cccb7a0ca..6a333403e1 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
@@ -18,7 +18,7 @@
import java.util.stream.Stream;
import javafx.collections.transformation.FilteredList;
-import org.epics.vtype.VEnum;
+import org.epics.vtype.VBoolean;
import org.epics.vtype.VType;
import org.phoebus.applications.pvtable.PVTableApplication;
import org.phoebus.applications.pvtable.Settings;
@@ -338,21 +338,31 @@ public void startEdit()
setText(null);
final TableItemProxy proxy = getTableView().getItems().get(getIndex());
- final VType value = proxy.getItem().getValue();
- if (value instanceof VEnum)
+ String[] valueOptions = proxy.getItem().getValueOptions();
+ if (valueOptions != null && valueOptions.length > 0)
{
- // Use combo for Enum-valued data
- final VEnum enumerated = (VEnum) value;
final ComboBox combo = new ComboBox<>();
- combo.getItems().addAll(enumerated.getDisplay().getChoices());
- combo.getSelectionModel().select(enumerated.getIndex());
-
- combo.setOnAction(event ->
- {
- // Need to write String, using the enum index
- commitEdit(Integer.toString(combo.getSelectionModel().getSelectedIndex()));
- event.consume();
- });
+ combo.getItems().addAll(valueOptions);
+ int index = proxy.getItem().getIndex();
+ if(index >=0 && index < valueOptions.length) {
+ combo.getSelectionModel().select(index);
+ }
+ if(proxy.getItem().getValue() instanceof VBoolean) {
+ combo.setOnAction(event ->
+ {
+ // Need to write boolean, using the enum index
+ commitEdit(Boolean.toString(combo.getSelectionModel().getSelectedIndex() == 1));
+ event.consume();
+ });
+ }
+ else {
+ combo.setOnAction(event ->
+ {
+ // Need to write String, using the enum index
+ commitEdit(Integer.toString(combo.getSelectionModel().getSelectedIndex()));
+ event.consume();
+ });
+ }
combo.setOnKeyReleased(event ->
{
if (event.getCode() == KeyCode.ESCAPE)