/** * 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.e4.commands; import static com.mulgasoft.emacsplus.EmacsPlusUtils.getPreferenceBoolean; import static com.mulgasoft.emacsplus.EmacsPlusUtils.getPreferenceStore; import static com.mulgasoft.emacsplus.preferences.PrefVars.SHOW_OTHER_HORIZONTAL; import javax.inject.Named; import org.eclipse.e4.core.contexts.Active; import org.eclipse.e4.core.di.annotations.Execute; import org.eclipse.e4.ui.model.application.ui.MElementContainer; import org.eclipse.e4.ui.model.application.ui.MUIElement; import org.eclipse.e4.ui.model.application.ui.basic.MPart; import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.texteditor.ITextEditor; import com.mulgasoft.emacsplus.Beeper; import com.mulgasoft.emacsplus.EmacsPlusUtils; import com.mulgasoft.emacsplus.commands.EmacsPlusCmdHandler; import com.mulgasoft.emacsplus.commands.MinibufferHandler; import com.mulgasoft.emacsplus.minibuffer.IMinibufferExecutable; import com.mulgasoft.emacsplus.minibuffer.SwitchMinibuffer; /** * Implements Select/Display buffer in another window * * Prompt for a buffer and select/show it in another frame. If: * - only one frame, then split and place in new buffer * - multiple frames, move buffer to adjacent frame if not in destination frame, * - else simply select/show in destination frame * * When splitting, split horizontally unless called with ^U * * @author mfeber - Initial API and implementation */ public class SwitchToBufferOtherCmd extends WindowSplitCmd implements IMinibufferExecutable { MPart apart; EmacsPlusCmdHandler handler; private boolean displayOnly = false; private String prefix = "Buffer%s"; //$NON-NLS-1$ // A global, sticky variable to set the default direction of split private static boolean DISPLAY_HORIZONTAL = getPreferenceBoolean(SHOW_OTHER_HORIZONTAL.getPref()); static { // listen for changes in the property store getPreferenceStore().addPropertyChangeListener( new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { if (SHOW_OTHER_HORIZONTAL.getPref().equals(event.getProperty())) { setHorizontal((Boolean)event.getNewValue()); } } } ); } public static void setHorizontal(boolean horizontal) { DISPLAY_HORIZONTAL = horizontal; } @Execute public Object execute(@Active MPart apart, @Active IEditorPart editor, @Active EmacsPlusCmdHandler handler, @Named(E4CmdHandler.CMD_CTX_KEY)boolean display, @Named(E4CmdHandler.PRE_CTX_KEY) String prefix) { this.handler = handler; this.apart = apart; this.displayOnly = display; this.prefix = prefix; try { ITextEditor ted = EmacsPlusUtils.getTextEditor(editor, true); if (ted != null) { MinibufferHandler.bufferTransform(new SwitchMinibuffer(this), ted, null); } } catch (BadLocationException e) { // Shouldn't happen Beeper.beep(); } return null; } public boolean isUniversalPresent() { return handler.isUniversalPresent(); } public String getMinibufferPrefix() { return prefix; } public boolean executeResult(ITextEditor editor, Object minibufferResult) { if (minibufferResult instanceof IEditorPart) { // get the MPart from the editor MPart miniPart = (MPart) ((IEditorPart) minibufferResult).getSite().getService(MPart.class); switchTo(miniPart); } return false; } void switchTo(MPart newPart) { if (getOrderedStacks(apart).size() == 1) { // case 1: 1 frame, split with miniPart // convenience hack: change direction on uArg splitIt(newPart, getDirection((isUniversalPresent()) ? !DISPLAY_HORIZONTAL : DISPLAY_HORIZONTAL)); } else { // case 2: multiple stacks, move to adjacent stack // get the starting stack MElementContainer<MUIElement> stack = getParentStack(apart).getStack(); // get the topart's stack MElementContainer<MUIElement> tstack = getParentStack(newPart).getStack(); stack = findNextStack(apart, stack, 1); if (stack != null && stack != tstack) { modelService.move(newPart, stack, 0); } } if (displayOnly) { // brings to top partService.showPart(newPart, PartState.VISIBLE); reactivate(apart); } else { // bug in Kepler forces us to activate the old before the new reactivate(apart); reactivate(newPart); } } public void setResultMessage(String resultMessage, boolean resultError) { } }