blob: 89196cdb3ae05eaed266e6d7a267f2f8cbda5525 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2010 Soyatec (http://www.soyatec.com) 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:
* Soyatec - initial API and implementation
*******************************************************************************/
package org.eclipse.xwt.tools.ui.designer.commands;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.xwt.IConstants;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Sash;
import org.eclipse.xwt.tools.ui.designer.XWTDesignerPlugin;
import org.eclipse.xwt.tools.ui.designer.core.parts.VisualEditPart;
import org.eclipse.xwt.tools.ui.designer.core.util.StringUtil;
import org.eclipse.xwt.tools.ui.designer.core.util.swt.SWTTools;
import org.eclipse.xwt.tools.ui.designer.core.visuals.IVisualInfo;
import org.eclipse.xwt.tools.ui.designer.parts.SashFormEditPart;
import org.eclipse.xwt.tools.ui.xaml.XamlNode;
/**
* @author jin.liu (jin.liu@soyatec.com)
*
*/
public class ChangeWeightsCommand extends Command {
private SashFormEditPart parent;
private ChangeBoundsRequest request;
private Command command;
private Integer[] weights;
public ChangeWeightsCommand(SashFormEditPart parent,
ChangeBoundsRequest request) {
super("Change Weights");
this.parent = parent;
this.request = request;
}
public boolean canExecute() {
if (parent == null || request == null || request.getEditParts() == null) {
return false;
}
IVisualInfo visualInfo = ((VisualEditPart) parent).getVisualInfo();
SashForm sashForm = (SashForm) visualInfo.getVisualObject();
weights = computeWeights(sashForm);
if (weights == null) {
return false;
}
for (Integer integer : weights) {
if (integer == null || integer.intValue() < 0) {
return false;
}
}
return true;
}
public void execute() {
command = new ApplyAttributeSettingCommand(
(XamlNode) parent.getModel(), "weights",
IConstants.XWT_NAMESPACE, StringUtil.format(weights));
command.execute();
}
public boolean canUndo() {
return command != null && command.canUndo();
}
public void undo() {
command.undo();
}
private VisualEditPart getEditPart() {
List<VisualEditPart> editParts = new ArrayList<VisualEditPart>(request
.getEditParts());
if (editParts.size() > 0) {
return editParts.get(0);
}
return null;
}
private Integer[] computeWeights(SashForm sashForm) {
int[] weights = sashForm.getWeights();
int[] newWeights = weights;
VisualEditPart editPart = getEditPart();
if (editPart != null) {
XamlNode parentNode = (XamlNode) parent.getModel();
int index = parentNode.getChildNodes().indexOf(editPart.getModel());
Object visualObject = editPart.getVisualInfo().getVisualObject();
if (index != -1) {
int resizeDirection = request.getResizeDirection();
Dimension sizeDelta = request.getSizeDelta();
int offset = getResizeOffset((Control) visualObject, null,
newWeights, index, sizeDelta.width, sizeDelta.height,
resizeDirection == PositionConstants.EAST
|| resizeDirection == PositionConstants.WEST);
for (int i = 0; i < newWeights.length; i++) {
if (i == index) {
newWeights[i] += offset;
} else {
newWeights[i] -= offset / (newWeights.length - 1);
}
}
}
// SashEditPart.
else {
Sash sash = (Sash) visualObject;
int sashIndex = getSashIndex(sashForm, sash);
org.eclipse.draw2d.geometry.Point moveDelta = request
.getMoveDelta();
boolean horizontal = (sash.getStyle() & SWT.VERTICAL) != 0;
Control[] controls = getControls(sashForm);
if (controls != null) {
int resizeOffset = getResizeOffset(controls[sashIndex], sash,
newWeights, sashIndex, moveDelta.x, moveDelta.y,
horizontal);
newWeights[sashIndex] += resizeOffset;
newWeights[sashIndex + 1] -= resizeOffset;
}
}
}
List<Integer> ws = new ArrayList<Integer>();
for (int i = 0; i < newWeights.length; i++) {
ws.add(newWeights[i]);
}
return ws.toArray(new Integer[ws.size()]);
}
private int getSashIndex(SashForm sashForm, Sash sash) {
try {
Field field = SashForm.class.getDeclaredField("sashes");
field.setAccessible(true);
Sash[] sashes = (Sash[]) field.get(sashForm);
for (int i = 0; i < sashes.length; i++) {
if (sashes[i].equals(sash)) {
return i;
}
}
} catch (Exception e) {
XWTDesignerPlugin.logError(e);
}
return -1;
}
private Control[] getControls(SashForm sashForm) {
try {
Field field = SashForm.class.getDeclaredField("controls");
field.setAccessible(true);
return (Control[]) field.get(sashForm);
} catch (Exception e) {
}
return null;
}
private int getResizeOffset(Control control, Sash sash, int[] weights, int index,
int x, int y, boolean horizontal) {
float total = 0;
for (int i : weights) {
total += i;
}
Rectangle bounds = SWTTools.getBounds(control);
if (horizontal) {
int w = bounds.width;
if (sash != null) {
// in case the child doesn't fill the cell
Rectangle sashBounds = SWTTools.getBounds(sash);
w = Math.max(w, sashBounds.x - bounds.x);
}
float percent = weights[index] / total;
float width = (w / percent);
float newPercent = (w + x) / width;
int newWeight = (int) (total * newPercent);
return newWeight - weights[index];
} else {
int h = bounds.height;
if (sash != null) {
// in case the child doesn't fill the cell
Rectangle sashBounds = SWTTools.getBounds(sash);
h = Math.max(h, sashBounds.y - bounds.y);
}
float percent = weights[index] / total;
float height = (h / percent);
float newPercent = (h + y) / height;
int newWeight = (int) (total * newPercent);
return newWeight - weights[index];
}
}
}