X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/SelectionListenerWithASTManager.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/SelectionListenerWithASTManager.java new file mode 100644 index 0000000..279fc49 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/SelectionListenerWithASTManager.java @@ -0,0 +1,249 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 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 net.sourceforge.phpdt.internal.ui.viewsupport; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.text.ITextSelection; +//incastrix +//import org.eclipse.jface.util.ListenerList; +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.jface.viewers.IPostSelectionProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.ui.texteditor.ITextEditor; + +/** + * Infrastructure to share an AST for editor post selection listeners. + */ +public class SelectionListenerWithASTManager { + + private static SelectionListenerWithASTManager fgDefault; + + /** + * @return Returns the default manager instance. + */ + public static SelectionListenerWithASTManager getDefault() { + if (fgDefault == null) { + fgDefault = new SelectionListenerWithASTManager(); + } + return fgDefault; + } + + private final static class PartListenerGroup { + private ITextEditor fPart; + + private ISelectionChangedListener fSelectionListener, + fPostSelectionListener; + + private Job fCurrentJob; + + private ListenerList fAstListeners; + + /** + * Lock to avoid having more than one calculateAndInform job in + * parallel. Only jobs may synchronize on this as otherwise deadlocks + * are possible. + */ + private final Object fJobLock = new Object(); + + public PartListenerGroup(ITextEditor part) { + fPart = part; + fCurrentJob = null; + fAstListeners = new ListenerList(); + + fSelectionListener = new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + ISelection selection = event.getSelection(); + if (selection instanceof ITextSelection) { + fireSelectionChanged((ITextSelection) selection); + } + } + }; + + fPostSelectionListener = new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + ISelection selection = event.getSelection(); + if (selection instanceof ITextSelection) { + firePostSelectionChanged((ITextSelection) selection); + } + } + }; + } + + public boolean isEmpty() { + return fAstListeners.isEmpty(); + } + + public void install(ISelectionListenerWithAST listener) { + if (isEmpty()) { + ISelectionProvider selectionProvider = fPart + .getSelectionProvider(); + if (selectionProvider instanceof IPostSelectionProvider) { + ((IPostSelectionProvider) selectionProvider) + .addPostSelectionChangedListener(fPostSelectionListener); + selectionProvider + .addSelectionChangedListener(fSelectionListener); + } + } + fAstListeners.add(listener); + } + + public void uninstall(ISelectionListenerWithAST listener) { + fAstListeners.remove(listener); + if (isEmpty()) { + ISelectionProvider selectionProvider = fPart + .getSelectionProvider(); + if (selectionProvider instanceof IPostSelectionProvider) { + ((IPostSelectionProvider) selectionProvider) + .removePostSelectionChangedListener(fPostSelectionListener); + selectionProvider + .removeSelectionChangedListener(fSelectionListener); + } + } + } + + public void fireSelectionChanged(final ITextSelection selection) { + if (fCurrentJob != null) { + fCurrentJob.cancel(); + } + } + + public void firePostSelectionChanged(final ITextSelection selection) { + if (fCurrentJob != null) { + fCurrentJob.cancel(); + } + + fCurrentJob = new Job("SelectionListenerWithASTManager Job") {// JavaUIMessages.SelectionListenerWithASTManager_job_title) + // { + public IStatus run(IProgressMonitor monitor) { + if (monitor == null) { + monitor = new NullProgressMonitor(); + } + synchronized (fJobLock) { + return calculateASTandInform(/*input,*/ selection, monitor); + } + } + }; + fCurrentJob.setPriority(Job.DECORATE); + fCurrentJob.setSystem(true); + fCurrentJob.schedule(); + } + + protected IStatus calculateASTandInform(/*IJavaElement input,*/ + ITextSelection selection, IProgressMonitor monitor) { + if (monitor.isCanceled()) { + return Status.CANCEL_STATUS; + } + // create AST + try { + // CompilationUnit astRoot= + // PHPeclipsePlugin.getDefault().getASTProvider().getAST(input, + // ASTProvider.WAIT_ACTIVE_ONLY, monitor); + + // if (astRoot != null && !monitor.isCanceled()) { + Object[] listeners; + synchronized (PartListenerGroup.this) { + listeners = fAstListeners.getListeners(); + } + for (int i = 0; i < listeners.length; i++) { + ((ISelectionListenerWithAST) listeners[i]) + .selectionChanged(fPart, selection);// , astRoot); + if (monitor.isCanceled()) { + return Status.CANCEL_STATUS; + } + } + return Status.OK_STATUS; + // } + } catch (OperationCanceledException e) { + // thrown when cancelling the AST creation + } + return Status.CANCEL_STATUS; + } + } + + private Map fListenerGroups; + + private SelectionListenerWithASTManager() { + fListenerGroups = new HashMap(); + } + + /** + * Registers a selection listener for the given editor part. + * + * @param part + * The editor part to listen to. + * @param listener + * The listener to register. + */ + public void addListener(ITextEditor part, ISelectionListenerWithAST listener) { + synchronized (this) { + PartListenerGroup partListener = (PartListenerGroup) fListenerGroups + .get(part); + if (partListener == null) { + partListener = new PartListenerGroup(part); + fListenerGroups.put(part, partListener); + } + partListener.install(listener); + } + } + + /** + * Unregisters a selection listener. + * + * @param part + * The editor part the listener was registered. + * @param listener + * The listener to unregister. + */ + public void removeListener(ITextEditor part, + ISelectionListenerWithAST listener) { + synchronized (this) { + PartListenerGroup partListener = (PartListenerGroup) fListenerGroups + .get(part); + if (partListener != null) { + partListener.uninstall(listener); + if (partListener.isEmpty()) { + fListenerGroups.remove(part); + } + } + } + } + + /** + * Forces a selection changed event that is sent to all listeners registered + * to the given editor part. The event is sent from a background thread: + * this method call can return before the listeners are informed. + * + * @param part + * The editor part that has a changed selection + * @param selection + * The new text selection + */ + public void forceSelectionChange(ITextEditor part, ITextSelection selection) { + synchronized (this) { + PartListenerGroup partListener = (PartListenerGroup) fListenerGroups + .get(part); + if (partListener != null) { + partListener.firePostSelectionChanged(selection); + } + } + } +}