/**
* 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 java.util.List;
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 com.mulgasoft.emacsplus.commands.EmacsPlusCmdHandler;
/**
* Make selected frame <adjustment> amount smaller or larger within it's PartSash
* If the PartSash is horizontal, then the frame is made shorter or taller
* else narrower or wider. Differs from strict gnu emacs.
*
* @author mfeber - Initial API and implementation
*/
public class WindowShrinkCmd extends E4WindowCmd {
// The use of container data to establish size does not directly correspond to columns,
// so pick a reasonable amount as a fraction of the total "size"
private static final float adjustment = 0.025f;
private static final float minsize = 0.05f;
public static enum Col {
BALANCE, SHRINK, ENLARGE;
}
@Execute
public Object execute(@Active MPart apart, @Named(E4CmdHandler.CMD_CTX_KEY)Col stype, @Active EmacsPlusCmdHandler handler) {
PartAndStack ps = getParentStack(apart);
MElementContainer<MUIElement> stack = ps.getStack();
MElementContainer<MUIElement> next = getAdjacentElement(stack, ps.getPart(), false);
int count = handler.getUniversalCount();
if (next != null) {
switch (stype) {
case SHRINK:
adjustContainerData((MUIElement)stack, (MUIElement)next, count, getTotalSize(apart));
break;
case ENLARGE:
adjustContainerData((MUIElement)next, (MUIElement)stack, count, getTotalSize(apart));
break;
case BALANCE:
balancePartSash(stack);
break;
}
}
return null;
}
/**
* Change the size of from relative to to by amount, but do not go below
* a minimum size.
*
* @param from selected PartStack
* @param to adjacent PartStack
* @param amount by which to adjust each
*/
private void adjustContainerData(MUIElement from, MUIElement to, int count, int size) {
int adjust = getIntData(from);;
int adjustTo = getIntData(to);;
int amount = (Math.round(size * adjustment)) * count;
int minim = Math.round(size * minsize);
if (adjust - amount < minim) {
// enforce minimum size
amount = adjust - minim;
}
// take from the rich and give to the poor
from.setContainerData(String.valueOf(adjust - amount));
to.setContainerData(String.valueOf(adjustTo + amount));
}
/**
* Just balance all the elements in the current PartSash
* TODO: This works well with simple arrangements, but not with complex trees
*
* @param stack
*/
private void balancePartSash(MElementContainer<MUIElement> stack) {
if (stack != null) {
try {
List<MUIElement> children = stack.getParent().getChildren();
int adjust = 0;
if (children.size() > 1) {
for (MUIElement child : children) {
adjust += Integer.parseInt(child.getContainerData());
}
String adjustData = String.valueOf(adjust / children.size());
for (MUIElement child : children) {
child.setContainerData(adjustData);
}
}
} catch (NumberFormatException e) {
// Ignore - someone has messed with the container data
}
}
}
}