/**
* Copyright (c) 2009, 2014 Mark Feber, MulgaSoft
*
* 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
*
*/
package com.mulgasoft.emacsplus.commands;
import java.util.ArrayList;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.handlers.HandlerUtil;
import com.mulgasoft.emacsplus.EmacsPlusActivation;
/**
* @author Mark Feber - initial API and implementation
*/
public class CloseOtherInstancesHandler extends EmacsPlusNoEditHandler {
/**
* Execute directly
*
* @see com.mulgasoft.emacsplus.commands.EmacsPlusCmdHandler#execute(org.eclipse.core.commands.ExecutionEvent)
*/
@Override
public Object execute(ExecutionEvent event) {
try {
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
IWorkbenchPage page = window.getActivePage();
closeOtherInstances(page);
} catch (ExecutionException e) {
} catch (PartInitException e) {
} catch (Exception e) {
}
return null;
}
/**
* Close all other editors on the current editor's input
*
* @param page
* @throws PartInitException
*/
protected void closeOtherInstances(IWorkbenchPage page) throws PartInitException {
if (page != null) {
IEditorReference active = (IEditorReference) page.getReference(page.getActiveEditor());
ArrayList<IEditorReference> otherInstances = getOtherInstances(active, page);
// Close the others, and guarantee proper (emacs+) activation
if (!otherInstances.isEmpty()) {
IEditorReference[] otherEditors = otherInstances.toArray(new IEditorReference[0]);;
// don't prompt to save contents, as the final instance is still open
page.closeEditors(otherEditors, false);
// We have to manually call our activation code, as closing the identity editors
// results in our document listeners being removed, and since the part is already
// active, a simple call to page.activate is a no-op.
EmacsPlusActivation.getInstance().partActivated(active);
}
}
}
private ArrayList<IEditorReference> getOtherInstances(IEditorReference active,IWorkbenchPage page) throws PartInitException {
ArrayList<IEditorReference> result = new ArrayList<IEditorReference>();
if (page != null) {
IEditorReference[] refArray = page.getEditorReferences();
if (refArray != null && refArray.length > 1) {
// Dereference if a multi-part editor, returns identity if not
IEditorReference dactive = (IEditorReference) page.getReference(getActiveEditor(page));
IEditorInput ai = active.getEditorInput();
if (ai != null) {
if (dactive != null && active != dactive) {
IEditorInput dai = dactive.getEditorInput();
if (dai != null) {
for (int i = 0; i < refArray.length; i++) {
try {
if (editorsMatch(active, ai, refArray[i]) || (editorsMatch(dactive, dai, refArray[i]))) {
result.add(refArray[i]);
}
} catch (Exception e) {
// Trap (most likely PartInitException) Exception so that we can get the instances that don't fail
}
}
}
} else {
for (int i = 0; i < refArray.length; i++) {
try {
if (editorsMatch(active, ai, refArray[i])) {
result.add(refArray[i]);
}
} catch (Exception e) {
// Trap (most likely PartInitException) Exception so that we can get the instances that don't fail
}
}
}
}
}
}
return result;
}
/**
* Compare two editor instances
* @param a
* @param b
* @return true if different editor instances are looking at the same content
* @throws PartInitException
*/
private boolean editorsMatch(IEditorReference a, IEditorInput ai, IEditorReference b) throws PartInitException {
return (a != b && ai.equals(b.getEditorInput()));
}
}