/** * */ 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() { public void partOpened(IWorkbenchPart part) { // System.out.println("partOpened("+ part +")"); } public void partDeactivated(IWorkbenchPart part) { // System.out.println("partDeactivated("+ part +")"); } public void partClosed(IWorkbenchPart part) { // System.out.println("("+ part +")"); } public void partBroughtToTop(IWorkbenchPart part) { // System.out.println("partClosed("+ part +")"); } 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() { 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.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); } } }