/*****************************************************************************
* Copyright (c) 2009 CEA LIST & LIFL
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.infra.core.sasheditor.internal;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.papyrus.infra.core.sasheditor.editor.actionbarcontributor.IMultiPageEditorActionBarContributor;
import org.eclipse.papyrus.infra.core.sasheditor.internal.ActivePageTracker.IActiveEditorChangedListener;
import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.MultiPageSelectionProvider;
import org.eclipse.ui.IEditorActionBarContributor;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IKeyBindingService;
import org.eclipse.ui.INestableKeyBindingService;
import org.eclipse.ui.IPartService;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.services.INestable;
import org.eclipse.ui.part.MultiPageEditorActionBarContributor;
import org.eclipse.ui.services.IServiceLocator;
/**
* This class is used to switch the services of a nested editor when the active nested editor change.
* This class is a {@link IActiveEditorChangedListener} registered to the {@link ActivePageTracker}
* by the {@link SashWindowsContainer}.
*
* When a new Editor is set active, by calling {@link #setActiveEditor(PagePart)}, following actions are
* performed:
* <ul>
* <li>deactivate services: nested site and keybinding</li>
* <li>An event is sent to the ActionBarContributor if it accept it (by implementing {@link IMultiPageEditorActionBarContributor})</li>
* <li>Send {@link SelectionChangedEvent} to the main editor. The event contains the current selection of the new active editor.</li>
* <li>Connect the keybinding service to the new Editor.</li>
* </ul>
*
*
* @author cedric dumoulin
*
*/
public class ActiveEditorServicesSwitcher implements IActiveEditorChangedListener {
/** Log object */
Logger log = Logger.getLogger(getClass().getName());
/** The currently active editor */
protected PagePart activeEditor;
/**
* The {@link IEditorSite} of the outerMost editor (the main editor) ...
*/
private IEditorSite outerEditorSite;
/**
* The active service locator. This value may be <code>null</code> if there is no selected page, or if the selected page is a control with no
* site.
*/
private INestable activeServiceLocator;
/**
* Constructor.
*
* @param outerEditorSite
* {@link IEditorSite} of the main editor.
*/
public ActiveEditorServicesSwitcher(IEditorSite outerEditorSite) {
this.outerEditorSite = outerEditorSite;
}
/**
* Get the currently active IEditorPart, if any.
* Return null if there is no active IeditorPart.
* Method check if the active leaf encapsulate an IEditorPart. Return it if true.
*
* @return The currentlyactive IEditorPart or null.
*/
private IEditorPart getActiveIEditorPart() {
return getIEditorPart(activeEditor);
}
/**
* Get IEditorPart of the specified PagePart, if any.
* Return null if there is no IeditorPart.
* Method check if the leaf encapsulate an IEditorPart. Return it if true.
*
* @return The IEditorPart or null.
*/
private IEditorPart getIEditorPart(PagePart pagePart) {
if(pagePart == null)
return null;
if(pagePart instanceof EditorPart) {
return ((EditorPart)pagePart).getIEditorPart();
}
// not found
return null;
}
/**
* Called when the active editor is changed.
* Perform requested operations.
*
* @param oldEditor
* @param newEditor
*/
public void activeEditorChanged(PagePart oldEditor, PagePart newEditor) {
if(activeEditor == newEditor) {
return;
}
// System.out.println(getClass().getSimpleName() + ".activeEditorChange('" + (newEditor != null ? newEditor.getPageTitle() : "null") + "')");
activeEditor = newEditor;
// Set focus
IPartService partService = (IPartService)getOuterEditorSite().getService(IPartService.class);
if(newEditor != null && partService.getActivePart() == getOuterEditorSite().getPart()) {
newEditor.setFocus();
}
// Switch services
deactivateServices(false);
fireChangeEventToActionBarContributor();
propagateSelectionChanged();
activateServices();
//
if(newEditor != null)
newEditor.setFocus();
}
/**
* Change the current selection of the outermost editor (the main editor).
* Send a {@link SelectionChangedEvent} event to the outerProvider. The event contains the current selection
* of the new activeEditor.
*
* @param editor
* The new activeEditor.
*/
private void propagateSelectionChanged() {
// Get the IEditor
IEditorPart editorPart = getActiveIEditorPart();
// Propagate the selection change event.
// Get the selection of the new activeEditor and send an SelectionChangedEvent to the outerProvider (provider of the main
// editor) with the selection.
if(editorPart != null) {
ISelectionProvider selectionProvider = editorPart.getSite().getSelectionProvider();
if(selectionProvider != null) {
ISelectionProvider outerProvider = getOuterEditorSite().getSelectionProvider();
if(outerProvider instanceof MultiPageSelectionProvider) {
SelectionChangedEvent event = new SelectionChangedEvent(selectionProvider, selectionProvider.getSelection());
MultiPageSelectionProvider provider = (MultiPageSelectionProvider)outerProvider;
provider.fireSelectionChanged(event);
provider.firePostSelectionChanged(event);
} else {
if(log.isLoggable(Level.WARNING)) {
log.warning(this.getClass().getSimpleName()
+ " did not propogate selection for " //$NON-NLS-1$
+ editorPart.getTitle());
}
}
}
}
}
/**
* Activates services of the active editor: site, keybinding
* deactivate old active site.
*/
@SuppressWarnings({ "restriction", "deprecation" })
private void activateServices() {
// Deactivate old active site
if(activeServiceLocator != null) {
activeServiceLocator.deactivate();
activeServiceLocator = null;
}
// Get the service
final IKeyBindingService service = getOuterEditorSite().getKeyBindingService();
final IEditorPart editor = getActiveIEditorPart();
if(editor != null) {
// active the service for this inner editor
if(service instanceof INestableKeyBindingService) {
final INestableKeyBindingService nestableService = (INestableKeyBindingService)service;
nestableService.activateKeyBindingService(editor.getEditorSite());
} else {
WorkbenchPlugin.log("MultiPageEditorPart.activateSite() Parent key binding service was not an instance of INestableKeyBindingService. It was an instance of " + service.getClass().getName() + " instead."); //$NON-NLS-1$ //$NON-NLS-2$
}
// Activate the services for the new service locator.
final IServiceLocator serviceLocator = editor.getEditorSite();
if(serviceLocator instanceof INestable) {
activeServiceLocator = (INestable)serviceLocator;
activeServiceLocator.activate();
}
}
}
/**
* Deactivate services: old nested site if any and keybinding service if there is no active editor.
* Deactivate the key binding service.
* Deactivate it only if there is no editor selected.
*/
@SuppressWarnings({ "restriction", "deprecation" })
private void deactivateServices(boolean immediate) {
// Deactivate the nested services from the last active service locator.
if(activeServiceLocator != null) {
activeServiceLocator.deactivate();
activeServiceLocator = null;
}
final IEditorPart editor = getActiveIEditorPart();
final IKeyBindingService service = getOuterEditorSite().getKeyBindingService();
if(editor != null || immediate) {
// There is no selected page, so deactivate the active service.
if(service instanceof INestableKeyBindingService) {
final INestableKeyBindingService nestableService = (INestableKeyBindingService)service;
nestableService.activateKeyBindingService(null);
} else {
WorkbenchPlugin.log("MultiPageEditorPart.deactivateSite() Parent key binding service was not an instance of INestableKeyBindingService. It was an instance of " + service.getClass().getName() + " instead."); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
/**
* Send message to the ActionBarContributor, like this it can switch the active editor.
*/
private void fireChangeEventToActionBarContributor() {
IEditorActionBarContributor contributor = getOuterEditorSite().getActionBarContributor();
if(contributor != null && contributor instanceof IMultiPageEditorActionBarContributor) {
((IMultiPageEditorActionBarContributor)contributor).setActivePage(getActiveIEditorPart());
}
// Ensure compatibility with Eclipse MultiPageEditorActionBarContributor
else if(contributor != null && contributor instanceof MultiPageEditorActionBarContributor) {
((MultiPageEditorActionBarContributor)contributor).setActivePage(getActiveIEditorPart());
}
}
/**
* Return the MultipageEditorSite
*
* @return
*/
private IEditorSite getOuterEditorSite() {
return outerEditorSite;
}
}