Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 209727 Details for
Bug 360894
[patch] Extensions tree viewer should also be filtered by leaf item's attributes
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Git-Patch against 3.8 M4 [master], please add icons from the next attachement
org.eclipse.pde.ui_extensionstree_git.patch (text/plain), 57.53 KB, created by
Sascha Becher
on 2012-01-19 04:16:38 EST
(
hide
)
Description:
Git-Patch against 3.8 M4 [master], please add icons from the next attachement
Filename:
MIME Type:
Creator:
Sascha Becher
Created:
2012-01-19 04:16:38 EST
Size:
57.53 KB
patch
obsolete
>From 0969d0963dad4d90c813c8b5699e20ec23e9c081 Wed, 18 Jan 2012 23:20:35 +0100 >From: zour <s.becher@qualitype.de> >Date: Wed, 18 Jan 2012 23:18:20 +0100 >Subject: [PATCH] Bug 360894 Extensions tree viewer should also be filtered by leaf item's attributes > >Actions: >- "Filter related" fills the filter text with the values of a list of > attributes when found on the selected tree node. These attributes > for relation are: label, id, class, commandId, value, pattern, > locationURI, defaultHandler > The action is presented by a toolbar icon, in the context menu of the > tree and by pressing Ctrl+F (key binding of "Find"). > Multi-Selection is supported but can be costly. The action is only > enabled when at least one item of the selection is supported by > the attributes for relation. >- "Search Extension Element": starts a workspace-wide search with > current filter set to the tree. Displays search results in Search > View with a distinct icon. Opening a search result reveals the > extensions page with the filter already being applied to the tree. > One might find this useful i.e. for finding implementing handlers or > menu contributions of remote command definitions and alike. The > action is only enabled when filtering occurs. >- "Search Related" (context menu only) combines Filter Related with > Search Extension Elements by performing a workspace wide search for > the attributes supported by Filter Related found on the currently > selected tree node(s). >- "Toggle Expand State" expands and collapses selected tree node(s) for > convenient reading of large expressions or for hiding only parts > of the tree. >All actions have icons designed to reveal their purpose. > >Other Features: >- Typing into the filter doesn't get blocked any more by extensive > search operations. Running search operations are being canceled when > the filter text changes. >- Sensible tree expand behaviour: a filtered tree now contains also all > children of the matching elements in collapsed state. >- LabelProvider of the tree displays these extension elements with the > following attributes: > (test): property, (handler): class, > (activityPatternBinding): activityId, (propertyTester): class > The label provider has a list of attributes to visit each tree node > with in order to obtain the label text. That list has been completed > to display even more elements with their most distinctive attribute: > label, name, class, id, commandId, property, activityId, attribute, > value >- Any value found for the attribute "class" is displayed without the > package to minimize label length. >- Attribute values with the notation "id1?after=id2" found for > "Filter Related" are being split into id1/id2 in order to find the > location of item with id2, thus learning where it appears in the > UI or elsewhere. > >diff --git a/ui/org.eclipse.pde.ui/icons/dlcl16/filter_related.gif b/ui/org.eclipse.pde.ui/icons/dlcl16/filter_related.gif >new file mode 100644 >index 0000000..f07bf77 >--- /dev/null >+++ b/ui/org.eclipse.pde.ui/icons/dlcl16/filter_related.gif >Binary files differ >diff --git a/ui/org.eclipse.pde.ui/icons/dlcl16/search_extensions.gif b/ui/org.eclipse.pde.ui/icons/dlcl16/search_extensions.gif >new file mode 100644 >index 0000000..8f7cbab >--- /dev/null >+++ b/ui/org.eclipse.pde.ui/icons/dlcl16/search_extensions.gif >Binary files differ >diff --git a/ui/org.eclipse.pde.ui/icons/dlcl16/toggle_expand_state.gif b/ui/org.eclipse.pde.ui/icons/dlcl16/toggle_expand_state.gif >new file mode 100644 >index 0000000..e868b95 >--- /dev/null >+++ b/ui/org.eclipse.pde.ui/icons/dlcl16/toggle_expand_state.gif >Binary files differ >diff --git a/ui/org.eclipse.pde.ui/icons/elcl16/filter_related.gif b/ui/org.eclipse.pde.ui/icons/elcl16/filter_related.gif >new file mode 100644 >index 0000000..b983f27 >--- /dev/null >+++ b/ui/org.eclipse.pde.ui/icons/elcl16/filter_related.gif >Binary files differ >diff --git a/ui/org.eclipse.pde.ui/icons/elcl16/search_extensions.gif b/ui/org.eclipse.pde.ui/icons/elcl16/search_extensions.gif >new file mode 100644 >index 0000000..6d1094e >--- /dev/null >+++ b/ui/org.eclipse.pde.ui/icons/elcl16/search_extensions.gif >Binary files differ >diff --git a/ui/org.eclipse.pde.ui/icons/elcl16/toggle_expand_state.gif b/ui/org.eclipse.pde.ui/icons/elcl16/toggle_expand_state.gif >new file mode 100644 >index 0000000..f61d0b9 >--- /dev/null >+++ b/ui/org.eclipse.pde.ui/icons/elcl16/toggle_expand_state.gif >Binary files differ >diff --git a/ui/org.eclipse.pde.ui/icons/obj16/esearch_obj.gif b/ui/org.eclipse.pde.ui/icons/obj16/esearch_obj.gif >new file mode 100644 >index 0000000..32860cb >--- /dev/null >+++ b/ui/org.eclipse.pde.ui/icons/obj16/esearch_obj.gif >Binary files differ >diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEPluginImages.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEPluginImages.java >index 88c9ab2..c22b465 100644 >--- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEPluginImages.java >+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEPluginImages.java >@@ -153,6 +153,7 @@ > public static final ImageDescriptor DESC_INFO_ST_OBJ = create(PATH_OBJ, "info_st_obj.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_CATEGORY_OBJ = create(PATH_OBJ, "category_obj.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_PSEARCH_OBJ = create(PATH_OBJ, "psearch_obj.gif"); //$NON-NLS-1$ >+ public static final ImageDescriptor DESC_ESEARCH_OBJ = create(PATH_OBJ, "esearch_obj.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_SITE_OBJ = create(PATH_OBJ, "site_obj.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_JUNIT_MAIN_TAB = create(PATH_OBJ, "test.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_OUTPUT_FOLDER_OBJ = create(PATH_OBJ, "output_folder_attrib.gif"); //$NON-NLS-1$ >@@ -232,6 +233,7 @@ > public static final ImageDescriptor DESC_VERTICAL = create(PATH_LCL, "th_vertical.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_COLLAPSE_ALL = create(PATH_LCL, "collapseall.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_COLLAPSE_ALL_MINI = create(PATH_LCL, "collapse_all_mini.gif"); //$NON-NLS-1$ >+ public static final ImageDescriptor DESC_TOGGLE_EXPAND_STATE = create(PATH_LCL, "toggle_expand_state.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_HELP = create(PATH_LCL, "help.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_LINK_WITH_EDITOR = create(PATH_LCL, "synced.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_CALLEES = create(PATH_LCL, "ch_callees.gif"); //$NON-NLS-1$ >@@ -242,6 +244,8 @@ > public static final ImageDescriptor DESC_HISTORY_LIST = create(PATH_LCL, "history_list.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_CLEAR = create(PATH_LCL, "clear.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_FILTER = create(PATH_LCL, "filter_ps.gif"); //$NON-NLS-1$ >+ public static final ImageDescriptor DESC_FILTER_RELATED = create(PATH_LCL, "filter_related.gif"); //$NON-NLS-1$ >+ public static final ImageDescriptor DESC_SEARCH_EXTENSIONS = create(PATH_LCL, "search_extensions.gif"); //$NON-NLS-1$ > > public static final ImageDescriptor DESC_ADD_ATT_DISABLED = create(PATH_LCL_DISABLED, "add_att.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_ALPHAB_SORT_CO_DISABLED = create(PATH_LCL_DISABLED, "alphab_sort_co.gif"); //$NON-NLS-1$ >@@ -255,6 +259,7 @@ > public static final ImageDescriptor DESC_HORIZONTAL_DISABLED = create(PATH_LCL_DISABLED, "th_horizontal.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_VERTICAL_DISABLED = create(PATH_LCL_DISABLED, "th_vertical.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_COLLAPSE_ALL_DISABLED = create(PATH_LCL_DISABLED, "collapseall.gif"); //$NON-NLS-1$ >+ public static final ImageDescriptor DESC_TOGGLE_EXPAND_STATE_DISABLED = create(PATH_LCL_DISABLED, "toggle_expand_state.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_LINK_WITH_EDITOR_DISABLED = create(PATH_LCL_DISABLED, "synced.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_CALLEES_DISABLED = create(PATH_LCL_DISABLED, "ch_callees.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_CALLERS_DISABLED = create(PATH_LCL_DISABLED, "ch_callers.gif"); //$NON-NLS-1$ >@@ -264,6 +269,8 @@ > public static final ImageDescriptor DESC_HISTORY_LIST_DISABLED = create(PATH_LCL_DISABLED, "history_list.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_DCLEAR = create(PATH_LCL_DISABLED, "clear.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_FILTER_DISABLED = create(PATH_LCL_DISABLED, "filter_ps.gif"); //$NON-NLS-1$ >+ public static final ImageDescriptor DESC_FILTER_RELATED_DISABLED = create(PATH_LCL_DISABLED, "filter_related.gif"); //$NON-NLS-1$ >+ public static final ImageDescriptor DESC_SEARCH_EXTENSIONS_DISABLED = create(PATH_LCL_DISABLED, "search_extensions.gif"); //$NON-NLS-1$ > > public static final ImageDescriptor DESC_RUN_EXC = create(PATH_OBJ, "run_exc.gif"); //$NON-NLS-1$ > public static final ImageDescriptor DESC_DEBUG_EXC = create(PATH_OBJ, "debug_exc.gif"); //$NON-NLS-1$ >diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java >index cfae1ea7..5593169 100644 >--- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java >+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java >@@ -54,6 +54,10 @@ > > public static String DependencyPropertiesDialog_exportGroupText; > >+ public static String ExtensionsPage_toggleExpandState; >+ >+ public static String ExtensionsPage_searchWithExtensionsFilter; >+ > public static String ExternalizeStringsOperation_editNames_addComment; > > public static String ExternalizeStringsOperation_editNames_insertProperty; >@@ -1425,6 +1429,8 @@ > public static String EditorActions_revert; > public static String Actions_open_label; > public static String Actions_delete_label; >+ public static String Actions_filter_relatedPluginElements; >+ public static String Actions_search_relatedPluginElements; > public static String Actions_synchronizeVersions_label; > > public static String Menus_new_label; >diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/actions/FilterRelatedExtensionsAction.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/actions/FilterRelatedExtensionsAction.java >new file mode 100644 >index 0000000..0d29745 >--- /dev/null >+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/actions/FilterRelatedExtensionsAction.java >@@ -0,0 +1,135 @@ >+/******************************************************************************* >+ * Copyright (c) 2011, 2012 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Sascha Becher <s.becher@qualitype.de> - bug 360894 >+ *******************************************************************************/ >+package org.eclipse.pde.internal.ui.editor.actions; >+ >+import java.util.*; >+import org.eclipse.jface.action.Action; >+import org.eclipse.jface.viewers.IStructuredSelection; >+import org.eclipse.jface.viewers.TreeViewer; >+import org.eclipse.pde.core.plugin.IPluginAttribute; >+import org.eclipse.pde.core.plugin.IPluginElement; >+import org.eclipse.pde.internal.ui.PDEPluginImages; >+import org.eclipse.pde.internal.ui.PDEUIMessages; >+import org.eclipse.pde.internal.ui.editor.plugin.FormFilteredTree; >+import org.eclipse.pde.internal.ui.search.ExtensionsPatternFilter; >+import org.eclipse.swt.widgets.Text; >+import org.eclipse.ui.PlatformUI; >+import org.eclipse.ui.actions.ActionFactory; >+import org.eclipse.ui.keys.IBindingService; >+ >+/** >+ * Serves as Filter Related Action in context menu of the extensions tree and toolbar icon on the same page >+ * >+ * @author Sascha Becher >+ */ >+public class FilterRelatedExtensionsAction extends Action { >+ >+ protected TreeViewer fExtensionTree; >+ protected FormFilteredTree fFilteredTree; >+ >+ public FilterRelatedExtensionsAction(TreeViewer treeViewer, FormFilteredTree filteredTree) { >+ String filterBinding = ((IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class)).getBestActiveBindingFormattedFor(ActionFactory.FIND.getCommandId()); >+ setImageDescriptor(PDEPluginImages.DESC_FILTER_RELATED); >+ setDisabledImageDescriptor(PDEPluginImages.DESC_FILTER_RELATED_DISABLED); >+ setText(PDEUIMessages.Actions_filter_relatedPluginElements + ((filterBinding != null) ? "\t" + filterBinding : "")); //$NON-NLS-1$ //$NON-NLS-2$ >+ >+ this.fExtensionTree = treeViewer; >+ this.fFilteredTree = filteredTree; >+ } >+ >+ public void run() { >+ String filterPattern = getFilterRelatedPattern((IStructuredSelection) fExtensionTree.getSelection()); >+ Text filterControl = fFilteredTree.getFilterControl(); >+ if (filterControl != null && filterPattern.length() > 0) { >+ filterControl.setText(filterPattern); >+ } >+ } >+ >+ /** >+ * Obtains common attributes from selected plugin element to filter tree for; >+ * attribute values are concatenated with a slash and set as filter text >+ * >+ * @param selection selected items to filter for related plugin elements >+ */ >+ public static String getFilterRelatedPattern(IStructuredSelection selection) { >+ Iterator it = selection.iterator(); >+ Set filterPatterns = new HashSet(); >+ while (it.hasNext()) { >+ Object treeElement = it.next(); >+ if (treeElement instanceof IPluginElement) { >+ IPluginElement pluginElement = (IPluginElement) treeElement; >+ for (int i = 0; i < ExtensionsPatternFilter.RELATED_ATTRIBUTES.length; i++) { >+ String property = ExtensionsPatternFilter.RELATED_ATTRIBUTES[i]; >+ IPluginAttribute attribute = pluginElement.getAttribute(property); >+ if (attribute != null && attribute.getValue() != null && attribute.getValue().length() > 0) { >+ String value = attribute.getValue(); >+ if (!value.startsWith("%")) { //$NON-NLS-1$ >+ int delimiterPosition = value.indexOf('?'); // split before '?' and right after last '=' >+ if (delimiterPosition == -1) { >+ filterPatterns.add(value); >+ } else { >+ filterPatterns.add(value.substring(0, delimiterPosition)); >+ int position = value.lastIndexOf('='); >+ if (position != -1) { >+ filterPatterns.add(value.substring(position + 1, value.length())); >+ } >+ } >+ } else { >+ String resourceValue = pluginElement.getResourceString(value); >+ if ((resourceValue != null && resourceValue.length() > 0)) { >+ filterPatterns.add(resourceValue); >+ } >+ } >+ } >+ } >+ } >+ } >+ StringBuffer patternBuffer = new StringBuffer(); >+ for (Iterator iterator = filterPatterns.iterator(); iterator.hasNext();) { >+ Object pattern = iterator.next(); >+ if (pattern != null) { >+ patternBuffer.append(pattern); >+ patternBuffer.append('/'); >+ } >+ } >+ String filterPattern = patternBuffer.toString(); >+ if (filterPattern.endsWith("/")) { //$NON-NLS-1$ >+ filterPattern = filterPattern.substring(0, filterPattern.length() - 1); >+ } >+ return filterPattern; >+ } >+ >+ public static boolean isFilterRelatedEnabled(IStructuredSelection structuredSelection) { >+ boolean createFilterRelatedAction = false; >+ if (structuredSelection != null && !structuredSelection.isEmpty()) { >+ Iterator it = structuredSelection.iterator(); >+ while (it.hasNext()) { >+ Object treeElement = it.next(); >+ if (treeElement instanceof IPluginElement) { >+ createFilterRelatedAction |= isFilterRelatedEnabled((IPluginElement) treeElement); >+ } >+ } >+ } >+ return createFilterRelatedAction; >+ } >+ >+ private static boolean isFilterRelatedEnabled(IPluginElement pluginElement) { >+ for (int i = 0; i < ExtensionsPatternFilter.RELATED_ATTRIBUTES.length; i++) { >+ String property = ExtensionsPatternFilter.RELATED_ATTRIBUTES[i]; >+ IPluginAttribute attribute = pluginElement.getAttribute(property); >+ if (attribute != null) { >+ return true; >+ } >+ } >+ return false; >+ } >+ >+} >\ No newline at end of file >diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/actions/SearchExtensionsAction.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/actions/SearchExtensionsAction.java >new file mode 100644 >index 0000000..cd70944 >--- /dev/null >+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/actions/SearchExtensionsAction.java >@@ -0,0 +1,74 @@ >+/******************************************************************************* >+ * Copyright (c) 2011, 2012 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Sascha Becher <s.becher@qualitype.de> - bug 360894 >+ *******************************************************************************/ >+package org.eclipse.pde.internal.ui.editor.actions; >+ >+import org.eclipse.jface.action.Action; >+import org.eclipse.jface.viewers.IStructuredSelection; >+import org.eclipse.pde.internal.core.search.PluginSearchInput; >+import org.eclipse.pde.internal.core.search.PluginSearchScope; >+import org.eclipse.pde.internal.ui.PDEPluginImages; >+import org.eclipse.pde.internal.ui.editor.plugin.FormFilteredTree; >+import org.eclipse.pde.internal.ui.search.FindExtensionsByAttributeQuery; >+import org.eclipse.search.ui.ISearchQuery; >+import org.eclipse.search.ui.NewSearchUI; >+ >+/** >+ * Search in workspace plugins for occurences of either the current filter text or filter related attributes >+ * using the ExtensionsPatternFilter search behaviour. >+ * >+ * @author Sascha Becher >+ */ >+public class SearchExtensionsAction extends Action { >+ >+ protected IStructuredSelection selection; >+ protected FormFilteredTree fFilteredTree; >+ >+ private String fFilterRelatedText; >+ >+ public SearchExtensionsAction(FormFilteredTree filteredTree, String actionText) { >+ this(null, null, actionText); >+ this.fFilteredTree = filteredTree; >+ } >+ >+ public SearchExtensionsAction(IStructuredSelection selection, String filterRelatedText, String actionText) { >+ setImageDescriptor(PDEPluginImages.DESC_SEARCH_EXTENSIONS); >+ setDisabledImageDescriptor(PDEPluginImages.DESC_SEARCH_EXTENSIONS_DISABLED); >+ setText(actionText); >+ this.selection = selection; >+ this.fFilterRelatedText = filterRelatedText; >+ } >+ >+ public void run() { >+ NewSearchUI.activateSearchResultView(); >+ NewSearchUI.runQueryInBackground(createSearchQuery()); >+ } >+ >+ protected ISearchQuery createSearchQuery() { >+ PluginSearchInput input = new PluginSearchInput(); >+ input.setSearchElement(PluginSearchInput.ELEMENT_PLUGIN); >+ input.setSearchLimit(PluginSearchInput.LIMIT_ALL); >+ input.setSearchString(getFilterText()); >+ input.setSearchScope(new PluginSearchScope(PluginSearchScope.SCOPE_WORKSPACE, PluginSearchScope.EXTERNAL_SCOPE_ALL, null)); >+ input.setCaseSensitive(false); >+ return new FindExtensionsByAttributeQuery(selection, input); >+ } >+ >+ private String getFilterText() { >+ if (fFilterRelatedText != null) { >+ return fFilterRelatedText; >+ } >+ if (fFilteredTree != null) { >+ return fFilteredTree.getFilterControl().getText(); >+ } >+ return new String(); >+ } >+ >+} >\ No newline at end of file >diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/actions/ToggleExpandStateAction.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/actions/ToggleExpandStateAction.java >new file mode 100644 >index 0000000..beb46ce >--- /dev/null >+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/actions/ToggleExpandStateAction.java >@@ -0,0 +1,119 @@ >+/******************************************************************************* >+ * Copyright (c) 2011, 2012 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Sascha Becher <s.becher@qualitype.de> - bug 360894 >+ *******************************************************************************/ >+package org.eclipse.pde.internal.ui.editor.actions; >+ >+import java.util.*; >+import org.eclipse.jface.action.Action; >+import org.eclipse.jface.viewers.*; >+import org.eclipse.pde.internal.core.text.plugin.PluginParentNode; >+import org.eclipse.pde.internal.ui.PDEPluginImages; >+import org.eclipse.pde.internal.ui.PDEUIMessages; >+import org.eclipse.pde.internal.ui.editor.plugin.FormFilteredTree; >+ >+/** >+ * Expands and collapses selected tree nodes in the extension elements tree viewer upon their expand state. >+ * >+ * @author Sascha Becher >+ */ >+public class ToggleExpandStateAction extends Action { >+ >+ public static int NEEDS_EXPAND = 1; >+ public static int NEEDS_COLLAPSE = 2; >+ >+ protected TreeViewer fExtensionTree; >+ protected FormFilteredTree fFilteredTree; >+ >+ /** >+ * @param treeViewer >+ */ >+ public ToggleExpandStateAction(FormFilteredTree filteredTree, TreeViewer treeViewer) { >+ setImageDescriptor(PDEPluginImages.DESC_TOGGLE_EXPAND_STATE); >+ setDisabledImageDescriptor(PDEPluginImages.DESC_TOGGLE_EXPAND_STATE_DISABLED); >+ setText(PDEUIMessages.ExtensionsPage_toggleExpandState); >+ fExtensionTree = treeViewer; >+ fFilteredTree = filteredTree; >+ } >+ >+ public void run() { >+ StructuredSelection selection = (StructuredSelection) fExtensionTree.getSelection(); >+ if (!selection.isEmpty()) { >+ try { >+ List children = traverseChildren(selection.toList()); >+ fFilteredTree.setRedraw(false); >+ int state = getStateChangeRequired(selection); >+ if (state == NEEDS_EXPAND) { // expand sub tree >+ for (Iterator iterator = children.iterator(); iterator.hasNext();) { >+ fExtensionTree.expandToLevel(iterator.next(), 0); >+ } >+ if (selection != null && !(selection.isEmpty())) { >+ fExtensionTree.setSelection(selection, false); >+ } >+ } else { // collapse sub tree >+ for (Iterator iterator = selection.iterator(); iterator.hasNext();) { >+ fExtensionTree.setExpandedState(iterator.next(), false); >+ } >+ } >+ } finally { >+ fFilteredTree.setRedraw(true); >+ fExtensionTree.refresh(); >+ } >+ } >+ super.run(); >+ } >+ >+ public int getStateChangeRequired(StructuredSelection selection) { >+ for (Iterator iterator = selection.iterator(); iterator.hasNext();) { >+ Object node = iterator.next(); >+ if (!fExtensionTree.getExpandedState(node)) { >+ return NEEDS_EXPAND; >+ } >+ } >+ return NEEDS_COLLAPSE; >+ } >+ >+ protected List traverseChildren(List children) { >+ List foundChildren = new ArrayList(); >+ foundChildren.addAll(0, children); >+ for (Iterator iterator = children.iterator(); iterator.hasNext();) { >+ Object child = iterator.next(); >+ if (child instanceof PluginParentNode) { >+ PluginParentNode node = (PluginParentNode) child; >+ if (node.getChildCount() > 0) { >+ List asList = Arrays.asList(node.getChildren()); >+ List grandChildren = traverseChildren(asList); >+ foundChildren.addAll(0, grandChildren); >+ } >+ } >+ } >+ return foundChildren; >+ } >+ >+ public static boolean isExpandable(IStructuredSelection selection) { >+ boolean isExpandable = false; >+ if (selection != null) { >+ if (!selection.isEmpty()) { >+ // enable expand action when selected leafs are expandable >+ for (Iterator iterator = selection.iterator(); iterator.hasNext();) { >+ Object element = iterator.next(); >+ if (element instanceof PluginParentNode) { >+ PluginParentNode node = (PluginParentNode) element; >+ if (node.getChildCount() > 0) { >+ isExpandable = true; >+ break; >+ } >+ } >+ } >+ } >+ } >+ return isExpandable; >+ } >+ >+} >\ No newline at end of file >diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/plugin/ExtensionsSection.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/plugin/ExtensionsSection.java >index 2c9b627..b33255b 100644 >--- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/plugin/ExtensionsSection.java >+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/plugin/ExtensionsSection.java >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2011 IBM Corporation and others. >+ * Copyright (c) 2000, 2012 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -8,12 +8,14 @@ > * Contributors: > * IBM Corporation - initial API and implementation > * Peter Friese <peter.friese@gentleware.com> - bug 194529, bug 196867 >+ * Sascha Becher <s.becher@qualitype.com> - bug 360894 > *******************************************************************************/ > package org.eclipse.pde.internal.ui.editor.plugin; > > import java.util.*; > import org.eclipse.core.resources.IProject; > import org.eclipse.core.runtime.*; >+import org.eclipse.core.runtime.jobs.*; > import org.eclipse.jface.action.*; > import org.eclipse.jface.dialogs.IMessageProvider; > import org.eclipse.jface.util.IPropertyChangeListener; >@@ -32,11 +34,11 @@ > import org.eclipse.pde.internal.core.text.plugin.PluginBaseNode; > import org.eclipse.pde.internal.ui.*; > import org.eclipse.pde.internal.ui.editor.*; >-import org.eclipse.pde.internal.ui.editor.actions.CollapseAction; >-import org.eclipse.pde.internal.ui.editor.actions.SortAction; >+import org.eclipse.pde.internal.ui.editor.actions.*; > import org.eclipse.pde.internal.ui.editor.contentassist.XMLElementProposalComputer; > import org.eclipse.pde.internal.ui.elements.DefaultContentProvider; > import org.eclipse.pde.internal.ui.parts.TreePart; >+import org.eclipse.pde.internal.ui.search.ExtensionsPatternFilter; > import org.eclipse.pde.internal.ui.search.PluginSearchActionGroup; > import org.eclipse.pde.internal.ui.util.SWTUtil; > import org.eclipse.pde.internal.ui.wizards.extension.ExtensionEditorWizard; >@@ -51,9 +53,9 @@ > import org.eclipse.swt.widgets.*; > import org.eclipse.ui.actions.ActionContext; > import org.eclipse.ui.actions.ActionFactory; >-import org.eclipse.ui.dialogs.PatternFilter; > import org.eclipse.ui.forms.widgets.FormToolkit; > import org.eclipse.ui.forms.widgets.Section; >+import org.eclipse.ui.progress.WorkbenchJob; > > public class ExtensionsSection extends TreeSection implements IModelChangedListener, IPropertyChangeListener { > private static final int BUTTON_MOVE_DOWN = 4; >@@ -68,14 +70,17 @@ > private Hashtable fEditorWizards; > private SortAction fSortAction; > private CollapseAction fCollapseAction; >+ private ToggleExpandStateAction fExpandAction; >+ private FilterRelatedExtensionsAction fFilterRelatedAction; >+ private SearchExtensionsAction fSearchAction; > > private static final int BUTTON_ADD = 0; > >- private static final String[] COMMON_LABEL_PROPERTIES = {"label", //$NON-NLS-1$ >- "name", //$NON-NLS-1$ >- "id", //$NON-NLS-1$ >- "commandId", //$NON-NLS-1$ >- "activityId"}; //$NON-NLS-1$ >+ // TODO common label properties should be configured in preferences >+ public static final String[] COMMON_LABEL_ATTRIBUTES = {"label", //$NON-NLS-1$ >+ "name", "class", "id", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ >+ "commandId", "property", "activityId", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ >+ "attribute", "value"}; //$NON-NLS-1$ //$NON-NLS-2$ > > private static final String[] VALID_IMAGE_TYPES = {"png", "bmp", "ico", "gif", "jpg", "tiff"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ > >@@ -232,6 +237,27 @@ > updateButtons(ssel.size() != 1 ? null : ssel); > } > }); >+ >+ // required for enabling constant typing in the filter control >+ filterText.addKeyListener(new KeyAdapter() { >+ public void keyPressed(KeyEvent e) { >+ if (fFilteredTree.getFilterControl().getText().length() > 0) { >+ Job jobs[] = Job.getJobManager().find(null); >+ try { >+ Job.getJobManager().suspend(); >+ for (int i = 0; i < jobs.length; i++) { >+ Job job = jobs[i]; >+ if (job != null && "Refresh Filter".equals(job.getName())) { //$NON-NLS-1$ >+ // remove prior filtering refresh jobs in order to avoid blocked filter control >+ job.cancel(); >+ } >+ } >+ } finally { >+ Job.getJobManager().resume(); >+ } >+ } >+ } >+ }); > } > } > >@@ -252,9 +278,21 @@ > } > } > }); >+ // Add action to filter tree with some of the selection's attributes >+ fFilterRelatedAction = new FilterRelatedExtensionsAction(fExtensionTree, fFilteredTree); >+ toolBarManager.add(fFilterRelatedAction); >+ // Add action to search all workspace plugins with current filtering applied to the tree viewer >+ fSearchAction = new SearchExtensionsAction(fFilteredTree, PDEUIMessages.ExtensionsPage_searchWithExtensionsFilter); >+ toolBarManager.add(fSearchAction); >+ // Add separator >+ Separator separator = new Separator(); >+ toolBarManager.add(separator); > // Add sort action to the tool bar > fSortAction = new SortAction(fExtensionTree, PDEUIMessages.ExtensionsPage_sortAlpha, null, null, this); > toolBarManager.add(fSortAction); >+ // Add expand selected leafs action to the toolbar >+ fExpandAction = new ToggleExpandStateAction(fFilteredTree, fExtensionTree); >+ toolBarManager.add(fExpandAction); > // Add collapse action to the tool bar > fCollapseAction = new CollapseAction(fExtensionTree, PDEUIMessages.ExtensionsPage_collapseAll); > toolBarManager.add(fCollapseAction); >@@ -309,11 +347,13 @@ > * @see org.eclipse.pde.internal.ui.editor.PDESection#doGlobalAction(java.lang.String) > */ > public boolean doGlobalAction(String actionId) { >- >+ if (actionId.equals(ActionFactory.FIND.getId()) && fFilterRelatedAction != null) { >+ fFilterRelatedAction.run(); >+ return true; >+ } > if (!isEditable()) { > return false; > } >- > if (actionId.equals(ActionFactory.DELETE.getId())) { > handleDelete(); > return true; >@@ -348,7 +388,7 @@ > > protected void fillContextMenu(IMenuManager manager) { > ISelection selection = fExtensionTree.getSelection(); >- IStructuredSelection ssel = (IStructuredSelection) selection; >+ final IStructuredSelection ssel = (IStructuredSelection) selection; > if (ssel.size() == 1) { > Object object = ssel.getFirstElement(); > if (object instanceof IPluginParent) { >@@ -377,12 +417,21 @@ > manager.add(new Separator()); > delAction.setEnabled(isEditable()); > } >+ if (ssel.size() > 0) { >+ if (FilterRelatedExtensionsAction.isFilterRelatedEnabled(ssel)) { >+ FilterRelatedExtensionsAction filterRelatedAction = new FilterRelatedExtensionsAction(fExtensionTree, fFilteredTree); >+ manager.add(filterRelatedAction); >+ SearchExtensionsAction searchRelatedAction = new SearchExtensionsAction(ssel, FilterRelatedExtensionsAction.getFilterRelatedPattern(ssel), PDEUIMessages.Actions_search_relatedPluginElements); >+ manager.add(searchRelatedAction); >+ manager.add(new Separator()); >+ } >+ } > manager.add(new Separator()); > if (ssel.size() < 2) { // only cut things when the selection is one > getPage().getPDEEditor().getContributor().addClipboardActions(manager); > } > getPage().getPDEEditor().getContributor().contextMenuAboutToShow(manager, false); >- >+ this.fFilteredTree.update(); > } > > static IMenuManager fillContextMenu(PDEFormPage page, final IPluginParent parent, IMenuManager manager) { >@@ -491,6 +540,10 @@ > PDEPlugin.logException(e); > } > } >+ } >+ >+ public FormFilteredTree getFormFilteredTree() { >+ return fFilteredTree; > } > > private void handleNew() { >@@ -643,10 +696,13 @@ > // The model changed but the editor is still open, we should try to retain expansion, selection will be retained on its own > Object[] expanded = fExtensionTree.getExpandedElements(); > IPluginModelBase model = (IPluginModelBase) getPage().getModel(); >- fExtensionTree.getControl().setRedraw(false); >- fExtensionTree.setInput(model.getPluginBase()); >- fExtensionTree.setExpandedElements(expanded); >- fExtensionTree.getControl().setRedraw(true); >+ try { >+ fExtensionTree.getControl().setRedraw(false); >+ fExtensionTree.setInput(model.getPluginBase()); >+ fExtensionTree.setExpandedElements(expanded); >+ } finally { >+ fExtensionTree.getControl().setRedraw(true); >+ } > reportMissingExtensionPointSchemas(model.getPluginBase()); > getManagedForm().fireSelectionChanged(ExtensionsSection.this, fExtensionTree.getSelection()); > super.refresh(); >@@ -809,8 +865,8 @@ > if (labelAtt == null) { > // try some hard-coded attributes that > // are used frequently >- for (int i = 0; i < COMMON_LABEL_PROPERTIES.length; i++) { >- labelAtt = element.getAttribute(COMMON_LABEL_PROPERTIES[i]); >+ for (int i = 0; i < COMMON_LABEL_ATTRIBUTES.length; i++) { >+ labelAtt = element.getAttribute(COMMON_LABEL_ATTRIBUTES[i]); > if (labelAtt != null) > break; > } >@@ -821,9 +877,14 @@ > labelAtt = element.getAttributes()[0]; > } > } >- if (labelAtt != null && labelAtt.getValue() != null) >+ if (labelAtt != null && labelAtt.getValue() != null) { > fullName = stripShortcuts(labelAtt.getValue()); >+ if (labelAtt.getName().equals(COMMON_LABEL_ATTRIBUTES[2])) { // remove package from handler class >+ fullName = fullName.substring(fullName.lastIndexOf('.') + 1, fullName.length()); >+ } >+ } > fullName = element.getResourceString(fullName); >+ > if (fullNames) > return fullName != null ? fullName : baseName; > if (fullName == null) >@@ -1081,6 +1142,18 @@ > } > > private void updateButtons(Object item) { >+ if (fExpandAction != null) { >+ fExpandAction.setEnabled(ToggleExpandStateAction.isExpandable((IStructuredSelection) fExtensionTree.getSelection())); >+ } >+ if (fFilterRelatedAction != null) { >+ fFilterRelatedAction.setEnabled(FilterRelatedExtensionsAction.isFilterRelatedEnabled((IStructuredSelection) fExtensionTree.getSelection())); >+ } >+ if (fSearchAction != null) { >+ Text filterControl = fFilteredTree.getFilterControl(); >+ // enable action only when filtering occurs >+ fSearchAction.setEnabled(filterControl != null && filterControl.getText().length() > 0); >+ } >+ > if (getPage().getModel().isEditable() == false) > return; > boolean sorted = fSortAction != null && fSortAction.isChecked(); >@@ -1140,8 +1213,52 @@ > * @see org.eclipse.pde.internal.ui.editor.TreeSection#createTreeViewer(org.eclipse.swt.widgets.Composite, int) > */ > protected TreeViewer createTreeViewer(Composite parent, int style) { >- fFilteredTree = new FormFilteredTree(parent, style, new PatternFilter()); >+ fFilteredTree = new FormFilteredTree(parent, style, new ExtensionsPatternFilter()) { >+ protected WorkbenchJob doCreateRefreshJob() { >+ final WorkbenchJob job = super.doCreateRefreshJob(); >+ job.addJobChangeListener(new JobChangeAdapter() { >+ private ISelection selection; >+ >+ public void scheduled(IJobChangeEvent event) { >+ ((ExtensionsPatternFilter) fFilteredTree.getPatternFilter()).clearMatchingLeafs(); >+ selection = fExtensionTree.getSelection(); >+ fFilteredTree.setRedraw(false); >+ } >+ >+ public void done(IJobChangeEvent event) { >+ ExtensionsPatternFilter extensionsPatternFilter = ((ExtensionsPatternFilter) fFilteredTree.getPatternFilter()); >+ fExtensionTree.collapseAll(); >+ Object[] leafs = extensionsPatternFilter.getMatchingLeafsAsArray(); >+ for (int i = 0; i < leafs.length; i++) { >+ fExtensionTree.expandToLevel(leafs[i], 0); >+ } >+ if (selection != null && !(selection.isEmpty())) { >+ fExtensionTree.setSelection(selection, false); >+ } >+ fFilteredTree.setRedraw(true); >+ } >+ >+ }); >+ return job; >+ } >+ >+ protected long getRefreshJobDelay() { >+ return 500; // required for continuous typing while performing extensive search operation >+ } >+ }; > parent.setData("filtered", Boolean.TRUE); //$NON-NLS-1$ >+ fFilteredTree.addMouseWheelListener(new MouseWheelListener() { >+ >+ public void mouseScrolled(MouseEvent e) { >+ if ((e.stateMask & SWT.MOD1) == SWT.MOD1) { >+ //System.out.println("e.stateMask == SWT.MOD1"); >+ //fExtensionTree.scrollDown(0, 80); >+ //fFilteredTree.redraw(); >+ } >+ //} >+ >+ } >+ }); > return fFilteredTree.getViewer(); > } > >diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties >index 36ab48f..e35c100 100644 >--- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties >+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties >@@ -1189,6 +1189,8 @@ > EditorActions_revert = Re&vert > Actions_open_label = &Open > Actions_delete_label = &Delete >+Actions_filter_relatedPluginElements=&Filter Related >+Actions_search_relatedPluginElements=Search &Related > Actions_synchronizeVersions_label = S&ynchronize Versions... > > Menus_new_label = &New >@@ -1536,6 +1538,8 @@ > ExtensionsPage_title=Extensions > ExtensionsPage_tabName=Extensions > ExtensionsPage_sortAlpha=Sort the Extensions alphabetically >+ExtensionsPage_toggleExpandState=Toggle Expand State >+ExtensionsPage_searchWithExtensionsFilter=Extension Element Search > ExtensionDetails_title=Extension Details > ExtensionDetails_desc=Set the properties of the selected extension. Required fields are denoted by "*". > ExtensionDetails_id=ID >diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/AttributesMatch.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/AttributesMatch.java >new file mode 100644 >index 0000000..abf9831 >--- /dev/null >+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/AttributesMatch.java >@@ -0,0 +1,45 @@ >+/******************************************************************************* >+ * Copyright (c) 2011, 2012 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Sascha Becher <s.becher@qualitype.de> - bug 360894 >+ *******************************************************************************/ >+package org.eclipse.pde.internal.ui.search; >+ >+import org.eclipse.pde.internal.ui.editor.plugin.ManifestEditor; >+import org.eclipse.search.ui.text.Match; >+ >+/** >+ * An extension to {@link Match} in order to present matching plugins which resulted >+ * in a search queried from the extensions page of the {@link ManifestEditor} >+ * >+ * @author Sascha Becher >+ */ >+public class AttributesMatch extends Match { >+ >+ /** >+ * A constant expressing that the {@link Match} resulted in a search queried from >+ * the extensions page of the {@link ManifestEditor} >+ */ >+ public static final int UNIT_ATTRIBUTE_SEARCH_PATTERN = 3; >+ >+ protected String searchPattern; >+ >+ public AttributesMatch(Object element, String searchPattern) { >+ super(element, UNIT_LINE, 0, 0); >+ this.searchPattern = searchPattern; >+ } >+ >+ public String getSearchPattern() { >+ return searchPattern; >+ } >+ >+ public int getBaseUnit() { >+ return UNIT_ATTRIBUTE_SEARCH_PATTERN; >+ } >+ >+} >\ No newline at end of file >diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/ExtensionElementSearchOperation.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/ExtensionElementSearchOperation.java >new file mode 100644 >index 0000000..d005c32 >--- /dev/null >+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/ExtensionElementSearchOperation.java >@@ -0,0 +1,88 @@ >+/******************************************************************************* >+ * Copyright (c) 2011, 2012 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Sascha Becher <s.becher@qualitype.de> - bug 360894 >+ *******************************************************************************/ >+package org.eclipse.pde.internal.ui.search; >+ >+import java.util.ArrayList; >+import org.eclipse.core.runtime.IProgressMonitor; >+import org.eclipse.pde.core.plugin.*; >+import org.eclipse.pde.internal.core.search.ISearchResultCollector; >+import org.eclipse.pde.internal.core.search.PluginSearchInput; >+ >+/** >+ * Search operation for finding extension elements within a plugin using the {@link ExtensionsPatternFilter}. >+ * >+ * @author Sascha Becher >+ */ >+public class ExtensionElementSearchOperation { >+ >+ protected PluginSearchInput fInput; >+ private ISearchResultCollector fCollector; >+ >+ public ExtensionElementSearchOperation(PluginSearchInput input, ISearchResultCollector collector) { >+ this.fInput = input; >+ this.fCollector = collector; >+ } >+ >+ public void execute(IProgressMonitor monitor) { >+ IPluginModelBase[] entries = fInput.getSearchScope().getMatchingModels(); >+ monitor.beginTask("", entries.length); //$NON-NLS-1$ >+ >+ try { >+ for (int i = 0; i < entries.length; i++) { >+ IPluginModelBase candidate = entries[i]; >+ visit(candidate); >+ monitor.worked(1); >+ } >+ } finally { >+ monitor.done(); >+ } >+ } >+ >+ private void visit(IPluginModelBase model) { >+ ArrayList matches = findMatch(model); >+ for (int i = 0; i < matches.size(); i++) { >+ fCollector.accept(matches.get(i)); >+ } >+ } >+ >+ private ArrayList findMatch(IPluginModelBase model) { >+ ArrayList result = new ArrayList(); >+ int searchLimit = fInput.getSearchLimit(); >+ if (fInput.getSearchElement() == PluginSearchInput.ELEMENT_PLUGIN) { >+ if (searchLimit != PluginSearchInput.LIMIT_REFERENCES) >+ findPluginDeclaration(model, result); >+ if (searchLimit != PluginSearchInput.LIMIT_DECLARATIONS) >+ findPluginReferences(model, result); >+ } >+ return result; >+ } >+ >+ private void findPluginDeclaration(IPluginModelBase model, ArrayList result) { >+ IPluginBase pluginBase = model.getPluginBase(); >+ ExtensionsPatternFilter filter = new ExtensionsPatternFilter(); >+ filter.setUseCacheForSearch(true); >+ filter.clearMatchingLeafs(); >+ filter.setPattern(fInput.getSearchString()); >+ filter.filter(null, pluginBase, pluginBase.getExtensions()); >+ if (pluginBase instanceof IPlugin && filter.getMatchingLeafsAsArray().length > 0) { >+ result.add(pluginBase); >+ } >+ } >+ >+ private void findPluginReferences(IPluginModelBase model, ArrayList result) { >+ IPluginBase pluginBase = model.getPluginBase(); >+ IPluginImport[] imports = pluginBase.getImports(); >+ for (int i = 0; i < imports.length; i++) { >+ findPluginDeclaration(imports[i].getPluginModel(), result); >+ } >+ } >+ >+} >\ No newline at end of file >diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/ExtensionsPatternFilter.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/ExtensionsPatternFilter.java >new file mode 100644 >index 0000000..8ab071e >--- /dev/null >+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/ExtensionsPatternFilter.java >@@ -0,0 +1,217 @@ >+/******************************************************************************* >+ * Copyright (c) 2011, 2012 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Sascha Becher <s.becher@qualitype.de> - bug 360894 >+ *******************************************************************************/ >+package org.eclipse.pde.internal.ui.search; >+ >+import java.util.*; >+import org.eclipse.jface.viewers.Viewer; >+import org.eclipse.pde.core.plugin.*; >+import org.eclipse.pde.internal.core.bundle.BundlePlugin; >+import org.eclipse.ui.dialogs.PatternFilter; >+ >+/** >+ * An extended filtering capability for the filtered tree of ExtensionsPage. The >+ * search criteria is splitted by / first. The resulting values are used to >+ * perform a search on all node's values. All elements fitting at least one of >+ * the split values will be displayed. This extensions does not compromise the >+ * default filtering behaviour of the tree while providing the ability to >+ * highlight related items such as commands along with their command images, >+ * handlers, menu entries and activities. >+ * >+ * @see org.eclipse.ui.dialogs.FilteredTree >+ * @since 3.8 >+ * >+ */ >+public class ExtensionsPatternFilter extends PatternFilter { >+ >+ // TODO related attributes should be configured in preferences >+ public static final String[] RELATED_ATTRIBUTES = {"label", //$NON-NLS-1$ >+ "id", "class", "commandId", "value", "pattern", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ >+ "locationURI", "defaultHandler"}; //$NON-NLS-1$ //$NON-NLS-2$ >+ >+ protected String[] valuePatterns = null; >+ protected String searchPattern; >+ >+ protected Set matchingLeafs = new HashSet(); >+ >+ /** >+ * Check if the current (leaf) element is a match with the filter text. The >+ * default behavior checks that the label of the element is a match. >+ * >+ * Subclasses should override this method. >+ * >+ * @param viewer >+ * the viewer that contains the element >+ * @param element >+ * the tree element to check >+ * @return true if the given element's label matches the filter text >+ */ >+ protected boolean isLeafMatch(Viewer viewer, Object element) { >+ Boolean foundAny = (Boolean) foundAnyCache.get(element); >+ if (foundAny != null) { >+ return foundAny.booleanValue(); >+ } >+ >+ // match label; default behaviour >+ if (viewer != null && super.isLeafMatch(viewer, element)) { >+ return true; >+ } >+ >+ // match all splitted attribute's values of IPluginElement against splitted filter patterns >+ if (element instanceof IPluginElement) { >+ if (valuePatterns != null && valuePatterns.length > 0) { >+ for (int j = 0; j < valuePatterns.length; j++) { >+ String valuePattern = valuePatterns[j]; >+ if (valuePattern != null && valuePattern.length() > 0) { >+ IPluginElement pluginElement = (IPluginElement) element; >+ int attributeCount = pluginElement.getAttributeCount(); >+ IPluginAttribute[] pluginAttributes = pluginElement.getAttributes(); >+ for (int i = 0; i < attributeCount; i++) { >+ IPluginAttribute attribute = pluginAttributes[i]; >+ if (attribute != null && attribute.getValue() != null) { >+ String[] attributes = attribute.getValue().replaceAll("/{1,}", "/").split("/"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ >+ if (attributes != null) { >+ for (int k = 0; k < attributes.length; k++) { >+ String value = attributes[k]; >+ if (value != null && value.length() > 0) { >+ if (!value.startsWith("%")) { //$NON-NLS-1$ >+ int delimiterPosition = value.indexOf('?'); // strip right of '?' >+ if (delimiterPosition != -1) { >+ value = value.substring(0, delimiterPosition); >+ } >+ } else { >+ String resourceValue = pluginElement.getResourceString(value); >+ value = (resourceValue != null && resourceValue.length() > 0) ? resourceValue : value; >+ } >+ if (value.toLowerCase().equals(valuePattern.toLowerCase())) { >+ return true; >+ } >+ } >+ } >+ } >+ } >+ } >+ if (valuePattern.equalsIgnoreCase(pluginElement.getName())) { >+ return true; >+ } >+ } >+ } >+ } >+ } >+ return false; >+ } >+ >+ public Object[] filter(Viewer viewer, Object parent, Object[] elements) { >+ if (!useCache) { >+ return super.filter(viewer, parent, elements); >+ } >+ if (parent != null && parent instanceof BundlePlugin) { >+ if (foundAnyCache.keySet().size() == 0) { >+ BundlePlugin pluginPlugin = (BundlePlugin) parent; >+ doFilter(viewer, pluginPlugin, pluginPlugin.getExtensions()); >+ } >+ } >+ return super.filter(viewer, parent, elements); >+ } >+ >+ protected boolean doFilter(Viewer viewer, Object parent, IPluginObject[] children) { >+ boolean isParentMatch = false; >+ Object parentMatch = foundAnyCache.get(parent); >+ if (parentMatch != null) { >+ isParentMatch = ((Boolean) parentMatch).booleanValue(); >+ } >+ >+ // find leaf matches >+ boolean isAnyLeafMatch = false; >+ for (int j = 0; j < children.length; j++) { >+ IPluginObject iPluginObject = children[j]; >+ boolean isChildMatch = true; >+ if (!isParentMatch) { >+ isChildMatch = this.isLeafMatch(viewer, iPluginObject); >+ isAnyLeafMatch |= isChildMatch; >+ if (isChildMatch) { >+ matchingLeafs.add(iPluginObject); >+ } >+ } >+ foundAnyCache.put(iPluginObject, Boolean.valueOf(isChildMatch)); >+ } >+ >+ // traverse children when available >+ boolean isAnyChildMatch = false; >+ for (int i = 0; i < children.length; i++) { >+ IPluginObject iPluginObject = children[i]; >+ if (iPluginObject instanceof IPluginParent) { >+ IPluginParent pluginElement = (IPluginParent) iPluginObject; >+ if (pluginElement.getChildren().length > 0) { >+ boolean isChildrenMatch = doFilter(viewer, pluginElement, pluginElement.getChildren()); >+ isAnyChildMatch |= isChildrenMatch; >+ if (isChildrenMatch) { >+ foundAnyCache.put(iPluginObject, Boolean.TRUE); >+ isParentMatch = true; >+ } >+ } >+ } >+ } >+ return isAnyChildMatch | isAnyLeafMatch; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) >+ */ >+ public boolean select(Viewer viewer, Object parentElement, Object element) { >+ if (useCache) { >+ Object cachedResult = foundAnyCache.get(element); >+ if (cachedResult != null) { >+ return ((Boolean) cachedResult).booleanValue(); >+ } >+ } >+ return isLeafMatch(viewer, element); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * >+ * @see org.eclipse.ui.dialogs.PatternFilter#setPattern(java.lang.String) >+ */ >+ public final void setPattern(String patternString) { >+ super.setPattern(patternString); >+ searchPattern = patternString; >+ valuePatterns = patternString.replaceAll("/{1,}", "/").split("/"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ >+ } >+ >+ public String getPattern() { >+ return searchPattern; >+ } >+ >+ public void clearMatchingLeafs() { >+ matchingLeafs.clear(); >+ } >+ >+ public Object[] getMatchingLeafsAsArray() { >+ return matchingLeafs.toArray(); >+ } >+ >+ public void addMatchingLeafs(List children) { >+ System.out.println(matchingLeafs.size()); >+ matchingLeafs.addAll(children); >+ System.out.println(matchingLeafs.size()); >+ } >+ >+ /** >+ * Can be called to turn on caching. >+ * >+ * @param useCache >+ * The useCache to set. >+ */ >+ public void setUseCacheForSearch(boolean useCache) { >+ this.useCache = useCache; >+ } >+ >+} >\ No newline at end of file >diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/FindExtensionsByAttributeQuery.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/FindExtensionsByAttributeQuery.java >new file mode 100644 >index 0000000..77a2b82 >--- /dev/null >+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/FindExtensionsByAttributeQuery.java >@@ -0,0 +1,83 @@ >+/** >+ * >+ */ >+package org.eclipse.pde.internal.ui.search; >+ >+import org.eclipse.core.runtime.*; >+import org.eclipse.jface.viewers.IStructuredSelection; >+import org.eclipse.pde.internal.core.bundle.BundlePlugin; >+import org.eclipse.pde.internal.core.search.ISearchResultCollector; >+import org.eclipse.pde.internal.core.search.PluginSearchInput; >+import org.eclipse.search.ui.ISearchQuery; >+import org.eclipse.search.ui.ISearchResult; >+import org.eclipse.search.ui.text.AbstractTextSearchResult; >+ >+/** >+ * @author zour >+ * >+ */ >+public class FindExtensionsByAttributeQuery implements ISearchQuery { >+ >+ private SearchResult fSearchResult; >+ >+ private PluginSearchInput fSearchInput; >+ >+ public FindExtensionsByAttributeQuery(IStructuredSelection selection, PluginSearchInput input) { >+ fSearchInput = input; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.search.ui.ISearchQuery#run(org.eclipse.core.runtime.IProgressMonitor) >+ */ >+ public IStatus run(IProgressMonitor monitor) throws OperationCanceledException { >+ final AbstractTextSearchResult result = (AbstractTextSearchResult) getSearchResult(); >+ result.removeAll(); >+ ISearchResultCollector collector = new ISearchResultCollector() { >+ public void accept(Object match) { >+ if (match instanceof BundlePlugin) { >+ BundlePlugin plugin = (BundlePlugin) match; >+ result.addMatch(new AttributesMatch(plugin, fSearchInput.getSearchString())); >+ } >+ } >+ }; >+ ExtensionElementSearchOperation op = new ExtensionElementSearchOperation(fSearchInput, collector); >+ op.execute(monitor); >+ monitor.done(); >+ return Status.OK_STATUS; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.search.ui.ISearchQuery#getLabel() >+ */ >+ public String getLabel() { >+ return fSearchInput.getSearchString(); >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.search.ui.ISearchQuery#canRerun() >+ */ >+ public boolean canRerun() { >+ return true; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.search.ui.ISearchQuery#canRunInBackground() >+ */ >+ public boolean canRunInBackground() { >+ return true; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.search.ui.ISearchQuery#getSearchResult() >+ */ >+ public ISearchResult getSearchResult() { >+ if (fSearchResult == null) >+ fSearchResult = new SearchResult(this); >+ return fSearchResult; >+ } >+ >+ public PluginSearchInput getPluginSearchInput() { >+ return fSearchInput; >+ } >+ >+} >\ No newline at end of file >diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/ManifestEditorOpener.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/ManifestEditorOpener.java >index ded4863..dd56de7 100644 >--- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/ManifestEditorOpener.java >+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/ManifestEditorOpener.java >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Sascha Becher <s.becher@qualitype.de> - bug 360894 > *******************************************************************************/ > package org.eclipse.pde.internal.ui.search; > >@@ -16,10 +17,13 @@ > import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase; > import org.eclipse.pde.internal.core.ibundle.IManifestHeader; > import org.eclipse.pde.internal.core.text.plugin.PluginObjectNode; >-import org.eclipse.pde.internal.ui.editor.plugin.ManifestEditor; >+import org.eclipse.pde.internal.ui.editor.plugin.*; > import org.eclipse.search.ui.text.Match; > import org.eclipse.ui.IEditorPart; > import org.eclipse.ui.PartInitException; >+import org.eclipse.ui.forms.IFormPart; >+import org.eclipse.ui.forms.IManagedForm; >+import org.eclipse.ui.forms.editor.IFormPage; > import org.osgi.framework.Constants; > > // TODO this needs a rewrite >@@ -30,10 +34,20 @@ > editorPart = ManifestEditor.open(match.getElement(), true); > if (editorPart != null && editorPart instanceof ManifestEditor) { > ManifestEditor editor = (ManifestEditor) editorPart; >- IDocument doc = editor.getDocument(match); >- if (doc != null) { >- Match exact = findExactMatch(doc, match, editor); >- editor.openToSourcePage(match.getElement(), exact.getOffset(), exact.getLength()); >+ if (match.getBaseUnit() != AttributesMatch.UNIT_ATTRIBUTE_SEARCH_PATTERN) { >+ IDocument doc = editor.getDocument(match); >+ if (doc != null) { >+ Match exact = findExactMatch(doc, match, editor); >+ editor.openToSourcePage(match.getElement(), exact.getOffset(), exact.getLength()); >+ } >+ } else { // open to extensions page and initialize filter with search result's pattern text >+ IFormPage page = editor.setActivePage(ExtensionsPage.PAGE_ID); >+ IManagedForm form = page.getManagedForm(); >+ IFormPart parts[] = form.getParts(); >+ if (parts != null && parts.length > 0) { >+ ExtensionsSection section = (ExtensionsSection) parts[0]; >+ section.getFormFilteredTree().getFilterControl().setText(((AttributesMatch) match).getSearchPattern()); >+ } > } > } > return editorPart; >diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/SearchResult.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/SearchResult.java >index f09c4ef..cd9f099 100644 >--- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/SearchResult.java >+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/search/SearchResult.java >@@ -7,6 +7,7 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >+ * Sascha Becher <s.becher@qualitype.de> - bug 360894 > *******************************************************************************/ > package org.eclipse.pde.internal.ui.search; > >@@ -29,9 +30,15 @@ > > public class SearchResult extends AbstractTextSearchResult implements IEditorMatchAdapter { > protected ISearchQuery fQuery; >+ private final ImageDescriptor fImage; > > public SearchResult(ISearchQuery query) { > fQuery = query; >+ if (fQuery instanceof FindExtensionsByAttributeQuery) { >+ fImage = PDEPluginImages.DESC_ESEARCH_OBJ; >+ } else { >+ fImage = PDEPluginImages.DESC_PSEARCH_OBJ; >+ } > } > > /* (non-Javadoc) >@@ -60,7 +67,7 @@ > * @see org.eclipse.search.ui.ISearchResult#getImageDescriptor() > */ > public ImageDescriptor getImageDescriptor() { >- return PDEPluginImages.DESC_PSEARCH_OBJ; >+ return fImage; > } > > /* (non-Javadoc)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 360894
:
205156
|
205157
|
209727
|
209729
|
211150
|
211250