[248380] Provide Sort option in Outline view
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/sort.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/sort.gif
new file mode 100644
index 0000000..23c5d0b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/sort.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIMessages.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIMessages.java
index fe5a3b8..3150a14 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIMessages.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIMessages.java
@@ -300,7 +300,8 @@
public static String previousSibling_label;
public static String previousSibling_description;
public static String Use_XInclude;
-
+ public static String Open;
+ public static String _UI_BUTTON_SORT;
static {
// load message values from bundle file
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIPluginResources.properties b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIPluginResources.properties
index 323ab87..aed3ba8 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIPluginResources.properties
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIPluginResources.properties
@@ -329,4 +329,5 @@
previousSibling_description=Go to Previous Sibling
gotoMatchingTag_label=Matching Tag
gotoMatchingTag_description=Go To Matching Tag
-
+Open=Open "{0}"
+_UI_BUTTON_SORT=Sort
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeLabelProvider.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeLabelProvider.java
index 8e3b504..6168dde 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeLabelProvider.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeLabelProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * Copyright (c) 2001, 2008 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
@@ -12,16 +12,16 @@
*******************************************************************************/
package org.eclipse.wst.xml.ui.internal.contentoutline;
-import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.swt.graphics.Image;
import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapter;
/**
- * A label provider backed by JFaceNodeAdapters.
+ * A (column) label provider backed by JFaceNodeAdapters.
*/
-public class JFaceNodeLabelProvider extends LabelProvider {
+public class JFaceNodeLabelProvider extends ColumnLabelProvider {
/**
* JFaceNodeLabelProvider constructor comment.
*/
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/RefreshStructureJob.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/RefreshStructureJob.java
index 6960dbd..a58c09b 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/RefreshStructureJob.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/RefreshStructureJob.java
@@ -13,7 +13,9 @@
package org.eclipse.wst.xml.ui.internal.contentoutline;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
@@ -42,32 +44,53 @@
/** debug flag */
static final boolean DEBUG;
- private static final long UPDATE_DELAY = 250;
+ private static final long UPDATE_DELAY = 300;
static {
String value = Platform.getDebugOption("org.eclipse.wst.sse.ui/debug/refreshStructure"); //$NON-NLS-1$
DEBUG = (value != null) && value.equalsIgnoreCase("true"); //$NON-NLS-1$
}
/** List of refresh requests (Nodes) */
- private final List fRequests;
+ private final List fRefreshes;
+ /** List of update requests (Nodes) */
+ private final List fUpdates;
+ /** List of update requests (Nodes) */
+ private final List fUpdateProperties;
/** the structured viewers */
- List fViewers = new ArrayList(3);
+ Set fRefreshViewers = new HashSet(3);
+ Set fUpdateViewers = new HashSet(3);
public RefreshStructureJob() {
super(XMLUIMessages.refreshoutline_0);
setPriority(Job.LONG);
setSystem(true);
- fRequests = new ArrayList(2);
+ fRefreshes = new ArrayList(5);
+ fUpdates = new ArrayList(5);
+ fUpdateProperties = new ArrayList(5);
}
- private synchronized void addRequest(Node newNodeRequest) {
+ private synchronized void addUpdateRequest(Node newNodeRequest, String[] updateProperties) {
+ /*
+ * If we get to here, either from existing request list being zero
+ * length, or no exisitng requests "matched" new request, then add the
+ * new request.
+ */
+ fUpdates.add(newNodeRequest);
+ fUpdateProperties.add(updateProperties);
+ }
+
+ private synchronized void addUpdateViewer(StructuredViewer viewer) {
+ fUpdateViewers.add(viewer);
+ }
+
+ private synchronized void addRefreshRequest(Node newNodeRequest) {
/*
* note: the caller must NOT pass in null node request (which, since
* private method, we do not need to gaurd against here, as long as we
* gaurd against it in calling method.
*/
- int size = fRequests.size();
+ int size = fRefreshes.size();
for (int i = 0; i < size; i++) {
- Node existingNodeRequest = (Node) fRequests.get(i);
+ Node existingNodeRequest = (Node) fRefreshes.get(i);
/*
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=157427 If we
* already have a request which equals the new request, discard
@@ -94,7 +117,7 @@
* any that are contained by new request ... in future :) .
*/
if (contains(newNodeRequest, existingNodeRequest)) {
- fRequests.set(i, newNodeRequest);
+ fRefreshes.set(i, newNodeRequest);
return;
}
}
@@ -103,13 +126,11 @@
* length, or no exisitng requests "matched" new request, then add the
* new request.
*/
- fRequests.add(newNodeRequest);
+ fRefreshes.add(newNodeRequest);
}
- private synchronized void addViewer(StructuredViewer viewer) {
- if (!fViewers.contains(viewer)) {
- fViewers.add(viewer);
- }
+ private synchronized void addRefreshViewer(StructuredViewer viewer) {
+ fRefreshViewers.add(viewer);
}
/**
@@ -203,23 +224,70 @@
}
/**
- * This method also synchronized because it accesses the fRequests queue
- * and fViewers list
+ * Update must be on UI thread because it's on a SWT widget.
+ *
+ * @param node
+ */
+ private void doUpdate(final StructuredViewer[] viewers, final Node node, final String[] properties) {
+ final Display display = PlatformUI.getWorkbench().getDisplay();
+ display.asyncExec(new Runnable() {
+ public void run() {
+ if (DEBUG) {
+ System.out.println("refresh on: [" + node.getNodeName() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ for (int i = 0; i < viewers.length; i++) {
+ if (!viewers[i].getControl().isDisposed()) {
+ viewers[i].update(node, properties);
+ }
+ else {
+ if (DEBUG) {
+ System.out.println(" !!! skipped refreshing disposed viewer: " + viewers[i]); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * This method also synchronized because it accesses the fRefreshes queue
+ * and fRefreshViewers list
*
* @return an array containing and array of the currently requested Nodes
* to refresh and the viewers in which to refresh them
*/
- private synchronized Object[] getRequests() {
- Node[] toRefresh = (Node[]) fRequests.toArray(new Node[fRequests.size()]);
- fRequests.clear();
+ private synchronized Object[] getRefreshRequests() {
+ Node[] toRefresh = (Node[]) fRefreshes.toArray(new Node[fRefreshes.size()]);
+ fRefreshes.clear();
- StructuredViewer[] viewers = (StructuredViewer[]) fViewers.toArray(new StructuredViewer[fViewers.size()]);
- fViewers.clear();
+ StructuredViewer[] viewers = (StructuredViewer[]) fRefreshViewers.toArray(new StructuredViewer[fRefreshViewers.size()]);
+ fRefreshViewers.clear();
return new Object[]{toRefresh, viewers};
}
/**
+ * This method also synchronized because it accesses the fUpdates queue
+ * and fUpdateViewers list
+ *
+ * @return an array containing and array of the currently requested Nodes
+ * to refresh and the viewers in which to refresh them
+ */
+ private synchronized Object[] getUpdateRequests() {
+ Node[] toUpdate = (Node[]) fUpdates.toArray(new Node[fUpdates.size()]);
+ fUpdates.clear();
+
+ StructuredViewer[] viewers = (StructuredViewer[]) fUpdateViewers.toArray(new StructuredViewer[fUpdateViewers.size()]);
+ fUpdateViewers.clear();
+
+ String[][] properties = (String[][]) fUpdateProperties.toArray(new String[fUpdateProperties.size()][]);
+ fUpdateProperties.clear();
+
+ return new Object[]{toUpdate, viewers, properties};
+ }
+
+ /**
* Invoke a refresh on the viewer on the given node.
*
* @param node
@@ -229,25 +297,32 @@
return;
}
- addViewer(viewer);
- addRequest(node);
+ addRefreshViewer(viewer);
+ addRefreshRequest(node);
+ schedule(UPDATE_DELAY);
+ }
+
+ /**
+ * Invoke a refresh on the viewer on the given node.
+ *
+ * @param node
+ */
+ public void update(StructuredViewer viewer, Node node, String[] properties) {
+ if (node == null) {
+ return;
+ }
+
+ addUpdateViewer(viewer);
+ addUpdateRequest(node, properties);
schedule(UPDATE_DELAY);
}
protected IStatus run(IProgressMonitor monitor) {
IStatus status = Status.OK_STATUS;
try {
- // Retrieve BOTH viewers and Nodes on one block
- Object[] requests = getRequests();
- Node[] nodes = (Node[]) requests[0];
- StructuredViewer[] viewers = (StructuredViewer[]) requests[1];
-
- for (int i = 0; i < nodes.length; i++) {
- if (monitor.isCanceled()) {
- throw new OperationCanceledException();
- }
- doRefresh(nodes[i], viewers);
- }
+ performUpdates();
+
+ performRefreshes(monitor);
}
finally {
monitor.done();
@@ -255,4 +330,30 @@
return status;
}
+ private void performRefreshes(IProgressMonitor monitor) {
+ // Retrieve BOTH viewers and Nodes on one block
+ Object[] requests = getRefreshRequests();
+ Node[] nodes = (Node[]) requests[0];
+ StructuredViewer[] viewers = (StructuredViewer[]) requests[1];
+
+ for (int i = 0; i < nodes.length; i++) {
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ doRefresh(nodes[i], viewers);
+ }
+ }
+
+ private void performUpdates() {
+ // Retrieve BOTH viewers and Nodes on one block
+ Object[] requests = getUpdateRequests();
+ Node[] nodes = (Node[]) requests[0];
+ StructuredViewer[] viewers = (StructuredViewer[]) requests[1];
+ String[][] properties = (String[][]) requests[2];
+
+ for (int i = 0; i < nodes.length; i++) {
+ doUpdate(viewers, nodes[i], properties[i]);
+ }
+ }
+
}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImages.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImages.java
index 3e2a63e..a13408d 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImages.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImages.java
@@ -41,6 +41,7 @@
public static final String IMG_OBJ_LOCAL_VARIABLE = "icons/full/obj16/localvariable_obj.gif"; //$NON-NLS-1$
public static final String IMG_OBJ_NOTATION = "icons/full/obj16/notation.gif"; //$NON-NLS-1$
public static final String IMG_OBJ_PROCESSINGINSTRUCTION = "icons/full/obj16/proinst_obj.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_SORT = "icons/full/obj16/sort.gif"; //$NON-NLS-1$
public static final String IMG_OBJ_TAG_GENERIC = "icons/full/obj16/tag-generic.gif"; //$NON-NLS-1$
public static final String IMG_OBJ_TAG_GENERIC_DEEMPHASIZED = "icons/full/obj16/tag_generic_deemphasized_obj.gif"; //$NON-NLS-1$
public static final String IMG_OBJ_TAG_GENERIC_EMPHASIZED = "icons/full/obj16/tag_generic_emphasized_obj.gif"; //$NON-NLS-1$
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLUIPreferenceNames.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLUIPreferenceNames.java
index d71a7a3..771ff17 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLUIPreferenceNames.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLUIPreferenceNames.java
@@ -65,6 +65,21 @@
*/
public static final String USE_INFERRED_GRAMMAR = getUseInferredGrammarKey();
+ public static class OUTLINE_BEHAVIOR {
+ public static final String ELEMENT_NODE = "outline-behavior.element-node"; //$NON-NLS-1$
+ public static final String ATTRIBUTE_NODE = "outline-behavior.attribute-node"; //$NON-NLS-1$
+ public static final String TEXT_NODE = "outline-behavior.text-node"; //$NON-NLS-1$
+ public static final String CDATA_SECTION_NODE = "outline-behavior.cdata-section-node"; //$NON-NLS-1$
+ public static final String ENTITY_REFERENCE_NODE = "outline-behavior.entity-reference-node"; //$NON-NLS-1$
+ public static final String ENTITY_NODE = "outline-behavior.entity-node"; //$NON-NLS-1$
+ public static final String PROCESSING_INSTRUCTION_NODE = "outline-behavior.instruction-node"; //$NON-NLS-1$
+ public static final String COMMENT_NODE = "outline-behavior.comment-node"; //$NON-NLS-1$
+ public static final String DOCUMENT_NODE = "outline-behavior.document-node"; //$NON-NLS-1$
+ public static final String DOCUMENT_TYPE_NODE = "outline-behavior.document-type-node"; //$NON-NLS-1$
+ public static final String DOCUMENT_FRAGMENT_NODE = "outline-behavior.document-fragment-node"; //$NON-NLS-1$
+ public static final String NOTATION_NODE = "outline-behavior.notation-node"; //$NON-NLS-1$
+ }
+
private static String getUseInferredGrammarKey() {
return "useInferredGrammar"; //$NON-NLS-1$
}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/AbstractXMLContentOutlineConfiguration.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/AbstractXMLContentOutlineConfiguration.java
index abeda1c..c536274 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/AbstractXMLContentOutlineConfiguration.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/AbstractXMLContentOutlineConfiguration.java
@@ -50,7 +50,7 @@
* @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration
* @since 3.1
*/
-public class AbstractXMLContentOutlineConfiguration extends ContentOutlineConfiguration {
+public abstract class AbstractXMLContentOutlineConfiguration extends ContentOutlineConfiguration {
private class ActionManagerMenuListener implements IMenuListener, IReleasable {
private XMLNodeActionManager fActionManager;
private TreeViewer fTreeViewer;
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/SortAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/SortAction.java
new file mode 100644
index 0000000..14caaa9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/SortAction.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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:
+ * IBM Corporation - initial API and implementation
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.contentoutline;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.sse.ui.internal.contentoutline.PropertyChangeUpdateAction;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.internal.preferences.XMLUIPreferenceNames;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+/**
+ * Toggling sort action for XML outlines
+ */
+class SortAction extends PropertyChangeUpdateAction {
+ static class ViewerNodeComparator extends ViewerComparator {
+ private int[] categories = new int[12];
+
+ public ViewerNodeComparator(IPreferenceStore store) {
+ super();
+ initCategoryOrder(store);
+ }
+
+ /**
+ * @param store
+ */
+ private void initCategoryOrder(IPreferenceStore store) {
+ String[] order = new String[12];
+ order[Node.ELEMENT_NODE - 1] = StringUtils.unpack(store.getString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ELEMENT_NODE))[0];
+ order[Node.ATTRIBUTE_NODE - 1] = StringUtils.unpack(store.getString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ATTRIBUTE_NODE))[0];
+ order[Node.TEXT_NODE - 1] = StringUtils.unpack(store.getString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.TEXT_NODE))[0];
+ order[Node.CDATA_SECTION_NODE - 1] = StringUtils.unpack(store.getString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.CDATA_SECTION_NODE))[0];
+ order[Node.ENTITY_REFERENCE_NODE - 1] = StringUtils.unpack(store.getString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ENTITY_REFERENCE_NODE))[0];
+ order[Node.ENTITY_NODE - 1] = StringUtils.unpack(store.getString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ENTITY_NODE))[0];
+ order[Node.PROCESSING_INSTRUCTION_NODE - 1] = StringUtils.unpack(store.getString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.PROCESSING_INSTRUCTION_NODE))[0];
+ order[Node.COMMENT_NODE - 1] = StringUtils.unpack(store.getString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.COMMENT_NODE))[0];
+ order[Node.DOCUMENT_NODE - 1] = StringUtils.unpack(store.getString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_NODE))[0];
+ order[Node.DOCUMENT_TYPE_NODE - 1] = StringUtils.unpack(store.getString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_TYPE_NODE))[0];
+ order[Node.DOCUMENT_FRAGMENT_NODE - 1] = StringUtils.unpack(store.getString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_FRAGMENT_NODE))[0];
+ order[Node.NOTATION_NODE - 1] = StringUtils.unpack(store.getString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.NOTATION_NODE))[0];
+ for (int i = 0; i < order.length; i++) {
+ try {
+ categories[i] = Integer.parseInt(order[i]);
+ }
+ catch (NumberFormatException e) {
+ }
+ }
+ }
+
+ public int category(Object element) {
+ if (element instanceof Node) {
+ return (categories[((Node) element).getNodeType() - 1]);
+ }
+
+ return super.category(element);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.viewers.ViewerComparator#isSorterProperty(java
+ * .lang.Object, java.lang.String)
+ */
+ public boolean isSorterProperty(Object element, String property) {
+ if (element instanceof Element) {
+ return ((Element) element).hasAttribute(property);
+ }
+ return super.isSorterProperty(element, property);
+ }
+ }
+
+ private TreeViewer treeViewer;
+
+ public SortAction(TreeViewer viewer, IPreferenceStore store, String preferenceKey) {
+ super(XMLUIMessages._UI_BUTTON_SORT, store, preferenceKey, false); //$NON-NLS-1$
+ setImageDescriptor(XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_SORT));
+ setToolTipText(getText());
+ treeViewer = viewer;
+ if (isChecked()) {
+ treeViewer.setComparator(createComparator());
+ }
+ }
+
+ private ViewerNodeComparator createComparator() {
+ return new ViewerNodeComparator(getPreferenceStore());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.texteditor.IUpdate#update()
+ */
+ public void update() {
+ super.update();
+ treeViewer.getControl().setRedraw(false);
+ Object[] expandedElements = treeViewer.getExpandedElements();
+ if (isChecked()) {
+ treeViewer.setComparator(createComparator());
+ }
+ else {
+ treeViewer.setComparator(null);
+ }
+ treeViewer.setInput(treeViewer.getInput());
+ treeViewer.setExpandedElements(expandedElements);
+ treeViewer.getControl().setRedraw(true);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLContentOutlineConfiguration.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLContentOutlineConfiguration.java
index af64219..f1e5bb1 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLContentOutlineConfiguration.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLContentOutlineConfiguration.java
@@ -38,24 +38,28 @@
import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeContentProvider;
import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeLabelProvider;
+import org.eclipse.wst.xml.ui.internal.preferences.XMLUIPreferenceNames;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
/**
- * Outline Configuration for generic XML support, expects that the viewer's
+ * More advanced Outline Configuration for XML support. Expects that the viewer's
* input will be the DOM Model.
*
- * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration
+ * @see AbstractXMLContentOutlineConfiguration
* @since 1.0
-
- TODO: Add Sort and Hide Comment actions
-
*/
public class XMLContentOutlineConfiguration extends AbstractXMLContentOutlineConfiguration {
+ static final String ATTR_NAME = "name";
+ static final String ATTR_ID = "id";
private class AttributeShowingLabelProvider extends JFaceNodeLabelProvider {
+ public boolean isLabelProperty(Object element, String property) {
+ return true;
+ }
+
/*
* (non-Javadoc)
*
@@ -64,9 +68,9 @@
public String getText(Object o) {
StringBuffer text = null;
if (o instanceof Node) {
- text = new StringBuffer(super.getText(o));
Node node = (Node) o;
if ((node.getNodeType() == Node.ELEMENT_NODE) && fShowAttributes) {
+ text = new StringBuffer(super.getText(o));
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=88444
if (node.hasAttributes()) {
Element element = (Element) node;
@@ -115,8 +119,8 @@
requiredAttribute = attr;
}
else {
- hasId = hasId || attrName.equals("id"); //$NON-NLS-1$
- hasName = hasName || attrName.equals("name"); //$NON-NLS-1$
+ hasId = hasId || attrName.equals(ATTR_ID);
+ hasName = hasName || attrName.equals(ATTR_NAME);
}
}
++i;
@@ -135,10 +139,10 @@
shownAttribute = requiredAttribute;
}
else if (hasId) {
- shownAttribute = attributes.getNamedItem("id"); //$NON-NLS-1$
+ shownAttribute = attributes.getNamedItem(ATTR_ID);
}
else if (hasName) {
- shownAttribute = attributes.getNamedItem("name"); //$NON-NLS-1$
+ shownAttribute = attributes.getNamedItem(ATTR_NAME);
}
if (shownAttribute == null) {
shownAttribute = attributes.item(0);
@@ -157,12 +161,65 @@
}
}
}
+ else {
+ text = new StringBuffer(super.getText(o));
+ }
}
else {
return super.toString();
}
return text.toString();
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.CellLabelProvider#getToolTipText(java.lang.Object)
+ */
+ public String getToolTipText(Object element) {
+ if (element instanceof Node) {
+ switch (((Node) element).getNodeType()) {
+ case Node.COMMENT_NODE :
+ case Node.CDATA_SECTION_NODE :
+ case Node.PROCESSING_INSTRUCTION_NODE :
+ case Node.TEXT_NODE : {
+ String nodeValue = ((Node) element).getNodeValue().trim();
+ return prepareText(nodeValue);
+ }
+ case Node.ELEMENT_NODE : {
+ // show the preceding comment's tooltip information
+ Node previous = ((Node) element).getPreviousSibling();
+ if (previous != null && previous.getNodeType() == Node.TEXT_NODE)
+ previous = previous.getPreviousSibling();
+ if (previous != null && previous.getNodeType() == Node.COMMENT_NODE)
+ return getToolTipText(previous);
+ }
+ }
+ }
+ return super.getToolTipText(element);
+ }
+
+ /**
+ * Remove leading indentation from each line in the give string.
+ * @param text
+ * @return
+ */
+ private String prepareText(String text) {
+ StringBuffer nodeText = new StringBuffer();
+ for (int i = 0; i < text.length(); i++) {
+ char c = text.charAt(i);
+ if (c != '\r' && c != '\n') {
+ nodeText.append(c);
+ }
+ else if (c == '\r' || c == '\n') {
+ nodeText.append('\n');
+ while (Character.isWhitespace(c) && i < text.length()) {
+ i++;
+ c = text.charAt(i);
+ }
+ nodeText.append(c);
+ }
+ }
+ return nodeText.toString();
+ }
}
/**
@@ -199,6 +256,7 @@
fTreeViewer.refresh(true);
}
}
+
private ILabelProvider fAttributeShowingLabelProvider;
private IContentProvider fContentProvider = null;
@@ -207,7 +265,11 @@
/*
* Preference key for Show Attributes
*/
- private final String OUTLINE_SHOW_ATTRIBUTE_PREF = "outline-show-attribute-editor"; //$NON-NLS-1$
+ private final String OUTLINE_SHOW_ATTRIBUTE_PREF = "outline-show-attribute"; //$NON-NLS-1$
+ /*
+ * Preference key for Sorting
+ */
+ private final String OUTLINE_SORT_PREF = "outline-sort"; //$NON-NLS-1$
/**
* Create new instance of XMLContentOutlineConfiguration
@@ -215,6 +277,37 @@
public XMLContentOutlineConfiguration() {
// Must have empty constructor to createExecutableExtension
super();
+
+ /**
+ * Set up our preference store here. This is done so that subclasses
+ * aren't required to set their own values, although if they have,
+ * those will be used instead.
+ */
+ IPreferenceStore store = getPreferenceStore();
+ if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_NODE).length() == 0)
+ store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_NODE, "1, true");
+ if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.PROCESSING_INSTRUCTION_NODE).length() == 0)
+ store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.PROCESSING_INSTRUCTION_NODE, "2, true");
+ if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_TYPE_NODE).length() == 0)
+ store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_TYPE_NODE, "3, true");
+ if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_FRAGMENT_NODE).length() == 0)
+ store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_FRAGMENT_NODE, "4, true");
+ if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.COMMENT_NODE).length() == 0)
+ store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.COMMENT_NODE, "5, true");
+ if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ATTRIBUTE_NODE).length() == 0)
+ store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ATTRIBUTE_NODE, "6, false");
+ if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ELEMENT_NODE).length() == 0)
+ store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ELEMENT_NODE, "7, true");
+ if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ENTITY_REFERENCE_NODE).length() == 0)
+ store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ENTITY_REFERENCE_NODE, "8, true");
+ if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.CDATA_SECTION_NODE).length() == 0)
+ store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.CDATA_SECTION_NODE, "9, true");
+ if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ENTITY_NODE).length() == 0)
+ store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ENTITY_NODE, "10, true");
+ if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.NOTATION_NODE).length() == 0)
+ store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.NOTATION_NODE, "11, true");
+ if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.TEXT_NODE).length() == 0)
+ store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.TEXT_NODE, "12, false");
}
/*
@@ -226,14 +319,18 @@
IContributionItem[] items;
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=88444
IContributionItem showAttributeItem = new PropertyChangeUpdateActionContributionItem(new ToggleShowAttributeAction(getPreferenceStore(), OUTLINE_SHOW_ATTRIBUTE_PREF, viewer));
+
+ IContributionItem sortItem = new PropertyChangeUpdateActionContributionItem(new SortAction(viewer, getPreferenceStore(), OUTLINE_SORT_PREF));
+
items = super.createMenuContributions(viewer);
if (items == null) {
- items = new IContributionItem[]{showAttributeItem};
+ items = new IContributionItem[]{showAttributeItem, sortItem};
}
else {
- IContributionItem[] combinedItems = new IContributionItem[items.length + 1];
+ IContributionItem[] combinedItems = new IContributionItem[items.length + 2];
System.arraycopy(items, 0, combinedItems, 0, items.length);
combinedItems[items.length] = showAttributeItem;
+ combinedItems[items.length+1] = sortItem;
items = combinedItems;
}
return items;
@@ -255,7 +352,7 @@
protected void enableShowAttributes(boolean showAttributes, TreeViewer treeViewer) {
// nothing by default
}
-
+
/*
* (non-Javadoc)
*
@@ -271,12 +368,13 @@
private Object getFilteredNode(Object object) {
if (object instanceof Node) {
Node node = (Node) object;
-
+ short nodeType = node.getNodeType();
// replace attribute node in selection with its parent
- if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+ if (nodeType == Node.ATTRIBUTE_NODE) {
node = ((Attr) node).getOwnerElement();
}
- else if (node.getNodeType() == Node.TEXT_NODE) {
+ // anything else not visible, replace with parent node
+ else if (nodeType == Node.TEXT_NODE) {
node = node.getParentNode();
}
return node;
@@ -317,5 +415,4 @@
}
return filteredSelection;
}
-
}