1 /*******************************************************************************
2 * Copyright (c) 2000, 2005 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.viewsupport;
13 import java.util.HashMap;
16 import org.eclipse.core.runtime.IProgressMonitor;
17 import org.eclipse.core.runtime.IStatus;
18 import org.eclipse.core.runtime.NullProgressMonitor;
19 import org.eclipse.core.runtime.OperationCanceledException;
20 import org.eclipse.core.runtime.Status;
21 import org.eclipse.core.runtime.jobs.Job;
22 import org.eclipse.jface.text.ITextSelection;
24 //import org.eclipse.jface.util.ListenerList;
25 import org.eclipse.core.runtime.ListenerList;
26 import org.eclipse.jface.viewers.IPostSelectionProvider;
27 import org.eclipse.jface.viewers.ISelection;
28 import org.eclipse.jface.viewers.ISelectionChangedListener;
29 import org.eclipse.jface.viewers.ISelectionProvider;
30 import org.eclipse.jface.viewers.SelectionChangedEvent;
31 import org.eclipse.ui.texteditor.ITextEditor;
34 * Infrastructure to share an AST for editor post selection listeners.
36 public class SelectionListenerWithASTManager {
38 private static SelectionListenerWithASTManager fgDefault;
41 * @return Returns the default manager instance.
43 public static SelectionListenerWithASTManager getDefault() {
44 if (fgDefault == null) {
45 fgDefault = new SelectionListenerWithASTManager();
50 private final static class PartListenerGroup {
51 private ITextEditor fPart;
53 private ISelectionChangedListener fSelectionListener,
54 fPostSelectionListener;
56 private Job fCurrentJob;
58 private ListenerList fAstListeners;
61 * Lock to avoid having more than one calculateAndInform job in
62 * parallel. Only jobs may synchronize on this as otherwise deadlocks
65 private final Object fJobLock = new Object();
67 public PartListenerGroup(ITextEditor part) {
70 fAstListeners = new ListenerList();
72 fSelectionListener = new ISelectionChangedListener() {
73 public void selectionChanged(SelectionChangedEvent event) {
74 ISelection selection = event.getSelection();
75 if (selection instanceof ITextSelection) {
76 fireSelectionChanged((ITextSelection) selection);
81 fPostSelectionListener = new ISelectionChangedListener() {
82 public void selectionChanged(SelectionChangedEvent event) {
83 ISelection selection = event.getSelection();
84 if (selection instanceof ITextSelection) {
85 firePostSelectionChanged((ITextSelection) selection);
91 public boolean isEmpty() {
92 return fAstListeners.isEmpty();
95 public void install(ISelectionListenerWithAST listener) {
97 ISelectionProvider selectionProvider = fPart
98 .getSelectionProvider();
99 if (selectionProvider instanceof IPostSelectionProvider) {
100 ((IPostSelectionProvider) selectionProvider)
101 .addPostSelectionChangedListener(fPostSelectionListener);
103 .addSelectionChangedListener(fSelectionListener);
106 fAstListeners.add(listener);
109 public void uninstall(ISelectionListenerWithAST listener) {
110 fAstListeners.remove(listener);
112 ISelectionProvider selectionProvider = fPart
113 .getSelectionProvider();
114 if (selectionProvider instanceof IPostSelectionProvider) {
115 ((IPostSelectionProvider) selectionProvider)
116 .removePostSelectionChangedListener(fPostSelectionListener);
118 .removeSelectionChangedListener(fSelectionListener);
123 public void fireSelectionChanged(final ITextSelection selection) {
124 if (fCurrentJob != null) {
125 fCurrentJob.cancel();
129 public void firePostSelectionChanged(final ITextSelection selection) {
130 if (fCurrentJob != null) {
131 fCurrentJob.cancel();
134 fCurrentJob = new Job("SelectionListenerWithASTManager Job") {// JavaUIMessages.SelectionListenerWithASTManager_job_title)
136 public IStatus run(IProgressMonitor monitor) {
137 if (monitor == null) {
138 monitor = new NullProgressMonitor();
140 synchronized (fJobLock) {
141 return calculateASTandInform(/*input,*/ selection, monitor);
145 fCurrentJob.setPriority(Job.DECORATE);
146 fCurrentJob.setSystem(true);
147 fCurrentJob.schedule();
150 protected IStatus calculateASTandInform(/*IJavaElement input,*/
151 ITextSelection selection, IProgressMonitor monitor) {
152 if (monitor.isCanceled()) {
153 return Status.CANCEL_STATUS;
157 // CompilationUnit astRoot=
158 // PHPeclipsePlugin.getDefault().getASTProvider().getAST(input,
159 // ASTProvider.WAIT_ACTIVE_ONLY, monitor);
161 // if (astRoot != null && !monitor.isCanceled()) {
163 synchronized (PartListenerGroup.this) {
164 listeners = fAstListeners.getListeners();
166 for (int i = 0; i < listeners.length; i++) {
167 ((ISelectionListenerWithAST) listeners[i])
168 .selectionChanged(fPart, selection);// , astRoot);
169 if (monitor.isCanceled()) {
170 return Status.CANCEL_STATUS;
173 return Status.OK_STATUS;
175 } catch (OperationCanceledException e) {
176 // thrown when cancelling the AST creation
178 return Status.CANCEL_STATUS;
182 private Map fListenerGroups;
184 private SelectionListenerWithASTManager() {
185 fListenerGroups = new HashMap();
189 * Registers a selection listener for the given editor part.
192 * The editor part to listen to.
194 * The listener to register.
196 public void addListener(ITextEditor part, ISelectionListenerWithAST listener) {
197 synchronized (this) {
198 PartListenerGroup partListener = (PartListenerGroup) fListenerGroups
200 if (partListener == null) {
201 partListener = new PartListenerGroup(part);
202 fListenerGroups.put(part, partListener);
204 partListener.install(listener);
209 * Unregisters a selection listener.
212 * The editor part the listener was registered.
214 * The listener to unregister.
216 public void removeListener(ITextEditor part,
217 ISelectionListenerWithAST listener) {
218 synchronized (this) {
219 PartListenerGroup partListener = (PartListenerGroup) fListenerGroups
221 if (partListener != null) {
222 partListener.uninstall(listener);
223 if (partListener.isEmpty()) {
224 fListenerGroups.remove(part);
231 * Forces a selection changed event that is sent to all listeners registered
232 * to the given editor part. The event is sent from a background thread:
233 * this method call can return before the listeners are informed.
236 * The editor part that has a changed selection
238 * The new text selection
240 public void forceSelectionChange(ITextEditor part, ITextSelection selection) {
241 synchronized (this) {
242 PartListenerGroup partListener = (PartListenerGroup) fListenerGroups
244 if (partListener != null) {
245 partListener.firePostSelectionChanged(selection);