Skip to main content

This CGIT instance is deprecated, and repositories have been moved to Gitlab or Github. See the repository descriptions for specific locations.

summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bundles/org.eclipse.wst.xsd.ui/src-adt-xsd/org/eclipse/wst/xsd/ui/internal/text/XSDModelDelayedReconciler.java195
-rw-r--r--bundles/org.eclipse.wst.xsd.ui/src-adt-xsd/org/eclipse/wst/xsd/ui/internal/text/XSDModelReconcileAdapter.java18
-rw-r--r--bundles/org.eclipse.wst.xsd.ui/src-adt/org/eclipse/wst/xsd/ui/internal/adt/outline/ADTContentOutlineProvider.java24
-rw-r--r--bundles/org.eclipse.wst.xsd.ui/src-adt/org/eclipse/wst/xsd/ui/internal/adt/outline/ADTContentOutlineRefreshJob.java143
4 files changed, 365 insertions, 15 deletions
diff --git a/bundles/org.eclipse.wst.xsd.ui/src-adt-xsd/org/eclipse/wst/xsd/ui/internal/text/XSDModelDelayedReconciler.java b/bundles/org.eclipse.wst.xsd.ui/src-adt-xsd/org/eclipse/wst/xsd/ui/internal/text/XSDModelDelayedReconciler.java
new file mode 100644
index 0000000000..02b7b6d76b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.ui/src-adt-xsd/org/eclipse/wst/xsd/ui/internal/text/XSDModelDelayedReconciler.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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
+ *******************************************************************************/
+package org.eclipse.wst.xsd.ui.internal.text;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+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.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.progress.UIJob;
+import org.eclipse.wst.xsd.ui.internal.editor.InternalXSDMultiPageEditor;
+import org.eclipse.xsd.XSDConcreteComponent;
+import org.eclipse.xsd.XSDSchema;
+import org.w3c.dom.Element;
+
+
+/**
+ * Provides delayed reconciliation between the SSE DOM and the XSD EMF model.
+ * Changes in the DOM are queued and processed by a UI job. When a new request
+ * comes in, the current run is cancelled, the new request is added to the queue,
+ * then the job is re-scheduled.
+ */
+public class XSDModelDelayedReconciler
+{
+ /**
+ * The model reconciler job.
+ */
+ private ReconcilerJob reconcilerJob;
+
+ /**
+ * The time in milliseconds to delay updating the EMF model.
+ */
+ private static final int DELAY = 300;
+
+ /**
+ * The elements to reconcile.
+ */
+ private List elementsToReconcile = new ArrayList();
+
+ /**
+ * Determines if the delayed reconciler should kick in.
+ */
+ public boolean shouldDelay(XSDSchema schema)
+ {
+ boolean shouldDelay = false;
+
+ // The delayed reconciler should not be used when the editor is in graphical editing mode.
+
+ IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPage workbenchPage = workbenchWindow.getActivePage();
+ IEditorPart editorPart = workbenchPage != null ? workbenchPage.getActiveEditor() : null;
+ if (editorPart != null && editorPart instanceof InternalXSDMultiPageEditor)
+ {
+ InternalXSDMultiPageEditor xsdEditor = (InternalXSDMultiPageEditor)editorPart;
+ shouldDelay = xsdEditor.isSourcePageActive();
+ }
+
+ return shouldDelay;
+ }
+
+ /**
+ * Updates the XSD EMF component corresponding to the DOM element.
+ *
+ * @param element the changed element.
+ * @param schema the containing schema.
+ */
+ public void elementChanged(Element element, XSDSchema schema)
+ {
+ synchronized (elementsToReconcile)
+ {
+ // The number of elements should be small so a linear search should be fine.
+
+ if (!elementsToReconcile.contains(element))
+ {
+ elementsToReconcile.add(element);
+ }
+
+ if (reconcilerJob == null)
+ {
+ reconcilerJob = new ReconcilerJob(schema);
+ }
+
+ reconcilerJob.schedule(DELAY);
+ }
+ }
+
+ /**
+ * A UI job used to reconcile the XSD EMF model with the associated SSE DOM.
+ */
+ class ReconcilerJob extends UIJob
+ {
+ /**
+ * The target schema.
+ */
+ private XSDSchema schema;
+
+ /**
+ * The number of times allowed to wake up and do nothing.
+ */
+ private static final int MAX_INACTIVE_COUNT = 10;
+
+ /**
+ * The job will terminate once this counter reaches MAX_INACTIVE_COUNT.
+ */
+ private int timesAwakeAndIdle = 0;
+
+ /**
+ * Constructs the reconciler job and configures some of its properties.
+ */
+ public ReconcilerJob(XSDSchema schema)
+ {
+ super("Reconciling the XSD EMF model"); //$NON-NLS-1$
+ setSystem(true);
+ setPriority(Job.LONG);
+ this.schema = schema;
+ }
+
+ public IStatus runInUIThread(IProgressMonitor monitor)
+ {
+ if (monitor.isCanceled())
+ {
+ return Status.CANCEL_STATUS;
+ }
+
+ Element[] elements = null;
+
+ synchronized (elementsToReconcile)
+ {
+ if (!elementsToReconcile.isEmpty())
+ {
+ elements = new Element[elementsToReconcile.size()];
+ elementsToReconcile.toArray(elements);
+ elementsToReconcile.clear();
+ }
+ else
+ {
+ if (shouldTerminate())
+ {
+ reconcilerJob = null;
+ return Status.CANCEL_STATUS;
+ }
+ }
+ }
+
+ reconcile(elements);
+
+ schedule(DELAY);
+
+ return Status.OK_STATUS;
+ }
+
+ private void reconcile(Element[] modifiedElements)
+ {
+ if (modifiedElements != null)
+ {
+ for (int index = 0; index < modifiedElements.length; index++)
+ {
+ Element modifiedElement = modifiedElements[index];
+
+ reconcile(modifiedElement);
+ }
+ }
+ }
+
+ private void reconcile(Element modifiedElement)
+ {
+ if (modifiedElement != null)
+ {
+ XSDConcreteComponent concreteComponent = schema.getCorrespondingComponent(modifiedElement);
+ concreteComponent.elementChanged(modifiedElement);
+ }
+ }
+
+ private boolean shouldTerminate()
+ {
+ return timesAwakeAndIdle++ == MAX_INACTIVE_COUNT;
+ }
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xsd.ui/src-adt-xsd/org/eclipse/wst/xsd/ui/internal/text/XSDModelReconcileAdapter.java b/bundles/org.eclipse.wst.xsd.ui/src-adt-xsd/org/eclipse/wst/xsd/ui/internal/text/XSDModelReconcileAdapter.java
index 80a6db576b..44b0626f8b 100644
--- a/bundles/org.eclipse.wst.xsd.ui/src-adt-xsd/org/eclipse/wst/xsd/ui/internal/text/XSDModelReconcileAdapter.java
+++ b/bundles/org.eclipse.wst.xsd.ui/src-adt-xsd/org/eclipse/wst/xsd/ui/internal/text/XSDModelReconcileAdapter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 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
@@ -24,11 +24,13 @@ import org.w3c.dom.Node;
public class XSDModelReconcileAdapter extends ModelReconcileAdapter
{
protected XSDSchema schema;
+ protected XSDModelDelayedReconciler delayedReconciler;
public XSDModelReconcileAdapter(Document document, XSDSchema schema)
{
super(document);
this.schema = schema;
+ this.delayedReconciler = new XSDModelDelayedReconciler();
}
protected void handleNodeChanged(Node node)
@@ -50,9 +52,17 @@ public class XSDModelReconcileAdapter extends ModelReconcileAdapter
if (node instanceof Element)
{
- XSDConcreteComponent concreteComponent = schema.getCorrespondingComponent(node);
- concreteComponent.elementChanged((Element)node);
- }
+ Element element = (Element) node;
+ if (delayedReconciler.shouldDelay(schema))
+ {
+ delayedReconciler.elementChanged(element, schema);
+ }
+ else
+ {
+ XSDConcreteComponent concreteComponent = schema.getCorrespondingComponent(node);
+ concreteComponent.elementChanged(element);
+ }
+ }
else if (node instanceof Document)
{
// The document changed so we may need to fix up the
diff --git a/bundles/org.eclipse.wst.xsd.ui/src-adt/org/eclipse/wst/xsd/ui/internal/adt/outline/ADTContentOutlineProvider.java b/bundles/org.eclipse.wst.xsd.ui/src-adt/org/eclipse/wst/xsd/ui/internal/adt/outline/ADTContentOutlineProvider.java
index e425871f41..ac6e76f24e 100644
--- a/bundles/org.eclipse.wst.xsd.ui/src-adt/org/eclipse/wst/xsd/ui/internal/adt/outline/ADTContentOutlineProvider.java
+++ b/bundles/org.eclipse.wst.xsd.ui/src-adt/org/eclipse/wst/xsd/ui/internal/adt/outline/ADTContentOutlineProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2001, 2008 IBM Corporation and others.
+ * Copyright (c) 2001, 2009 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
@@ -11,7 +11,6 @@
package org.eclipse.wst.xsd.ui.internal.adt.outline;
import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.wst.xsd.ui.internal.adt.facade.IADTObject;
import org.eclipse.wst.xsd.ui.internal.adt.facade.IADTObjectListener;
@@ -20,6 +19,7 @@ public class ADTContentOutlineProvider implements ITreeContentProvider, IADTObje
{
protected Viewer viewer = null;
protected Object oldInput, newInput;
+ protected ADTContentOutlineRefreshJob refreshJob;
public ADTContentOutlineProvider()
{
@@ -89,6 +89,11 @@ public class ADTContentOutlineProvider implements ITreeContentProvider, IADTObje
{
removeListener((IADTObject) input);
}
+ if (refreshJob != null)
+ {
+ refreshJob.cancel();
+ refreshJob = null;
+ }
}
/* (non-Javadoc)
@@ -99,6 +104,11 @@ public class ADTContentOutlineProvider implements ITreeContentProvider, IADTObje
this.viewer = viewer;
this.oldInput = oldInput;
this.newInput = newInput;
+ if (refreshJob != null)
+ {
+ refreshJob.cancel();
+ }
+ refreshJob = new ADTContentOutlineRefreshJob(viewer);
}
/* (non-Javadoc)
@@ -106,15 +116,7 @@ public class ADTContentOutlineProvider implements ITreeContentProvider, IADTObje
*/
public void propertyChanged(Object object, String property)
{
- if (viewer instanceof TreeViewer)
- {
- TreeViewer treeViewer = (TreeViewer) viewer;
- if (treeViewer.getTree() != null && !treeViewer.getTree().isDisposed())
- {
- treeViewer.refresh(object);
- treeViewer.reveal(object);
- }
- }
+ refreshJob.refresh((IADTObject)object);
}
/**
diff --git a/bundles/org.eclipse.wst.xsd.ui/src-adt/org/eclipse/wst/xsd/ui/internal/adt/outline/ADTContentOutlineRefreshJob.java b/bundles/org.eclipse.wst.xsd.ui/src-adt/org/eclipse/wst/xsd/ui/internal/adt/outline/ADTContentOutlineRefreshJob.java
new file mode 100644
index 0000000000..bf04cf473a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.ui/src-adt/org/eclipse/wst/xsd/ui/internal/adt/outline/ADTContentOutlineRefreshJob.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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
+ *******************************************************************************/
+package org.eclipse.wst.xsd.ui.internal.adt.outline;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.xsd.ui.internal.adapters.CategoryAdapter;
+import org.eclipse.wst.xsd.ui.internal.adt.facade.IADTObject;
+
+
+/**
+ * This job holds a queue of updates (affected nodes) for the XSD editor's
+ * outline view. When a new request comes in, the current run is cancelled,
+ * the new request is added to the queue, then the job is re-scheduled.
+ * This class is loosely based on RefreshStructureJob.
+ */
+class ADTContentOutlineRefreshJob extends Job
+{
+ /**
+ * The delay time in milliseconds.
+ */
+ private static final long UPDATE_DELAY = 300;
+
+ private final List nodesToRefresh = new ArrayList(5);
+
+ private final TreeViewer viewer;
+
+ public ADTContentOutlineRefreshJob(Viewer viewer)
+ {
+ super("Refreshing XSD outline"); //$NON-NLS-1$
+ setPriority(Job.LONG);
+ setSystem(true);
+ this.viewer = (TreeViewer)viewer;
+ }
+
+ private synchronized void addRefreshRequest(IADTObject adtObject)
+ {
+ if (nodesToRefresh.contains(adtObject))
+ {
+ return;
+ }
+
+ nodesToRefresh.add(adtObject);
+ }
+
+ protected void canceling()
+ {
+ nodesToRefresh.clear();
+ super.canceling();
+ }
+
+ private void doRefresh(final IADTObject adtObject)
+ {
+ final Display display = PlatformUI.getWorkbench().getDisplay();
+ display.asyncExec(new Runnable()
+ {
+ public void run()
+ {
+ boolean isValidViewer = viewer != null && !viewer.getControl().isDisposed();
+ if (isValidViewer)
+ {
+ viewer.refresh(adtObject);
+
+ // Needlessly revealing the category nodes causes a lot of UI flicker.
+
+ if (!(adtObject instanceof CategoryAdapter))
+ {
+ viewer.reveal(adtObject);
+ }
+ }
+ }
+ });
+ }
+
+ private synchronized IADTObject[] getNodesToRefresh()
+ {
+ IADTObject[] toRefresh = new IADTObject [nodesToRefresh.size()];
+ nodesToRefresh.toArray(toRefresh);
+ nodesToRefresh.clear();
+
+ return toRefresh;
+ }
+
+ public void refresh(IADTObject adtObject)
+ {
+ if (adtObject == null)
+ {
+ return;
+ }
+
+ addRefreshRequest(adtObject);
+
+ schedule(UPDATE_DELAY);
+ }
+
+ protected IStatus run(IProgressMonitor monitor)
+ {
+ IStatus status = Status.OK_STATUS;
+ try
+ {
+ performRefreshes(monitor);
+ }
+ finally
+ {
+ monitor.done();
+ }
+ return status;
+ }
+
+ private void performRefreshes(IProgressMonitor monitor)
+ {
+ IADTObject[] nodes = getNodesToRefresh();
+
+ for (int index = 0; index < nodes.length; index++)
+ {
+ if (monitor.isCanceled())
+ {
+ throw new OperationCanceledException();
+ }
+ IADTObject node = nodes[index];
+ doRefresh(node);
+ }
+ }
+} \ No newline at end of file

Back to the top