diff --git a/com.archimatetool.editor/src/com/archimatetool/editor/preferences/IPreferenceConstants.java b/com.archimatetool.editor/src/com/archimatetool/editor/preferences/IPreferenceConstants.java index 461a64502..3ad8fb76d 100644 --- a/com.archimatetool.editor/src/com/archimatetool/editor/preferences/IPreferenceConstants.java +++ b/com.archimatetool.editor/src/com/archimatetool/editor/preferences/IPreferenceConstants.java @@ -175,4 +175,9 @@ public interface IPreferenceConstants { // Single column layout in Properties View String PROPERTIES_SINGLE_COLUMN = "propertiesSingleColumn"; + + // Search Filter + String SEARCHFILTER_SHOW_ALL_FOLDERS = "searchFilterShowAllFolders"; + String SEARCHFILTER_MATCH_CASE = "searchFilterMatchCase"; + String SEARCHFILTER_USE_REGEX = "searchFilterUseRegex"; } diff --git a/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/Messages.java b/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/Messages.java index 10fdb39d3..41c6b2204 100644 --- a/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/Messages.java +++ b/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/Messages.java @@ -31,6 +31,10 @@ public class Messages extends NLS { public static String SearchWidget_17; + public static String SearchWidget_18; + + public static String SearchWidget_19; + public static String SearchWidget_2; public static String SearchWidget_3; diff --git a/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/SearchFilter.java b/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/SearchFilter.java index 2834438fa..66fd3a9dc 100644 --- a/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/SearchFilter.java +++ b/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/SearchFilter.java @@ -7,6 +7,8 @@ import java.util.HashSet; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; @@ -41,15 +43,20 @@ public class SearchFilter extends ViewerFilter { private Set fConceptsFilter = new HashSet<>(); private Set fPropertiesFilter = new HashSet<>(); private Set fSpecializationsFilter = new HashSet<>(); - private boolean fFilterViews = false; - - private boolean fShowAllFolders = false; + + private boolean fFilterViews; + private boolean fShowAllFolders; + private boolean fMatchCase; + private boolean fUseRegex; + + private Matcher fRegexMatcher; SearchFilter() { } void setSearchText(String text) { fSearchText = text; + createRegexMatcher(); } void reset() { @@ -136,7 +143,7 @@ private boolean shouldShowObjectWithName(Object element) { // Normalise in case of multi-line text name = StringUtils.normaliseNewLineCharacters(name); - return name.toLowerCase().contains(fSearchText.toLowerCase()); + return matchesString(name); } return false; @@ -145,7 +152,7 @@ private boolean shouldShowObjectWithName(Object element) { private boolean shouldShowObjectWithDocumentation(Object element) { if(element instanceof IDocumentable documentable) { String text = StringUtils.safeString(documentable.getDocumentation()); - return text.toLowerCase().contains(fSearchText.toLowerCase()); + return matchesString(text); } return false; @@ -170,13 +177,47 @@ private boolean shouldShowProperty(Object element) { if(element instanceof IProperties properties) { for(IProperty property : properties.getProperties()) { if(fPropertiesFilter.contains(property.getKey())) { - return hasSearchText() ? property.getValue().toLowerCase().contains(fSearchText.toLowerCase()) : true; + return hasSearchText() ? matchesString(property.getValue()) : true; } } } return false; } + + private boolean matchesString(String str) { + if(str == null || str.length() == 0) { + return false; + } + + if(isUseRegex()) { + return matchesRegexString(str); + } + + if(isMatchCase()) { + return str.contains(fSearchText); + } + + return str.toLowerCase().contains(fSearchText.toLowerCase()); + } + + private boolean matchesRegexString(String searchString) { + return fRegexMatcher != null ? fRegexMatcher.reset(searchString).find() : false; + } + + private void createRegexMatcher() { + fRegexMatcher = null; + + if(isUseRegex() && hasSearchText()) { + try { + // Create a Matcher from the search text Pattern that can be re-used + Pattern pattern = Pattern.compile(fSearchText, isMatchCase() ? 0 : Pattern.CASE_INSENSITIVE); + fRegexMatcher = pattern.matcher(""); + } + catch(Exception ex) { + } + } + } public boolean isFiltering() { return isFilteringName() || isFilteringDocumentation() || isFilteringConcepts() || isFilteringPropertyKeys() || isFilteringSpecializations() || isFilteringViews(); @@ -206,7 +247,25 @@ private boolean hasSearchText() { return fSearchText.length() > 0; } - void setFilterOnName(boolean set) { + void setMatchCase(boolean set) { + fMatchCase = set; + createRegexMatcher(); + } + + boolean isMatchCase() { + return fMatchCase; + } + + void setUseRegex(boolean set) { + fUseRegex = set; + createRegexMatcher(); + } + + boolean isUseRegex() { + return fUseRegex; + } + + void setFilterOnName(boolean set) { fFilterName = set; } @@ -269,5 +328,4 @@ void setFilterViews(boolean set) { boolean isFilteringViews() { return fFilterViews; } - } \ No newline at end of file diff --git a/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/SearchWidget.java b/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/SearchWidget.java index a1f178c67..8a0ab5d58 100644 --- a/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/SearchWidget.java +++ b/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/SearchWidget.java @@ -331,13 +331,41 @@ public void run() { IAction actionFolders = new Action(Messages.SearchWidget_12, IAction.AS_CHECK_BOX) { @Override public void run() { + ArchiPlugin.PREFERENCES.setValue(IPreferenceConstants.SEARCHFILTER_SHOW_ALL_FOLDERS, isChecked()); fSearchFilter.setShowAllFolders(isChecked()); refreshTree(); } }; - actionFolders.setChecked(fSearchFilter.isShowAllFolders()); + actionFolders.setChecked(ArchiPlugin.PREFERENCES.getBoolean(IPreferenceConstants.SEARCHFILTER_SHOW_ALL_FOLDERS)); + fSearchFilter.setShowAllFolders(actionFolders.isChecked()); dropDownAction.add(actionFolders); + // Match Case + IAction actionMatchCase = new Action(Messages.SearchWidget_18, IAction.AS_CHECK_BOX) { + @Override + public void run() { + ArchiPlugin.PREFERENCES.setValue(IPreferenceConstants.SEARCHFILTER_MATCH_CASE, isChecked()); + fSearchFilter.setMatchCase(isChecked()); + refreshTree(); + } + }; + actionMatchCase.setChecked(ArchiPlugin.PREFERENCES.getBoolean(IPreferenceConstants.SEARCHFILTER_MATCH_CASE)); + fSearchFilter.setMatchCase(actionMatchCase.isChecked()); + dropDownAction.add(actionMatchCase); + + // Regex + IAction actionUseRegex = new Action(Messages.SearchWidget_19, IAction.AS_CHECK_BOX) { + @Override + public void run() { + ArchiPlugin.PREFERENCES.setValue(IPreferenceConstants.SEARCHFILTER_USE_REGEX, isChecked()); + fSearchFilter.setUseRegex(isChecked()); + refreshTree(); + } + }; + actionUseRegex.setChecked(ArchiPlugin.PREFERENCES.getBoolean(IPreferenceConstants.SEARCHFILTER_USE_REGEX)); + fSearchFilter.setUseRegex(actionUseRegex.isChecked()); + dropDownAction.add(actionUseRegex); + dropDownAction.add(new Separator()); // Reset diff --git a/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/messages.properties b/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/messages.properties index be5f3865b..110d2e9d5 100644 --- a/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/messages.properties +++ b/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/search/messages.properties @@ -8,6 +8,8 @@ SearchWidget_14=Other SearchWidget_15=Strategy SearchWidget_16=Specializations SearchWidget_17=Views +SearchWidget_18=Match Case +SearchWidget_19=Match Regular Expression SearchWidget_2=Documentation SearchWidget_3=Search in Documentation SearchWidget_4=Filter Options diff --git a/com.archimatetool.help/help/Images/model-tree-filter.png b/com.archimatetool.help/help/Images/model-tree-filter.png index e12e362a2..a4dad308e 100755 Binary files a/com.archimatetool.help/help/Images/model-tree-filter.png and b/com.archimatetool.help/help/Images/model-tree-filter.png differ diff --git a/com.archimatetool.help/help/Images/model-tree-searchbar2.png b/com.archimatetool.help/help/Images/model-tree-searchbar2.png index 5d051c1d5..3d0e7706a 100755 Binary files a/com.archimatetool.help/help/Images/model-tree-searchbar2.png and b/com.archimatetool.help/help/Images/model-tree-searchbar2.png differ diff --git a/com.archimatetool.help/help/Text/model_tree_search.html b/com.archimatetool.help/help/Text/model_tree_search.html index d8a973955..f26c4d1e7 100644 --- a/com.archimatetool.help/help/Text/model_tree_search.html +++ b/com.archimatetool.help/help/Text/model_tree_search.html @@ -62,6 +62,18 @@

Show All Folders


+

Match Case

+ +

Select this option to match case on the search text.

+ +
+ +

Match Regular Expression

+ +

Select this option to match using regular expressions. Note that the syntax is Java based.

+ +
+

Reset Filters

Selecting this menu item will clear all selections for Documentation, Properties, Specializations, Elements, Relations, and Views.