Permalink
Browse files

Selection and expansion state working

  • Loading branch information...
1 parent 86f2037 commit cd8dbf0530779b1d98690b60172cfd389cf8ccdb @JanKoehnlein JanKoehnlein committed Sep 7, 2010
Showing with 303 additions and 143 deletions.
  1. +34 −0 plugins/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/DisplayRunHelper.java
  2. +2 −0 plugins/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/IOutlineNode.java
  3. +3 −2 plugins/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/IOutlineTreeProvider.java
  4. +104 −93 plugins/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/OutlinePage.java
  5. +99 −0 plugins/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/OutlineTreeState.java
  6. +16 −7 plugins/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/OutlineTreeViewer.java
  7. +4 −0 plugins/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/README.TXT
  8. +5 −4 plugins/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/impl/AbstractOutlineNode.java
  9. +22 −0 plugins/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/impl/ArtificialNode.java
  10. +6 −10 ...org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/impl/DefaultOutlineTreeProvider.java
  11. +2 −7 plugins/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/impl/DocumentNode.java
  12. +2 −9 plugins/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/impl/EObjectNode.java
  13. +1 −1 ...text/ui/editor/outline/impl/{SimpleOutlineContentProvider.java → OutlineNodeContentProvider.java}
  14. +1 −1 .../xtext/ui/editor/outline/impl/{InternalOutlineLabelProvider.java → OutlineNodeLabelProvider.java}
  15. +2 −9 plugins/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/impl/ResourceNode.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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
