From 3896ccf6d0b6b97efde5298ee6e3b9ed98ed754f Mon Sep 17 00:00:00 2001 From: Mathis-Hu Date: Thu, 3 Aug 2023 15:31:44 -0400 Subject: [PATCH 1/5] Change formula autocomplete to match other autocomplete --- .../autocomplete/FormulaFunctionProposal.java | 146 ++++++++---------- .../autocomplete/FormulaProposalProvider.java | 33 +++- 2 files changed, 91 insertions(+), 88 deletions(-) diff --git a/core/framework/src/main/java/org/phoebus/framework/autocomplete/FormulaFunctionProposal.java b/core/framework/src/main/java/org/phoebus/framework/autocomplete/FormulaFunctionProposal.java index d3e0a3f555..c29ff049de 100644 --- a/core/framework/src/main/java/org/phoebus/framework/autocomplete/FormulaFunctionProposal.java +++ b/core/framework/src/main/java/org/phoebus/framework/autocomplete/FormulaFunctionProposal.java @@ -33,101 +33,87 @@ public String getDescription() return "=" + function.getSignature(); } + public String getSignature() + { + return function.getSignature(); + } + + public String getName() + { + return function.getName(); + } + + public String[] getArguments() + { + return function.getArguments().toArray(new String[0]); + } + @Override public List getMatch(final String text) { - // Does text contain the function name? - final int match = text.indexOf(function.getName()); + // Does text contain parameters? + String sub_text = text.substring(1); + final List split = SimProposal.splitNameAndParameters(sub_text); + + final List segs = new ArrayList<>(split.size()); + + // First compare text up to optional parameters + final String noparm_text = split.get(0); + final String name = getName(); + final int match = name.toLowerCase().indexOf(noparm_text.toLowerCase()); + segs.add(MatchSegment.normal("=")); + // Text does not match the proposal?? if (match < 0) - return List.of(MatchSegment.normal(getDescription())); + segs.add(MatchSegment.normal(name)); + else + { + // Start of proposal .. + if (match > 0) + segs.add(MatchSegment.normal(name.substring(0, match))); + + // .. matching text .. + segs.add(MatchSegment.match(getSignature().substring(match, match + noparm_text.length()))); - // Copy text leading up to function name - final List segs = new ArrayList<>(); - if (match > 0) - segs.add(MatchSegment.normal(text.substring(0, match))); + // .. rest of proposal + final int rest = match + noparm_text.length(); + if (name.length() > rest) + segs.add(MatchSegment.normal(name.substring(rest))); + } - // Match function name - segs.add(MatchSegment.match(function.getName())); + String[] arguments = getArguments(); - // Is there a "(" to start arguments? - final int len = text.length(); - int pos = match + function.getName().length(); - if (pos < len && text.charAt(pos) == '(') + final int common = Math.min(split.size()-1, arguments.length); + int parm; + for (parm = 0; parm < common; ++parm) { - if (function.isVarArgs()) - { - int end = SimProposal.findClosingParenthesis(text, pos); - if (end < len) - { // Located end, match complete arguments - segs.add(MatchSegment.match(text.substring(pos, end+1))); - pos = end+1; - } - else - { // Match opening '(' and args, suggest ')' - segs.add(MatchSegment.match(text.substring(pos, end))); - segs.add(MatchSegment.comment(")")); - pos = end; - } - } + final String another = parm < arguments.length-1 ? "," : ")"; + if (parm == 0) + segs.add(MatchSegment.match("(" + split.get(parm+1) + another, + "(" + arguments[parm] + another)); else - { - // Match provided arguments with arg. name as description - segs.add(MatchSegment.match("(")); - ++pos; - int end = SimProposal.nextSep(text, pos); - for (int i=0; i 0) - segs.add(MatchSegment.normal(",")); - if (pos > 0) - { - if (end > pos) - { - // Have text for this argument. - segs.add(MatchSegment.match(text.substring(pos, end), - function.getArguments().get(i))); - if (text.charAt(end) == ')') - { - segs.add(MatchSegment.match(")")); - pos = end + 1; - break; - } - else - { - pos = end + 1; - end = SimProposal.nextSep(text, pos); - } - } - else - { - segs.add(MatchSegment.comment(text.substring(pos), - function.getArguments().get(i))); - pos = end = -1; - } - } - else - segs.add(MatchSegment.comment(function.getArguments().get(i))); - } - } + segs.add(MatchSegment.match(split.get(parm+1) + another, + arguments[parm] + another)); } - else + + // Add remaining parameters as COMMENT + final StringBuilder buf = new StringBuilder(); + if (parm < arguments.length) { - // Show argument info as comment - for (int i=0; i= 0 && pos < len) - segs.add(MatchSegment.normal(text.substring(pos))); + if (buf.length() > 0) + segs.add(MatchSegment.comment(buf.toString())); return segs; } } + + diff --git a/core/framework/src/main/java/org/phoebus/framework/autocomplete/FormulaProposalProvider.java b/core/framework/src/main/java/org/phoebus/framework/autocomplete/FormulaProposalProvider.java index c2ccb49bbb..a0d6a0965d 100644 --- a/core/framework/src/main/java/org/phoebus/framework/autocomplete/FormulaProposalProvider.java +++ b/core/framework/src/main/java/org/phoebus/framework/autocomplete/FormulaProposalProvider.java @@ -51,16 +51,33 @@ public List lookup(final String text) if (! text.startsWith("=")) return generic; - // User is typing a formula - // Find all functions where the text results in a match + // Does text contain parameters? + final String sub_text = text.substring(1); + final List split = SimProposal.splitNameAndParameters(sub_text); + final String noparm_text = split.get(0); + final int given = SimProposal.hasOpeningBacket(sub_text) + ? split.size() - 1 + : -1; + final boolean complete_args = SimProposal.hasClosingBacket(sub_text); + + // Search 'all' proposals for match final List result = new ArrayList<>(); - for (Proposal p : functions) - for (MatchSegment seg : p.getMatch(text)) - if (seg.getType() == MatchSegment.Type.MATCH) - { - result.add(p); - break; + // First compare text up to optional parameters + for (FormulaFunctionProposal proposal : functions) + if (proposal.getName().toLowerCase().contains(noparm_text.toLowerCase())) { + // If text contains arguments, check them + if (given >= 0) { + final int required = proposal.getArguments().length; + // Skip if text contains more arguments than proposal allows + if (given > required) + continue; + // Skip if text contains complete arguments "(...)" but wrong number + if (given != required && complete_args) + continue; + // Text has fewer arguments, or not ending in "..)" } + result.add(proposal); + } // Show functions with a match if (result.size() > 0) From cd8664e9b204933a93c433ab388aa6e730f9c97c Mon Sep 17 00:00:00 2001 From: Mathis-Hu Date: Mon, 7 Aug 2023 12:29:38 -0400 Subject: [PATCH 2/5] Add property to set a unique color for groupWidget title --- .../builder/model/widgets/GroupWidget.java | 123 +++++++++++------- .../javafx/widgets/GroupRepresentation.java | 40 ++++-- 2 files changed, 101 insertions(+), 62 deletions(-) diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/GroupWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/GroupWidget.java index 399c35b96b..ecad65c358 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/GroupWidget.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/GroupWidget.java @@ -10,6 +10,7 @@ import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propBackgroundColor; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propFont; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propForegroundColor; +import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propLineColor; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propTransparent; import static org.csstudio.display.builder.model.properties.InsetsWidgetProperty.runtimePropExtendedInsets; @@ -56,20 +57,25 @@ @SuppressWarnings("nls") public class GroupWidget extends MacroWidget { + /** Group Widget version */ + public static final Version GROUP_WIDGET_VERSION = new Version(3, 0, 0); + + private boolean old_colors = false; + /** Widget descriptor */ public static final WidgetDescriptor WIDGET_DESCRIPTOR = - new WidgetDescriptor("group", WidgetCategory.STRUCTURE, - Messages.GroupWidget_Name, - "/icons/group.png", - Messages.GroupWidget_Description, - Arrays.asList("org.csstudio.opibuilder.widgets.groupingContainer")) - { - @Override - public Widget createWidget() - { - return new GroupWidget(); - } - }; + new WidgetDescriptor("group", WidgetCategory.STRUCTURE, + Messages.GroupWidget_Name, + "/icons/group.png", + Messages.GroupWidget_Description, + Arrays.asList("org.csstudio.opibuilder.widgets.groupingContainer")) + { + @Override + public Widget createWidget() + { + return new GroupWidget(); + } + }; /** Group widget style */ public enum Style @@ -99,16 +105,16 @@ public String toString() /** 'style' property */ static final WidgetPropertyDescriptor