Programmatically split an editor area to show two editors side by side

.Last time a workmate of mine asked me if it is possible, to programmatically split the editor area of an eclipse RCP application.

We all know that if you have two editors opened in the workbench, you can drag one of the editors and drop it in one of the regions of the editor area (bottom, top, left or right) so that both editors are side by side.

I started to analyze the eclipse code and look for a public API that I can use to achieve this task. I didn’t find anything. My first idea was to simulate the Drag&Drop behavior, but it came out to be a very challenging task.

So I’ve decided to use some of the API calls, which the eclipse team discourages to use. And it works. I bundled my code into a plug-in. Maybe someone will find this useful.


package spliteditorarea.actions;

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.EditorSashContainer;
import org.eclipse.ui.internal.EditorStack;
import org.eclipse.ui.internal.ILayoutContainer;
import org.eclipse.ui.internal.LayoutPart;
import org.eclipse.ui.internal.PartPane;
import org.eclipse.ui.internal.PartSashContainer;
import org.eclipse.ui.internal.PartSite;
import org.eclipse.ui.internal.PartStack;
import org.eclipse.ui.internal.WorkbenchPage;

/**
 * Our sample action implements workbench action delegate. The action proxy will
 * be created by the workbench and shown in the UI. When the user tries to use
 * the action, this delegate will be created and execution will be delegated to
 * it.
 * 
 * @see IWorkbenchWindowActionDelegate
 */
@SuppressWarnings("restriction")
public class SplitEditorAreaAction implements IWorkbenchWindowActionDelegate {
	private IWorkbenchWindow window;

	/**
	 * The constructor.
	 */
	public SplitEditorAreaAction() {
	}

	/**
	 * The action has been activated. The argument of the method represents the
	 * 'real' action sitting in the workbench UI.
	 * 
	 * @see IWorkbenchWindowActionDelegate#run
	 */
	public void run(IAction action) {
		splitEditorArea();
	}

	/**
	 * Split the editor area if there is at least two editor in it.
	 */
	private void splitEditorArea() {
		IWorkbenchPage workbenchPage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
		IWorkbenchPart part = workbenchPage.getActivePart();
		PartPane partPane = ((PartSite) part.getSite()).getPane();
		LayoutPart layoutPart = partPane.getPart();

		IEditorReference[] editorReferences = workbenchPage.getEditorReferences();
		// Do it only if we have more that one editor
		if (editorReferences.length > 1) {
			// Get PartPane that correspond to the active editor
			PartPane currentEditorPartPane = ((PartSite) workbenchPage.getActiveEditor().getSite()).getPane();
			EditorSashContainer editorSashContainer = null;
			ILayoutContainer rootLayoutContainer = layoutPart.getContainer();
			if (rootLayoutContainer instanceof LayoutPart) {
				ILayoutContainer editorSashLayoutContainer = ((LayoutPart) rootLayoutContainer).getContainer();
				if (editorSashLayoutContainer instanceof EditorSashContainer) {
					editorSashContainer = ((EditorSashContainer) editorSashLayoutContainer);
				}
			}
			/*
			 * Create a new part stack (i.e. a workbook) to home the currentEditorPartPane
			 * which hold the active editor
			 * */
			PartStack newPart = createStack(editorSashContainer);
			editorSashContainer.stack(currentEditorPartPane, newPart);
			if (rootLayoutContainer instanceof LayoutPart) {
				ILayoutContainer cont = ((LayoutPart) rootLayoutContainer).getContainer();
				if (cont instanceof PartSashContainer) {
					// "Split" the editor area by adding the new part
					((PartSashContainer) cont).add(newPart);
				}
			}
		}
	}

	/**
	 * A method to create a part stack container (a new workbook)
	 * 
	 * @param editorSashContainer the <code>EditorSashContainer</code> to set for the returned <code>PartStack</code>
	 * @return a new part stack container
	 */
	private PartStack createStack(EditorSashContainer editorSashContainer) {
		WorkbenchPage workbenchPage = (WorkbenchPage) PlatformUI.getWorkbench().getActiveWorkbenchWindow()
				.getActivePage();
		EditorStack newWorkbook = EditorStack.newEditorWorkbook(editorSashContainer, workbenchPage);
		return newWorkbook;
	}

	/**
	 * Selection in the workbench has been changed. We can change the state of
	 * the 'real' action here if we want, but this can only happen after the
	 * delegate has been created.
	 * 
	 * @see IWorkbenchWindowActionDelegate#selectionChanged
	 */
	public void selectionChanged(IAction action, ISelection selection) {
	}

	/**
	 * We can use this method to dispose of any system resources we previously
	 * allocated.
	 * 
	 * @see IWorkbenchWindowActionDelegate#dispose
	 */
	public void dispose() {
	}

	/**
	 * We will cache window object in order to be able to provide parent shell
	 * for the message dialog.
	 * 
	 * @see IWorkbenchWindowActionDelegate#init
	 */
	public void init(IWorkbenchWindow window) {
		this.window = window;
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章