Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 0afc4007aacba70d2d9f8927d2f1e15875a3995d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
/**
 *
 */
package org.eclipse.papyrus.infra.core.sasheditor.editor;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.papyrus.infra.core.sasheditor.internal.SashWindowsContainer;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;

/**
 * This class allows to listen on events coming from all the active main Editors containing
 * a {@link SashWindowsContainer}. It send events when the active editor change and it contains
 * a {@link SashWindowsContainer}, and when the active page of one of the container has changed.
 *
 * <br>
 * This class allow to listen on following events:
 * <ul>
 * <li>pageChanged - a page has changed in the current container</li>
 * <li>containerChanged - the active editor has changed, and so the currently active container.</li>
 * </ul>
 *
 * This class require the current Eclipse page in order to listen on active editor changed.
 * This class connect itself to the Workbench editor changed event. Then, it ask the current editor for a ISashWindowsContainer (using getAdaptor() ).
 * If the editor return a ISashWindowsContainer,
 * this class listen to the pageChanged events. This class takes care to connect itself to the new ISashWindowsContainer when the editor changes.
 *
 * @TODO rename as SashWindowsEventsNotifier
 * @author cedric dumoulin
 *
 */
public class SashWindowsEventsProvider {

	/**
	 * List of listeners that will be notified when the current Sash Page has changed.
	 */
	private PageChangedListeners pageEventsManager = new PageChangedListeners();

	/**
	 * List of listeners that will be notified when the SashWindowsContainer has changed.
	 */
	private SashWindowsContainerChangedListeners containerEventsManager = new SashWindowsContainerChangedListeners();

	/**
	 * Workbench page to which this mngr listen for {@link IEditorPart} changes.
	 */
	private IWorkbenchPage workbenchPage;

	/**
	 * The last active editor read by a call to workbenchPage.getActiveEditor();
	 */
	private IEditorPart lastActiveEditor = null;

	/**
	 * Currently active SashContainer, or null if none is active.
	 */
	private ISashWindowsContainer currentContainer = null;

	/** Currently active page, or null if no container is active */
	private IPage activePage = null;


	private IPartListener workbenchPartListener = new IPartListener() {

		@Override
		public void partOpened(IWorkbenchPart part) {
			// System.out.println("partOpened("+ part +")");

		}

		@Override
		public void partDeactivated(IWorkbenchPart part) {
			// System.out.println("partDeactivated("+ part +")");
		}

		@Override
		public void partClosed(IWorkbenchPart part) {
			// System.out.println("("+ part +")");
		}

		@Override
		public void partBroughtToTop(IWorkbenchPart part) {
			// System.out.println("partClosed("+ part +")");
		}

		@Override
		public void partActivated(IWorkbenchPart part) {
			// System.out.println("partActivated(" + part + ") - activeEditor: " + workbenchPage.getActiveEditor());
			checkActiveEditorChange();
		}
	};

	/**
	 * Permanent listener on sash pageChanged event.
	 */
	private IPageChangedListener sashPageChangedListener = new IPageChangedListener() {

		@Override
		public void pageChanged(IPage newPage) {
			firePageChanged(newPage);
		}
	};

	/**
	 *
	 * Constructor.
	 * Page can be acquired with : <code>IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();</code>
	 */
	public SashWindowsEventsProvider(IWorkbenchPage page) {

		// Initialize activePave and current Sash Container.
		init(page);
		// Register changed event listeners
		registerEditorChangedListener();
		checkActiveEditorChange();
	}

	/**
	 * Initialize the first values.
	 *
	 * @param page
	 */
	private void init(IWorkbenchPage page) {
		if (page == null) {
			throw new IllegalArgumentException("page should not be null.");
		}

		workbenchPage = page;

		// Get the currently active container, if any.
		// ISashWindowsContainer newContainer = null;
		// IEditorPart editorPart = page.getActiveEditor();
		// if(editorPart != null) {
		// newContainer = (ISashWindowsContainer)editorPart.getAdapter(ISashWindowsContainer.class);
		// }

		// // Set SashContainer and ActivePage
		// currentContainer = newContainer;
		// if( currentContainer != null)
		// {
		// activePage = newContainer.getActiveSashWindowsPage();
		// System.err.println("activePage=" + activePage.getPageTitle()
		// + ", tab index=" + currentContainer.);
		// }
	}

