| /******************************************************************************* |
| * 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); |
| } |
| } |
| } |