/**
* Copyright (c) 2015 committers of YAKINDU and others.
* 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:
* committers of YAKINDU - initial API and implementation
*
*/
package org.yakindu.base.xtext.utils.jface.viewers.util;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.resources.IProject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.domain.IEditingDomainProvider;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IPageListener;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IStartup;
import org.eclipse.ui.IWindowListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
/**
* Get the last active editor in general or of a specific type.
*
* Please note that the ActiveEditorTracker currently only supports one single
* workbench window properly.
*
* @author patrick.koenemann@itemis.de
* @author alexander.nyssen@itemis.de
*
*/
public class ActiveEditorTracker implements IPageListener, IPartListener,
IStartup, IWindowListener {
private static final String SINGLETON_MSG = "This class is a singleton and may only be instantiated once!";
private IWorkbenchWindow workbenchWindow;
private Map<String, IEditorPart> activeEditors = new HashMap<String, IEditorPart>();
private String lastActiveEditorId;
private IWorkbenchPage activePage;
private static ActiveEditorTracker INSTANCE;
public ActiveEditorTracker() {
if (INSTANCE != null)
throw new IllegalStateException(SINGLETON_MSG);
INSTANCE = this;
}
public void earlyStartup() {
PlatformUI.getWorkbench().addWindowListener(this);
}
/**
* @return The last active editor in the current active workbench page.
*/
public static IEditorPart getLastActiveEditor() {
if (INSTANCE == null) {
// not yet initialized, e.g. when another early startups blocks us!
// Let's try to get the current active editor instead.
if (PlatformUI.getWorkbench() != null) {
if (PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null) {
return PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getActivePage().getActiveEditor();
}
}
return null;
}
return INSTANCE.getLastActiveEditorInternal();
}
/**
* @return The last active editor with the given editor ID in the current
* active workbench page.
*/
public static IEditorPart getLastEditor(String editorId) {
if (INSTANCE == null) {
// not yet initialized, e.g. when another early startups blocks us!
// Let's try to get any editor with the specified id instead.
if (PlatformUI.getWorkbench() != null) {
final IWorkbenchWindow window = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow();
if (window != null) {
final IWorkbenchPage page = window.getActivePage();
if (page != null) {
for (IEditorReference ref : page.getEditorReferences()) {
if (ref.getId().equals(editorId)) {
return ref.getEditor(false);
}
}
}
}
}
return null;
}
return INSTANCE.getEditorById(editorId);
}
/**
*
* @return The EMF resource set of the last active editor (if it is still
* open).
*/
public static ResourceSet getLastActiveEditorResourceSet() {
final IEditorPart editor = getLastActiveEditor();
if (editor == null)
return null;
EditingDomain domain = null;
if (editor instanceof IEditingDomainProvider) {
domain = ((IEditingDomainProvider) editor).getEditingDomain();
} else if (editor.getAdapter(IEditingDomainProvider.class) != null) {
domain = ((IEditingDomainProvider) editor
.getAdapter(IEditingDomainProvider.class))
.getEditingDomain();
} else if (editor.getAdapter(EditingDomain.class) != null) {
domain = (EditingDomain) editor.getAdapter(EditingDomain.class);
}
if (domain == null) {
return null;
}
return domain.getResourceSet();
}
/**
* @return The project which contains the file that is open in the last
* active editor in the current workbench page.
*/
public static IProject getLastActiveEditorProject() {
final IEditorPart editor = getLastActiveEditor();
if (editor == null)
return null;
final IEditorInput editorInput = editor.getEditorInput();
if (editorInput instanceof IFileEditorInput) {
final IFileEditorInput input = (IFileEditorInput) editorInput;
return input.getFile().getProject();
}
return null;
}
public void pageActivated(IWorkbenchPage page) {
this.activePage = page;
}
public void pageClosed(IWorkbenchPage page) {
if (page == activePage) {
activePage = null;
}
lastActiveEditorId = null;
}
public void pageOpened(IWorkbenchPage page) {
// do nothing
}
public void partActivated(IWorkbenchPart part) {
if (part instanceof IEditorPart) {
setActiveEditor((IEditorPart) part);
}
}
public void partBroughtToTop(IWorkbenchPart part) {
if (part instanceof IEditorPart) {
setActiveEditor((IEditorPart) part);
}
}
public void partClosed(IWorkbenchPart part) {
if (part instanceof IEditorPart) {
String id = null;
for (Entry<String, IEditorPart> entry : activeEditors.entrySet()) {
if (entry.getValue().equals(part)) {
id = entry.getKey();
break;
}
}
if (id != null) {
activeEditors.remove(id);
if (id.equals(lastActiveEditorId)) {
lastActiveEditorId = null;
}
}
}
}
public void partDeactivated(IWorkbenchPart part) {
if (part instanceof IEditorPart) {
// do nothing
}
}
private IEditorPart getLastActiveEditorInternal() {
if (activePage == null) {
initialize(PlatformUI.getWorkbench().getActiveWorkbenchWindow());
if (activePage == null)
return null;
}
boolean updated = false;
if (lastActiveEditorId == null) {
final IEditorPart editor = activePage.getActiveEditor();
if (editor != null) {
setActiveEditor(editor);
}
updated = true;
}
IEditorPart editor = getEditorById(lastActiveEditorId);
if (editor == null && !updated) {
editor = activePage.getActiveEditor();
if (editor != null) {
setActiveEditor(editor);
}
}
return editor;
}
private IEditorPart getEditorById(String editorId) {
if (activePage == null || editorId == null)
return null;
final IEditorPart editor = activeEditors.get(editorId);
final String id = checkEditorAndGetId(editor);
if (id != null && id.equals(editorId)) {
return editor;
}
return null;
}
private String checkEditorAndGetId(IEditorPart editor) {
if (editor == null)
return null;
for (IEditorReference ref : activePage.getEditorReferences()) {
if (editor.equals(ref.getEditor(false))) {
return ref.getId();
}
}
return null;
}
public IWorkbenchPage getActivePage() {
return activePage;
}
/**
* Set the active editor
*/
private void setActiveEditor(IEditorPart part) {
if (part == null) {
lastActiveEditorId = null;
return;
}
final IWorkbenchPartReference reference = activePage.getReference(part);
if (reference == null)
throw new IllegalStateException("Impossible?!");
lastActiveEditorId = reference.getId();
activeEditors.put(lastActiveEditorId, part);
}
public void partOpened(IWorkbenchPart part) {
if (part instanceof IEditorPart) {
setActiveEditor((IEditorPart) part);
}
}
public void dispose() {
if (workbenchWindow == null) {
return;
}
workbenchWindow.removePageListener(this);
workbenchWindow.getPartService().removePartListener(this);
workbenchWindow = null;
}
public void windowActivated(IWorkbenchWindow window) {
initialize(window);
}
protected void initialize(IWorkbenchWindow window) {
if (workbenchWindow != null && !workbenchWindow.equals(window)) {
/*
* TODO: implement logic for keeping track of editors in multiple
* workbench windows!
*/
}
this.workbenchWindow = window;
if (window == null)
return;
this.activePage = window.getActivePage();
final IEditorPart editor = this.activePage.getActiveEditor();
if (editor != null) {
lastActiveEditorId = checkEditorAndGetId(editor);
activeEditors.put(lastActiveEditorId, editor);
}
window.addPageListener(this);
window.getPartService().addPartListener(this);
}
public void windowDeactivated(IWorkbenchWindow window) {
// not of interest
}
public void windowClosed(IWorkbenchWindow window) {
dispose();
}
public void windowOpened(IWorkbenchWindow window) {
// not of interest
}
}