	/**
	 * Return the currently active ISashWindowsContainer or null if none is actif.
	 *
	 * @return
	 */
	public ISashWindowsContainer activeSashWindowsContainer() {
		return currentContainer;
	}

	/**
	 * Return the currently active {@link IEditorPart} owning the currently active ISashWindowsContaineror.
	 * Return null if no container is actif.
	 *
	 * @return
	 */
	public IEditorPart activeSashWindowsContainerOwner() {
		if (currentContainer == null) {
			return null;
		}
		return workbenchPage.getActiveEditor();
	}

	/**
	 * Return the currently active page associated to the currently active Container.
	 * Return null if no container is actif.
	 *
	 * @return
	 */
	public IPage activeSashWindowsPage() {
		return activePage;
	}

	/**
	 * Check if the active editor has changed. If true, send appropriate event.
	 */
	private void checkActiveEditorChange() {
		// If the currently active editor has changed, send an event.
		IEditorPart editor = workbenchPage.getActiveEditor();
		if (editor != lastActiveEditor) {
			lastActiveEditor = editor;
			activeEditorChanged(editor);
		}
		lastActiveEditor = editor;
	}

	/**
	 * Dispose this manager. Cleanup listeners.
	 */
	public void dispose() {
		workbenchPage.removePartListener(workbenchPartListener);
	}

	/**
	 * Register a listener listeneing on editor change.
	 * Page can be acuired with :
	 * IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
	 */
	private void registerEditorChangedListener() {

		workbenchPage.addPartListener(workbenchPartListener);
	}

	/**
	 * This method is called when the active editor has change.
	 * The method checks the new editor and send appropriate events.
	 * The editor can be null.
	 *
	 * @param newEditor
	 *            The new editor of null if none is set.
	 */
	private void activeEditorChanged(IEditorPart newEditor) {

		// Editor has changed. It can be null.
		// Compute new container.
		ISashWindowsContainer newContainer = null;
		if (newEditor != null) {
			newContainer = (ISashWindowsContainer) newEditor.getAdapter(ISashWindowsContainer.class);
		}

		// Throw event if necessary
		if (newContainer != currentContainer) {
			activeContainerChanged(newContainer);
		}
	}

	/**
	 * This method is called when the active container has changed.
	 * The pageChangedListener is removed from the oldContainer, and attached to the newContainer.
	 *
	 * @param newContainer
	 */
	private void activeContainerChanged(ISashWindowsContainer newContainer) {
		// Detach listener from the old container
		if (currentContainer != null && !currentContainer.isDisposed()) {
			currentContainer.removePageChangedListener(sashPageChangedListener);
		}

		// record new container
		currentContainer = newContainer;

		// attach listener to new container
		if (currentContainer != null) {
			currentContainer.addPageChangedListener(sashPageChangedListener);
			firePageChanged(newContainer.getActiveSashWindowsPage());
		}

		// Fire events.
		fireContainerChanged(newContainer);
		IPage newPage = (newContainer != null ? newContainer.getActiveSashWindowsPage() : null);
		firePageChanged(newPage);
	}

	/**
	 * Send an event indicating a containerChanged.
	 * Propagate the event to all the listeners.
	 *
	 * @param activeEditor
	 */
	private void fireContainerChanged(ISashWindowsContainer newContainer) {
		// Propagate to all the listeners
		containerEventsManager.fireEvent(newContainer);
	}

