| /******************************************************************************* |
| * 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(); |
| } |
| } |