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;
23 import org.eclipse.jface.util.ListenerList;
24 import org.eclipse.jface.viewers.IPostSelectionProvider;
25 import org.eclipse.jface.viewers.ISelection;
26 import org.eclipse.jface.viewers.ISelectionChangedListener;
27 import org.eclipse.jface.viewers.ISelectionProvider;
28 import org.eclipse.jface.viewers.SelectionChangedEvent;
29 import org.eclipse.ui.texteditor.ITextEditor;
32 * Infrastructure to share an AST for editor post selection listeners.
34 public class SelectionListenerWithASTManager {
36 private static SelectionListenerWithASTManager fgDefault;
39 * @return Returns the default manager instance.
41 public static SelectionListenerWithASTManager getDefault() {
42 if (fgDefault == null) {
43 fgDefault = new SelectionListenerWithASTManager();
48 private final static class PartListenerGroup {
49 private ITextEditor fPart;
51 private ISelectionChangedListener fSelectionListener,
52 fPostSelectionListener;
54 private Job fCurrentJob;
56 private ListenerList fAstListeners;
59 * Lock to avoid having more than one calculateAndInform job in
60 * parallel. Only jobs may synchronize on this as otherwise deadlocks
63 private final Object fJobLock = new Object();
65 public PartListenerGroup(ITextEditor part) {
68 fAstListeners = new ListenerList();
70 fSelectionListener = new ISelectionChangedListener() {
71 public void selectionChanged(SelectionChangedEvent event) {
72 ISelection selection = event.getSelection();
73 if (selection instanceof ITextSelection) {
74 fireSelectionChanged((ITextSelection) selection);
79 fPostSelectionListener = new ISelectionChangedListener() {
80 public void selectionChanged(SelectionChangedEvent event) {
81 ISelection selection = event.getSelection();
82 if (selection instanceof ITextSelection) {
83 firePostSelectionChanged((ITextSelection) selection);
89 public boolean isEmpty() {
90 return fAstListeners.isEmpty();
93 public void install(ISelectionListenerWithAST listener) {
95 ISelectionProvider selectionProvider = fPart
96 .getSelectionProvider();
97 if (selectionProvider instanceof IPostSelectionProvider) {
98 ((IPostSelectionProvider) selectionProvider)
99 .addPostSelectionChangedListener(fPostSelectionListener);
101 .addSelectionChangedListener(fSelectionListener);
104 fAstListeners.add(listener);
107 public void uninstall(ISelectionListenerWithAST listener) {
108 fAstListeners.remove(listener);
110 ISelectionProvider selectionProvider = fPart
111 .getSelectionProvider();
112 if (selectionProvider instanceof IPostSelectionProvider) {
113 ((IPostSelectionProvider) selectionProvider)
114 .removePostSelectionChangedListener(fPostSelectionListener);
116 .removeSelectionChangedListener(fSelectionListener);
121 public void fireSelectionChanged(final ITextSelection selection) {
122 if (fCurrentJob != null) {
123 fCurrentJob.cancel();
127 public void firePostSelectionChanged(final ITextSelection selection) {
128 if (fCurrentJob != null) {
129 fCurrentJob.cancel();
132 fCurrentJob = new Job("SelectionListenerWithASTManager Job") {// JavaUIMessages.SelectionListenerWithASTManager_job_title)
134 public IStatus run(IProgressMonitor monitor) {
135 if (monitor == null) {
136 monitor = new NullProgressMonitor();
138 synchronized (fJobLock) {
139 return calculateASTandInform(/*input,*/ selection, monitor);
143 fCurrentJob.setPriority(Job.DECORATE);
144 fCurrentJob.setSystem(true);
145 fCurrentJob.schedule();
148 protected IStatus calculateASTandInform(/*IJavaElement input,*/
149 ITextSelection selection, IProgressMonitor monitor) {
150 if (monitor.isCanceled()) {
151 return Status.CANCEL_STATUS;
155 // CompilationUnit astRoot=
156 // PHPeclipsePlugin.getDefault().getASTProvider().getAST(input,
157 // ASTProvider.WAIT_ACTIVE_ONLY, monitor);
159 // if (astRoot != null && !monitor.isCanceled()) {
161 synchronized (PartListenerGroup.this) {
162 listeners = fAstListeners.getListeners();
164 for (int i = 0; i < listeners.length; i++) {
165 ((ISelectionListenerWithAST) listeners[i])
166 .selectionChanged(fPart, selection);// , astRoot);
167 if (monitor.isCanceled()) {
168 return Status.CANCEL_STATUS;
171 return Status.OK_STATUS;
173 } catch (OperationCanceledException e) {
174 // thrown when cancelling the AST creation
176 return Status.CANCEL_STATUS;
180 private Map fListenerGroups;
182 private SelectionListenerWithASTManager() {
183 fListenerGroups = new HashMap();
187 * Registers a selection listener for the given editor part.
190 * The editor part to listen to.
192 * The listener to register.
194 public void addListener(ITextEditor part, ISelectionListenerWithAST listener) {
195 synchronized (this) {
196 PartListenerGroup partListener = (PartListenerGroup) fListenerGroups
198 if (partListener == null) {
199 partListener = new PartListenerGroup(part);
200 fListenerGroups.put(part, partListener);
202 partListener.install(listener);
207 * Unregisters a selection listener.
210 * The editor part the listener was registered.
212 * The listener to unregister.
214 public void removeListener(ITextEditor part,
215 ISelectionListenerWithAST listener) {
216 synchronized (this) {
217 PartListenerGroup partListener = (PartListenerGroup) fListenerGroups
219 if (partListener != null) {
220 partListener.uninstall(listener);
221 if (partListener.isEmpty()) {
222 fListenerGroups.remove(part);
229 * Forces a selection changed event that is sent to all listeners registered
230 * to the given editor part. The event is sent from a background thread:
231 * this method call can return before the listeners are informed.
234 * The editor part that has a changed selection
236 * The new text selection
238 public void forceSelectionChange(ITextEditor part, ITextSelection selection) {
239 synchronized (this) {
240 PartListenerGroup partListener = (PartListenerGroup) fListenerGroups
242 if (partListener != null) {
243 partListener.firePostSelectionChanged(selection);