	/**
	 * Send an event indicating a pageChanged.
	 * Propagate the event to all the listeners.
	 *
	 * @param activeEditor
	 */
	private void firePageChanged(IPage newPage) {

		activePage = newPage;
		// Propagate to all the listeners
		pageEventsManager.fireEvent(newPage);
	}

	/**
	 * Add a listener on pageChanged event.
	 *
	 * @param listener
	 */
	public void addPageChangedListener(IPageChangedListener listener) {
		pageEventsManager.addListener(listener);
	}

	/**
	 * Remove listener on pageChanged event.
	 *
	 * @param listener
	 */
	public void removePageChangedListener(IPageChangedListener listener) {
		pageEventsManager.removeListener(listener);
	}

	/**
	 * Add a listener on pageChanged event.
	 *
	 * @param listener
	 */
	public void addSashWindowsContainerChangedListener(ISashWindowsContainerChangedListener listener) {
		containerEventsManager.addListener(listener);
	}

	/**
	 * Remove listener on pageChanged event.
	 *
	 * @param listener
	 */
	public void removeSashWindowsContainerChangedListener(ISashWindowsContainerChangedListener listener) {
		containerEventsManager.removeListener(listener);
	}

	/**
	 *
	 * @author dumoulin
	 *
	 */
	private abstract class ListenersList<Listener, Event> {

		List<Listener> listeners;

		/**
		 * Add specified listener.
		 *
		 * @param listener
		 */
		public void addListener(Listener listener) {
			// Lazy creation
			if (listeners == null) {
				listeners = new ArrayList<Listener>();
			}

			// do not add if already present.
			if (listeners.contains(listener)) {
				return;
			}

			listeners.add(listener);
		}

		/**
		 * Remove specified listener.
		 *
		 * @param listener
		 */
		public void removeListener(Listener listener) {
			// Lazy creation
			if (listeners == null) {
				return;
			}

			listeners.remove(listener);
		}

		/**
		 * Fire the event on each listener
		 *
		 * @param event
		 */
		public void fireEvent(Event event) {
			// Lazy creation
			if (listeners == null) {
				return;
			}

			for (Listener listener : listeners) {
				propertyChanged(listener, event);
			}
		}

		/**
		 * Call the listener appropriate property.
		 *
		 * @param listener
		 * @param event
		 */
		public abstract void propertyChanged(Listener listener, Event event);
	}

	/**
	 * A list of {@link IPageChangedListener}.
	 *
	 * @author dumoulin
	 *
	 */
	public class PageChangedListeners extends ListenersList<IPageChangedListener, IPage> {

		/**
		 * Call the appropriate method on the listener.
		 *
		 * @see org.eclipse.papyrus.infra.core.sasheditor.editor.SashWindowsEventsProvider.ListenersList#propertyChanged(java.lang.Object, java.lang.Object)
		 * @param listener
		 * @param newPage
		 *
		 */
		@Override
		public void propertyChanged(IPageChangedListener listener, IPage newPage) {

			try {
				listener.pageChanged(newPage);
			} catch (Exception e) {
				// catch error in case a listener send an exception.
				// Still show the exception for debug purpose
				e.printStackTrace();
			}

		}

	}

	/**
	 * A list of {@link ISashWindowsContainerChangedListener} listening on container changed event.
	 *
	 * @author dumoulin
	 *
	 */
	public class SashWindowsContainerChangedListeners extends ListenersList<ISashWindowsContainerChangedListener, ISashWindowsContainer> {

		/**
		 * Call the appropriate method on the listener.
		 *
		 * @see org.eclipse.papyrus.infra.core.sasheditor.editor.SashWindowsEventsProvider.ListenersList#propertyChanged(java.lang.Object, java.lang.Object)
		 * @param listener
		 * @param newPage
		 *
		 */
		@Override
		public void propertyChanged(ISashWindowsContainerChangedListener listener, ISashWindowsContainer newContainer) {
			listener.sashWindowsContainerChanged(newContainer);

		}

	}

}

Back to the top