001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal;
011:
012: import java.util.Hashtable;
013:
014: import org.eclipse.core.runtime.ListenerList;
015: import org.eclipse.jface.viewers.IPostSelectionProvider;
016: import org.eclipse.jface.viewers.ISelection;
017: import org.eclipse.jface.viewers.ISelectionChangedListener;
018: import org.eclipse.jface.viewers.ISelectionProvider;
019: import org.eclipse.jface.viewers.SelectionChangedEvent;
020: import org.eclipse.ui.INullSelectionListener;
021: import org.eclipse.ui.ISelectionListener;
022: import org.eclipse.ui.ISelectionService;
023: import org.eclipse.ui.IWorkbenchPart;
024:
025: /**
026: * Abstract selection service.
027: */
028: public abstract class AbstractSelectionService implements
029: ISelectionService {
030:
031: /**
032: * The list of selection listeners (not per-part).
033: */
034: private ListenerList listeners = new ListenerList();
035:
036: /**
037: * The list of post selection listeners (not per-part).
038: */
039: private ListenerList postListeners = new ListenerList();
040:
041: /**
042: * The currently active part.
043: */
044: private IWorkbenchPart activePart;
045:
046: /**
047: * The active part's selection provider, remembered in case the part
048: * replaces its selection provider after we hooked a listener.
049: */
050: private ISelectionProvider activeProvider;
051:
052: /**
053: * Map from part id (String) to per-part tracker (AbstractPartSelectionTracker).
054: */
055: private Hashtable perPartTrackers;
056:
057: /**
058: * The JFace selection listener to hook on the active part's selection provider.
059: */
060: private ISelectionChangedListener selListener = new ISelectionChangedListener() {
061: public void selectionChanged(SelectionChangedEvent event) {
062: fireSelection(activePart, event.getSelection());
063: }
064: };
065:
066: /**
067: * The JFace post selection listener to hook on the active part's selection provider.
068: */
069: private ISelectionChangedListener postSelListener = new ISelectionChangedListener() {
070: public void selectionChanged(SelectionChangedEvent event) {
071: firePostSelection(activePart, event.getSelection());
072: }
073: };
074:
075: /**
076: * Creates a new SelectionService.
077: */
078: protected AbstractSelectionService() {
079: }
080:
081: /* (non-Javadoc)
082: * Method declared on ISelectionService.
083: */
084: public void addSelectionListener(ISelectionListener l) {
085: listeners.add(l);
086: }
087:
088: /* (non-Javadoc)
089: * Method declared on ISelectionService.
090: */
091: public void addSelectionListener(String partId,
092: ISelectionListener listener) {
093: getPerPartTracker(partId).addSelectionListener(listener);
094: }
095:
096: /* (non-Javadoc)
097: * Method declared on ISelectionService.
098: */
099: public void addPostSelectionListener(ISelectionListener l) {
100: postListeners.add(l);
101: }
102:
103: /* (non-Javadoc)
104: * Method declared on ISelectionService.
105: */
106: public void addPostSelectionListener(String partId,
107: ISelectionListener listener) {
108: getPerPartTracker(partId).addPostSelectionListener(listener);
109: }
110:
111: /* (non-Javadoc)
112: * Method declared on ISelectionService.
113: */
114: public void removeSelectionListener(ISelectionListener l) {
115: listeners.remove(l);
116: }
117:
118: /*
119: * (non-Javadoc)
120: * Method declared on ISelectionListener.
121: */
122: public void removePostSelectionListener(String partId,
123: ISelectionListener listener) {
124: getPerPartTracker(partId).removePostSelectionListener(listener);
125: }
126:
127: /* (non-Javadoc)
128: * Method declared on ISelectionService.
129: */
130: public void removePostSelectionListener(ISelectionListener l) {
131: postListeners.remove(l);
132: }
133:
134: /*
135: * (non-Javadoc)
136: * Method declared on ISelectionListener.
137: */
138: public void removeSelectionListener(String partId,
139: ISelectionListener listener) {
140: getPerPartTracker(partId).removeSelectionListener(listener);
141: }
142:
143: /**
144: * Fires a selection event to the given listeners.
145: *
146: * @param part the part or <code>null</code> if no active part
147: * @param sel the selection or <code>null</code> if no active selection
148: */
149: protected void fireSelection(final IWorkbenchPart part,
150: final ISelection sel) {
151: Object[] array = listeners.getListeners();
152: for (int i = 0; i < array.length; i++) {
153: final ISelectionListener l = (ISelectionListener) array[i];
154: if ((part != null && sel != null)
155: || l instanceof INullSelectionListener) {
156:
157: try {
158: l.selectionChanged(part, sel);
159: } catch (Exception e) {
160: WorkbenchPlugin.log(e);
161: }
162: }
163: }
164: }
165:
166: /**
167: * Fires a selection event to the given listeners.
168: *
169: * @param part the part or <code>null</code> if no active part
170: * @param sel the selection or <code>null</code> if no active selection
171: */
172: protected void firePostSelection(final IWorkbenchPart part,
173: final ISelection sel) {
174: Object[] array = postListeners.getListeners();
175: for (int i = 0; i < array.length; i++) {
176: final ISelectionListener l = (ISelectionListener) array[i];
177: if ((part != null && sel != null)
178: || l instanceof INullSelectionListener) {
179:
180: try {
181: l.selectionChanged(part, sel);
182: } catch (Exception e) {
183: WorkbenchPlugin.log(e);
184: }
185: }
186: }
187: }
188:
189: /**
190: * Returns the per-part selection tracker for the given part id.
191: *
192: * @param partId part identifier
193: * @return per-part selection tracker
194: */
195: protected AbstractPartSelectionTracker getPerPartTracker(
196: String partId) {
197: if (perPartTrackers == null) {
198: perPartTrackers = new Hashtable(4);
199: }
200: AbstractPartSelectionTracker tracker = (AbstractPartSelectionTracker) perPartTrackers
201: .get(partId);
202: if (tracker == null) {
203: tracker = createPartTracker(partId);
204: perPartTrackers.put(partId, tracker);
205: }
206: return tracker;
207: }
208:
209: /**
210: * Creates a new per-part selection tracker for the given part id.
211: *
212: * @param partId part identifier
213: * @return per-part selection tracker
214: */
215: protected abstract AbstractPartSelectionTracker createPartTracker(
216: String partId);
217:
218: /**
219: * Returns the selection.
220: */
221: public ISelection getSelection() {
222: if (activeProvider != null) {
223: return activeProvider.getSelection();
224: } else {
225: return null;
226: }
227: }
228:
229: /*
230: * @see ISelectionService#getSelection(String)
231: */
232: public ISelection getSelection(String partId) {
233: return getPerPartTracker(partId).getSelection();
234: }
235:
236: /**
237: * Sets the current-active part (or null if none)
238: *
239: * @since 3.1
240: *
241: * @param newPart the new active part (or null if none)
242: */
243: public void setActivePart(IWorkbenchPart newPart) {
244: // Optimize.
245: if (newPart == activePart) {
246: return;
247: }
248:
249: ISelectionProvider selectionProvider = null;
250:
251: if (newPart != null) {
252: selectionProvider = newPart.getSite()
253: .getSelectionProvider();
254:
255: if (selectionProvider == null) {
256: newPart = null;
257: }
258: }
259:
260: if (newPart == activePart) {
261: return;
262: }
263:
264: if (activePart != null) {
265: if (activeProvider != null) {
266: activeProvider
267: .removeSelectionChangedListener(selListener);
268: if (activeProvider instanceof IPostSelectionProvider) {
269: ((IPostSelectionProvider) activeProvider)
270: .removePostSelectionChangedListener(postSelListener);
271: } else {
272: activeProvider
273: .removeSelectionChangedListener(postSelListener);
274: }
275: activeProvider = null;
276: }
277: activePart = null;
278: }
279:
280: activePart = newPart;
281:
282: if (newPart != null) {
283: activeProvider = selectionProvider;
284: // Fire an event if there's an active provider
285: activeProvider.addSelectionChangedListener(selListener);
286: ISelection sel = activeProvider.getSelection();
287: fireSelection(newPart, sel);
288: if (activeProvider instanceof IPostSelectionProvider) {
289: ((IPostSelectionProvider) activeProvider)
290: .addPostSelectionChangedListener(postSelListener);
291: } else {
292: activeProvider
293: .addSelectionChangedListener(postSelListener);
294: }
295: firePostSelection(newPart, sel);
296: } else {
297: fireSelection(null, null);
298: firePostSelection(null, null);
299: }
300: }
301:
302: // /**
303: // * Notifies the listener that a part has been activated.
304: // */
305: // public void partActivated(IWorkbenchPart newPart) {
306: // // Optimize.
307: // if (newPart == activePart)
308: // return;
309: //
310: // // Unhook selection from the old part.
311: // reset();
312: //
313: // // Update active part.
314: // activePart = newPart;
315: //
316: // // Hook selection on the new part.
317: // if (activePart != null) {
318: // activeProvider = activePart.getSite().getSelectionProvider();
319: // if (activeProvider != null) {
320: // // Fire an event if there's an active provider
321: // activeProvider.addSelectionChangedListener(selListener);
322: // ISelection sel = activeProvider.getSelection();
323: // fireSelection(newPart, sel);
324: // if (activeProvider instanceof IPostSelectionProvider)
325: // ((IPostSelectionProvider) activeProvider)
326: // .addPostSelectionChangedListener(postSelListener);
327: // else
328: // activeProvider.addSelectionChangedListener(postSelListener);
329: // firePostSelection(newPart, sel);
330: // } else {
331: // //Reset active part. activeProvider may not be null next time this method is called.
332: // activePart = null;
333: // }
334: // }
335: // // No need to fire an event if no active provider, since this was done in reset()
336: // }
337: //
338: // /**
339: // * Notifies the listener that a part has been brought to the front.
340: // */
341: // public void partBroughtToTop(IWorkbenchPart newPart) {
342: // // do nothing, the active part has not changed,
343: // // so the selection is unaffected
344: // }
345: //
346: // /**
347: // * Notifies the listener that a part has been closed
348: // */
349: // public void partClosed(IWorkbenchPart part) {
350: // // Unhook selection from the part.
351: // if (part == activePart) {
352: // reset();
353: // }
354: // }
355: //
356: // /**
357: // * Notifies the listener that a part has been deactivated.
358: // */
359: // public void partDeactivated(IWorkbenchPart part) {
360: // // Unhook selection from the part.
361: // if (part == activePart) {
362: // reset();
363: // }
364: // }
365: //
366: // /**
367: // * Notifies the listener that a part has been opened.
368: // */
369: // public void partOpened(IWorkbenchPart part) {
370: // // Wait for activation.
371: // }
372: //
373: // /**
374: // * Notifies the listener that a part has been opened.
375: // */
376: // public void partInputChanged(IWorkbenchPart part) {
377: // // 36501 - only process if part is active
378: // if (activePart == part) {
379: // reset();
380: // partActivated(part);
381: // }
382: // }
383: //
384: // /**
385: // * Resets the service. The active part and selection provider are
386: // * dereferenced.
387: // */
388: // public void reset() {
389: // if (activePart != null) {
390: // fireSelection(null, null);
391: // firePostSelection(null, null);
392: // if (activeProvider != null) {
393: // activeProvider.removeSelectionChangedListener(selListener);
394: // if (activeProvider instanceof IPostSelectionProvider)
395: // ((IPostSelectionProvider) activeProvider)
396: // .removePostSelectionChangedListener(postSelListener);
397: // else
398: // activeProvider
399: // .removeSelectionChangedListener(postSelListener);
400: // activeProvider = null;
401: // }
402: // activePart = null;
403: // }
404: // }
405:
406: }
|