+ *******************************************************************************/
+package org.eclipse.xtext.ui.editor.outline;
+
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * @author koehnlein - Initial contribution and API
+ */
+public class DisplayRunHelper {
+
+ public static void runSyncInDisplayThread(Runnable runnable) {
+ if (Display.getCurrent() == null) {
+ // it is essential to have sync exec here as we're expecting a result
+ Display.getDefault().syncExec(runnable);
+ } else {
+ runnable.run();
+ }
+ }
+
+ public static void runAsyncInDisplayThread(Runnable runnable) {
+ if (Display.getCurrent() == null) {
+ // it is essential to have sync exec here as we're expecting a result
+ Display.getDefault().asyncExec(runnable);
+ } else {
+ runnable.run();
+ }
+ }
+}
@@ -32,6 +32,8 @@
boolean hasChildren();
+ boolean needsCreateChildren();
+
IXtextDocument getDocument();
}
@@ -14,13 +14,14 @@
import com.google.inject.ImplementedBy;
/**
- * Creates outline nodes.
+ * Creates outline nodes. Only called from within {@link org.eclipse.xtext.util.concurrent.IUnitOfWork}s where the
+ * {@link Resource} can be read safely.
*
* @author koehnlein - Initial contribution and API
*/
@ImplementedBy(DefaultOutlineTreeProvider.class)
public interface IOutlineTreeProvider {
-
+
void createChildren(IOutlineNode parent, Resource resource);
IOutlineNode createRoot(IXtextDocument document, Resource resource);
@@ -8,27 +8,26 @@
package org.eclipse.xtext.ui.editor.outline;
import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.editor.ISourceViewerAware;
import org.eclipse.xtext.ui.editor.model.IXtextDocument;
import org.eclipse.xtext.ui.editor.model.IXtextModelListener;
import org.eclipse.xtext.ui.editor.model.XtextDocumentUtil;
-import org.eclipse.xtext.ui.editor.outline.impl.InternalOutlineLabelProvider;
-import org.eclipse.xtext.ui.editor.outline.impl.SimpleOutlineContentProvider;
+import org.eclipse.xtext.ui.editor.outline.impl.OutlineNodeContentProvider;
+import org.eclipse.xtext.ui.editor.outline.impl.OutlineNodeLabelProvider;
import org.eclipse.xtext.ui.internal.Activator;
import org.eclipse.xtext.util.concurrent.IUnitOfWork;
@@ -39,20 +38,98 @@
/**
* @author koehnlein - Initial contribution and API
*/
-public class OutlinePage extends AbstractVirtualTreeContentOutlinePage implements ISourceViewerAware,
- IXtextModelListener {
+public class OutlinePage extends AbstractVirtualTreeContentOutlinePage implements ISourceViewerAware {
+
+ protected class RefreshJob extends Job {
+ private RefreshJob() {
+ super("Refreshing outline");
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ // System.out.println("Refreshing outline...");
+ OutlineTreeState formerState = new OutlineTreeState(getTreeViewer());
+ OutlineTreeState newState = new OutlineTreeState();
+ IOutlineNode rootNode = refreshOutlineModel(monitor, formerState, newState);
+ if (!monitor.isCanceled())
+ refreshViewer(rootNode, newState.getExpandedNodes(),
+ newState.getSelectedNodes());
+ // System.out.println("...done");
+ return Status.OK_STATUS;
+ } catch (Throwable t) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Error refreshing outline", t);
+ }
+ }
+
+ protected IOutlineNode refreshOutlineModel(final IProgressMonitor monitor,
+ final OutlineTreeState formerState, final OutlineTreeState newState) {
+ IOutlineNode rootNode = xtextDocument.readOnly(new IUnitOfWork<IOutlineNode, XtextResource>() {
+ public IOutlineNode exec(XtextResource resource) throws Exception {
+ IOutlineNode rootNode = treeProvider.createRoot(xtextDocument, resource);
+ List<IOutlineNode> createdNodes = Lists.newArrayList();
+ createdNodes.add(rootNode);
+ newState.addExpandedNode(rootNode);
+ for (IOutlineNode formerExpandedNode : formerState.getExpandedNodes()) {
+ if (monitor.isCanceled())
+ return null;
+ expandParentsAndNode(monitor, resource, formerExpandedNode, newState, createdNodes);
+ }
+ for (IOutlineNode formerSelectedNode: formerState.getSelectedNodes()) {
+ if (monitor.isCanceled())
+ return null;
+ IOutlineNode newSelectedNode = findEquivalentNode(formerSelectedNode, createdNodes);
+ if(newSelectedNode != null)
+ newState.addSelectedNode(newSelectedNode);
+ }
+ return rootNode;
+ }
+ });
+ return rootNode;
+ }
+
+ protected IOutlineNode findEquivalentNode(IOutlineNode formerNode, List<IOutlineNode> createdNodes) {
+ int index = createdNodes.indexOf(formerNode);
+ if (index != -1)
+ return createdNodes.get(index);
+ return null;
+ }
+
+ protected boolean expandParentsAndNode(IProgressMonitor monitor, Resource resource,
+ IOutlineNode formerExpandedNode, OutlineTreeState newState, List<IOutlineNode> createdNodes) {
+ if (monitor.isCanceled())
+ return false;
+ IOutlineNode parent = formerExpandedNode.getParent();
+ if (parent != null) {
+ if (!expandParentsAndNode(monitor, resource, parent, newState, createdNodes))
+ return false;
+ }
+ IOutlineNode newNode = findEquivalentNode(formerExpandedNode, createdNodes);
+ if (newNode != null) {
+ newState.addExpandedNode(newNode);
+ if (newNode.needsCreateChildren()) {
+ treeProvider.createChildren(newNode, resource);
+ createdNodes.addAll(newNode.getChildren());
+ }
+ return true;
+ }
+ return false;
+ }
+ }
private static final Logger LOG = Logger.getLogger(OutlinePage.class);
@Inject
- private InternalOutlineLabelProvider labelProvider;
+ private OutlineNodeLabelProvider labelProvider;
@Inject
- private SimpleOutlineContentProvider contentProvider;
+ private OutlineNodeContentProvider contentProvider;
@Inject
private IOutlineTreeProvider treeProvider;
+ private IXtextModelListener modelListener;
+
private IXtextDocument xtextDocument;
private Job refreshJob;
@@ -71,16 +148,28 @@ public void createControl(Composite parent) {
IOutlineNode rootNode = xtextDocument.readOnly(new IUnitOfWork<IOutlineNode, XtextResource>() {
public IOutlineNode exec(XtextResource resource) throws Exception {
IOutlineNode rootNode = treeProvider.createRoot(xtextDocument, resource);
+ treeProvider.createChildren(rootNode, resource);
return rootNode;
}
});
refreshViewer(rootNode, Collections.singletonList(rootNode), Collections.<IOutlineNode> emptyList());
- xtextDocument.addModelListener(this);
+ modelListener = new IXtextModelListener() {
+ public void modelChanged(XtextResource resource) {
+ try {
+ Job refreshJob = getRefreshJob();
+ refreshJob.cancel();
+ refreshJob.schedule();
+ } catch (Throwable t) {
+ LOG.error("Error refreshing outline", t);
+ }
+ }
+ };
+ xtextDocument.addModelListener(modelListener);
}
@Override
public void dispose() {
- xtextDocument.removeModelListener(this);
+ xtextDocument.removeModelListener(modelListener);
super.dispose();
}
@@ -91,74 +180,20 @@ public void setSourceViewer(ISourceViewer sourceViewer) {
protected synchronized Job getRefreshJob() {
if (refreshJob == null) {
- refreshJob = new Job("Refreshing outline") {
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- try {
- System.out.println("Refreshing outline...");
- List<IOutlineNode> expandedNodes = getExpandedNodes();
- IOutlineNode rootNode = refreshOutlineModel(monitor, expandedNodes);
- if (!monitor.isCanceled())
- refreshViewer(rootNode, expandedNodes, Collections.<IOutlineNode> emptyList());
- System.out.println("...done");
- return Status.OK_STATUS;
- } catch (Throwable t) {
- return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Error refreshing outline", t);
- }
- }
- };
+ refreshJob = new RefreshJob();
}
return refreshJob;
}
- protected IOutlineNode refreshOutlineModel(final IProgressMonitor monitor,
- final List<IOutlineNode> nodesToBeExpanded) {
- IOutlineNode rootNode = xtextDocument.readOnly(new IUnitOfWork<IOutlineNode, XtextResource>() {
- public IOutlineNode exec(XtextResource resource) throws Exception {
- IOutlineNode rootNode = treeProvider.createRoot(xtextDocument, resource);
- List<IOutlineNode> createdNodes = Lists.newArrayList();
- createdNodes.add(rootNode);
- if (rootNode.hasChildren()) {
- createdNodes.addAll(rootNode.getChildren());
- }
- for (Iterator<IOutlineNode> nodesToBeExpandedIter = nodesToBeExpanded.iterator();
- nodesToBeExpandedIter.hasNext(); ) {
- IOutlineNode nodeToBeExpanded = nodesToBeExpandedIter.next();
- if (monitor.isCanceled())
- return null;
- int index = createdNodes.indexOf(nodeToBeExpanded);
- if (index != -1) {
- IOutlineNode newNode = createdNodes.get(index);
- treeProvider.createChildren(newNode, resource);
- createdNodes.addAll(newNode.getChildren());
- } else {
- nodesToBeExpandedIter.remove();
- }
- }
- return rootNode;
- }
- });
- return rootNode;
- }
-
- public void modelChanged(XtextResource resource) {
- try {
- Job refreshJob = getRefreshJob();
- refreshJob.cancel();
- refreshJob.schedule();
- } catch (Throwable t) {
- LOG.error("Error refreshing outline", t);
- }
- }
-
- protected void refreshViewer(final IOutlineNode rootNode, final List<IOutlineNode> expandedNodes,
+ protected void refreshViewer(final IOutlineNode rootNode, final List<IOutlineNode> nodesToBeExpanded,
final List<IOutlineNode> selectedNodes) {
- runInSWTThread(new Runnable() {
+ DisplayRunHelper.runAsyncInDisplayThread(new Runnable() {
public void run() {
try {
TreeViewer treeViewer = getTreeViewer();
treeViewer.setInput(rootNode);
- treeViewer.setExpandedElements(Iterables.toArray(expandedNodes, IOutlineNode.class));
+ treeViewer.expandToLevel(1);
+ treeViewer.setExpandedElements(Iterables.toArray(nodesToBeExpanded, IOutlineNode.class));
treeViewer.setSelection(new StructuredSelection(selectedNodes));
} catch (Throwable t) {
LOG.error("Error refreshing outline", t);
@@ -167,28 +202,4 @@ public void run() {
});
}
- protected List<IOutlineNode> getExpandedNodes() {
- final List<IOutlineNode> expandedNodes = Lists.newArrayList();
- runInSWTThread(new Runnable() {
- public void run() {
- Object[] expandedElements = getTreeViewer().getExpandedElements();
- for (Object expandedElement : expandedElements) {
- if (!(expandedElement instanceof IOutlineNode))
- LOG.error("Content outline contains illegal node " + expandedElement);
- else
- expandedNodes.add((IOutlineNode) expandedElement);
- }
- }
- });
- return expandedNodes;
- }
-
- protected void runInSWTThread(Runnable runnable) {
- if (Display.getCurrent() == null) {
- Display.getDefault().asyncExec(runnable);
- } else {
- runnable.run();
- }
- }
-
}
Oops, something went wrong.

0 comments on commit cd8dbf0

Please sign in to comment.