blob: a2298155f5f504012e1366abab406abe6b1d056e [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.util.HashMap;
import java.util.Map;
import org.eclipse.xwt.IConstants;
import org.eclipse.xwt.metadata.IMetaclass;
import org.eclipse.emf.common.util.EList;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.xwt.tools.ui.designer.core.parts.VisualEditPart;
import org.eclipse.xwt.tools.ui.designer.core.visuals.IVisualInfo;
import org.eclipse.xwt.tools.ui.designer.core.visuals.swt.CompositeInfo;
import org.eclipse.xwt.tools.ui.designer.layouts.LayoutType;
import org.eclipse.xwt.tools.ui.designer.layouts.LayoutsHelper;
import org.eclipse.xwt.tools.ui.designer.loader.XWTProxy;
import org.eclipse.xwt.tools.ui.designer.parts.CompositeEditPart;
import org.eclipse.xwt.tools.ui.designer.utils.XWTUtility;
import org.eclipse.xwt.tools.ui.xaml.XamlAttribute;
import org.eclipse.xwt.tools.ui.xaml.XamlElement;
import org.eclipse.xwt.tools.ui.xaml.XamlFactory;
/**
* @author rui.ban rui.ban@soyatec.com
*/
public class ChangeLayoutCommand extends Command {
private LayoutType layoutType;
private EditPart editPart;
private XamlElement element;
private XamlAttribute layoutAttr;
private XamlElement newLayout;
private XamlElement oldLayout;
private boolean isNewAttr;
/**
* @param editPart
* @param text
*/
public ChangeLayoutCommand(EditPart editPart, LayoutType layoutType) {
this.editPart = editPart;
this.layoutType = layoutType;
}
/**
* @see org.eclipse.gef.commands.Command#canExecute()
*/
public boolean canExecute() {
if (editPart == null || !(editPart instanceof CompositeEditPart)) {
return false;
}
if (layoutType == null || layoutType == LayoutsHelper.getLayoutType(editPart)) {
return false;
}
return editPart.getModel() instanceof XamlElement;
}
/**
* @see org.eclipse.gef.commands.Command#execute()
*/
public void execute() {
element = (XamlElement) editPart.getModel();
updateLayoutData(element, layoutType);
layoutAttr = element.getAttribute("layout");
if (layoutType == LayoutType.NullLayout) {
element.getAttributes().remove(layoutAttr);
return;
}
if (layoutAttr == null) {
layoutAttr = XamlFactory.eINSTANCE.createAttribute("layout", IConstants.XWT_NAMESPACE);
isNewAttr = true;
}
EList<XamlElement> childNodes = layoutAttr.getChildNodes();
if (childNodes.size() == 1) {
oldLayout = childNodes.get(0);
}
childNodes.clear();
if (layoutType != LayoutType.NullLayout) {
newLayout = XamlFactory.eINSTANCE.createElement(layoutType.value(), IConstants.XWT_NAMESPACE);
childNodes.add(newLayout);
}
if (isNewAttr && layoutType != LayoutType.NullLayout) {
element.getAttributes().add(layoutAttr);
}
}
/**
* @see org.eclipse.gef.commands.Command#canUndo()
*/
public boolean canUndo() {
if (element == null) {
return false;
}
if (isNewAttr) {
return layoutAttr != null;
}
return layoutAttr != null && oldLayout != null;
}
/**
* @see org.eclipse.gef.commands.Command#undo()
*/
public void undo() {
if (isNewAttr) {
element.getAttributes().remove(layoutAttr);
} else if (oldLayout != null) {
layoutAttr.getChildNodes().clear();
layoutAttr.getChildNodes().add(oldLayout);
} else if (layoutAttr != null && element.getAttribute("layout", IConstants.XWT_NAMESPACE) == null) {
element.getAttributes().add(layoutAttr);
}
}
private void updateLayoutData(XamlElement element, LayoutType layoutType) {
if (element == null) {
return;
}
if (layoutType != LayoutType.NullLayout) {
// just remove them.
EList<XamlElement> childNodes = element.getChildNodes();
for (XamlElement subElement : childNodes) {
XamlAttribute attribute = subElement.getAttribute("layoutData");
if (attribute != null) {
subElement.getAttributes().remove(attribute);
}
}
} else if (editPart != null && editPart instanceof VisualEditPart) {
IVisualInfo visualInfo = ((VisualEditPart) editPart).getVisualInfo();
Composite parent = null;
if (visualInfo != null && visualInfo instanceof CompositeInfo) {
parent = (Composite) ((CompositeInfo) visualInfo).getVisualObject();
}
if (parent == null || parent.isDisposed()) {
return;
}
Map<Object, Control> model2control = new HashMap<Object, Control>();
for (Control child : parent.getChildren()) {
model2control.put(XWTProxy.getModel(child), child);
}
EList<XamlElement> childNodes = element.getChildNodes();
for (XamlElement xamlElement : childNodes) {
Control control = model2control.get(xamlElement);
IMetaclass metaclass = XWTUtility.getMetaclass(xamlElement);
if (metaclass == null || !Control.class.isAssignableFrom(metaclass.getType()) || control == null) {
continue;
}
Rectangle r = control.getBounds();
boolean boundsNoExisted = true, sizeNoExisted = true, locationNoExisted = true;
XamlAttribute boundsAttr = xamlElement.getAttribute("bounds");
if (boundsAttr != null) {
boundsAttr.setValue(toString(r));
boundsNoExisted = false;
}
XamlAttribute sizeAttr = xamlElement.getAttribute("size");
if (sizeAttr != null) {
sizeAttr.setValue(toString(new Point(r.width, r.height)));
sizeNoExisted = false;
}
XamlAttribute locationAttr = xamlElement.getAttribute("location");
if (locationAttr != null) {
locationAttr.setValue(toString(new Point(r.x, r.y)));
locationNoExisted = false;
}
if (boundsNoExisted && sizeNoExisted && locationNoExisted) {
boundsAttr = XamlFactory.eINSTANCE.createAttribute("bounds", IConstants.XWT_NAMESPACE);
boundsAttr.setValue(toString(r));
xamlElement.getAttributes().add(boundsAttr);
} else if (boundsNoExisted && sizeNoExisted) {
sizeAttr = XamlFactory.eINSTANCE.createAttribute("size", IConstants.XWT_NAMESPACE);
sizeAttr.setValue(toString(new Point(r.width, r.height)));
xamlElement.getAttributes().add(sizeAttr);
} else if (boundsNoExisted && locationNoExisted) {
locationAttr = XamlFactory.eINSTANCE.createAttribute("location", IConstants.XWT_NAMESPACE);
locationAttr.setValue(toString(new Point(r.x, r.y)));
xamlElement.getAttributes().add(locationAttr);
}
}
}
}
private String toString(Object object) {
if (object == null) {
return null;
}
if (object instanceof Rectangle) {
Rectangle r = (Rectangle) object;
return r.x + "," + r.y + "," + r.width + "," + r.height;
} else if (object instanceof Point) {
Point p = (Point) object;
return p.x + "," + p.y;
}
return object.toString();
}
}