blob: e022b6c77a2fc5ea116b0a6e3eb174186293d4ff [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.databinding;
import org.eclipse.core.runtime.Assert;
import org.eclipse.xwt.IConstants;
import org.eclipse.xwt.databinding.BindingMode;
import org.eclipse.xwt.internal.core.ScopeKeeper;
import org.eclipse.xwt.internal.core.UpdateSourceTrigger;
import org.eclipse.xwt.internal.utils.UserData;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.xwt.tools.ui.designer.commands.AddNewChildCommand;
import org.eclipse.xwt.tools.ui.designer.commands.DeleteCommand;
import org.eclipse.xwt.tools.ui.designer.commands.NamedCommand;
import org.eclipse.xwt.tools.ui.designer.loader.XWTProxy;
import org.eclipse.xwt.tools.ui.xaml.XamlAttribute;
import org.eclipse.xwt.tools.ui.xaml.XamlDocument;
import org.eclipse.xwt.tools.ui.xaml.XamlElement;
import org.eclipse.xwt.tools.ui.xaml.XamlFactory;
import org.eclipse.xwt.tools.ui.xaml.XamlNode;
/**
* @author jliu (jin.liu@soyatec.com)
*/
public class BindingInfo implements IBindingInfo, IBindingHandler, BindingConstants {
private BindingContext context;
private String elementName;
private BindingMode bindingMode;
private UpdateSourceTrigger triggerMode;
private String converter;
private CodeStyles codeStyles;
private XamlElement bindingNode;
public BindingInfo(BindingContext bindingContext) {
Assert.isNotNull(bindingContext);
this.context = bindingContext;
}
public BindingContext getBindingContext() {
return context;
}
public void setBindingNode(XamlElement bindingNode) {
this.bindingNode = bindingNode;
}
public XamlElement getBindingNode() {
return bindingNode;
}
public void setConverter(String converter) {
this.converter = converter;
if (bindingNode != null) {
addAttr(bindingNode, CONVERTER, IConstants.XWT_NAMESPACE, converter);
}
}
public String getConverter() {
return converter;
}
public void setElementName(String elementName) {
this.elementName = elementName;
if (bindingNode != null) {
addAttr(bindingNode, ELEMENT_NAME, IConstants.XWT_NAMESPACE, elementName);
}
}
public String getElementName() {
IObservable model = context.getModel();
if (elementName == null && model != null && model.getType() == IObservable.OBSERVE_SWT_JFACE) {
Object source = model.getSource();
elementName = getWidgetName(source);
}
return elementName;
}
private String getWidgetName(Object widget) {
ScopeKeeper nameContext = UserData.findScopeKeeper(widget);
if (nameContext != null) {
for (String name : nameContext.names()) {
if (widget == nameContext.getNamedObject(name)) {
return name;
}
}
}
return null;
}
public void setBindingMode(BindingMode bindingMode) {
this.bindingMode = bindingMode;
if (bindingNode != null) {
addAttr(bindingNode, MODE, IConstants.XWT_NAMESPACE, bindingMode.name());
}
}
public BindingMode getBindingMode() {
return bindingMode;
}
public void setCodeStyles(CodeStyles codeStyles) {
if (codeStyles != null) {
this.codeStyles = codeStyles;
}
}
public CodeStyles getCodeStyles() {
if (codeStyles == null) {
codeStyles = new CodeStyles();
}
return codeStyles;
}
private XamlAttribute getAttribute(XamlNode parent, String attrName, String namespace) {
XamlAttribute attribute = parent.getAttribute(attrName, namespace);
if (attribute == null) {
attribute = XamlFactory.eINSTANCE.createAttribute(attrName, namespace);
}
return attribute;
}
private XamlElement getElement(XamlNode parent, String name, String namespace) {
XamlElement child = parent.getChild(name, namespace);
if (child == null) {
child = XamlFactory.eINSTANCE.createElement(name, namespace);
}
return child;
}
private XamlAttribute addAttr(XamlNode parent, String attrName, String namespace, String value) {
if (parent == null || attrName == null || namespace == null) {
return null;
}
XamlAttribute attribute = parent.getAttribute(attrName, namespace);
if (attribute == null) {
attribute = XamlFactory.eINSTANCE.createAttribute(attrName, namespace);
}
attribute.setValue(value);
if (!parent.getAttributes().contains(attribute)) {
parent.getAttributes().add(attribute);
}
return attribute;
}
private String getCreateName(Object model, CompoundCommand commands) {
if (!(model instanceof Widget)) {
return null;
}
Widget widget = (Widget) model;
String original = getWidgetName(widget);
if (original != null) {
return original;
}
String elementName = getElementName();
if (elementName == null) {
elementName = NamedCommand.generateName(widget);
}
commands.add(new NamedCommand(widget, elementName));
UserData.setObjectName(widget, elementName);
return elementName;
}
public boolean canBinding() {
return context.isValid();
}
public Command bindWithCommand() {
if (!canBinding()) {
return null;
}
CompoundCommand commandList = new CompoundCommand();
Property targetProperty = context.getTargetProperty();
Property modelProperty = context.getModelProperty();
IObservable target = context.getTarget();
IObservable model = context.getModel();
Object targetSource = target.getSource();
Object modelSource = model.getSource();
XamlNode node = null;
if (targetSource instanceof Widget) {
node = XWTProxy.getModel((Widget) targetSource);
} else if (targetSource instanceof XamlElement) {
node = (XamlElement) targetSource;
}
if (node == null) {
return UnexecutableCommand.INSTANCE;
}
// 1. Get attr of targetProperty, such as < text="{}"/>
XamlAttribute attribute = node.getAttribute(targetProperty.getName(), IConstants.XWT_NAMESPACE);
if (attribute != null) {
commandList.add(new DeleteCommand(attribute));
attribute = null;
}
if (attribute == null) {
attribute = XamlFactory.eINSTANCE.createAttribute(targetProperty.getName(), IConstants.XWT_NAMESPACE);
}
// 2. Binding Node.
if (bindingNode == null) {
bindingNode = attribute.getChild(BINDING, IConstants.XWT_NAMESPACE);
}
if (bindingNode == null) {
bindingNode = XamlFactory.eINSTANCE.createElement(BINDING, IConstants.XWT_NAMESPACE);
}
// 3. ElementName
int type = model.getType();
if (type == IObservable.OBSERVE_SWT_JFACE) {
addAttr(bindingNode, ELEMENT_NAME, IConstants.XWT_NAMESPACE, getCreateName(modelSource, commandList));
}
// 4. DataContext
else if (IObservable.OBSERVE_JAVA_BAEN == type) {
XamlDocument ownerDocument = node.getOwnerDocument();
XamlElement rootElement = ownerDocument.getRootElement();
DataContext dataContext = (DataContext) modelSource;
String key = dataContext.getKey();
if (key != null) {
boolean canUseDC = getCodeStyles().useDataContext;
if (canUseDC) {
XamlAttribute contextNode = getAttribute(rootElement, DATA_CONTEXT, IConstants.XWT_NAMESPACE);
contextNode.setUseFlatValue(true);
XamlElement resourceNode = getElement(contextNode, STATIC_RESOURCE, IConstants.XWT_NAMESPACE);
if (!key.equals(resourceNode.getValue())) {
if (resourceNode.getValue() != null) {
canUseDC = false;
} else {
resourceNode.setValue(key);
commandList.add(new AddNewChildCommand(contextNode, resourceNode));
commandList.add(new AddNewChildCommand(rootElement, contextNode));
}
}
}
if (!canUseDC || !getCodeStyles().useDataContext) {
XamlAttribute sourceAttr = getAttribute(bindingNode, SOURCE, IConstants.XWT_NAMESPACE);
sourceAttr.setUseFlatValue(true);
XamlElement resourceNode = getElement(sourceAttr, STATIC_RESOURCE, IConstants.XWT_NAMESPACE);
resourceNode.setValue(key);
commandList.add(new AddNewChildCommand(sourceAttr, resourceNode));
commandList.add(new AddNewChildCommand(bindingNode, sourceAttr));
}
}
}
// 5. Path
addAttr(bindingNode, PATH, IConstants.XWT_NAMESPACE, modelProperty.toString());
// 6. BindingMode
if (bindingMode != null && BindingMode.TwoWay.equals(bindingMode)) {
addAttr(bindingNode, MODE, IConstants.XWT_NAMESPACE, bindingMode.name());
}
// 7. Converter.
if (converter != null) {
addAttr(bindingNode, CONVERTER, IConstants.XWT_NAMESPACE, converter);
}
// 8. UpdateSourceTrigger
if (triggerMode != null) {
addAttr(bindingNode, UPDATE_SOURCE_TRIGGER, IConstants.XWT_NAMESPACE, triggerMode.name());
}
// 9. Code Style.
attribute.setUseFlatValue(getCodeStyles().useFlatVlaue);
if (!attribute.getChildNodes().contains(bindingNode)) {
attribute.getChildNodes().add(bindingNode);
}
if (!node.getAttributes().contains(attribute)) {
commandList.add(new AddNewChildCommand(node, attribute));
}
return commandList.unwrap();
}
public boolean canDelete() {
return bindingNode != null && bindingNode.eContainer() != null;
}
public Command deleteWithCommand() {
if (canDelete()) {
XamlAttribute bindAttr = (XamlAttribute) bindingNode.eContainer();
return new DeleteCommand(bindAttr);
}
return null;
}
public IObservable getModel() {
return context.getModel();
}
public Property getModelProperty() {
return context.getModelProperty();
}
public IObservable getTarget() {
return context.getTarget();
}
public Property getTargetProperty() {
return context.getTargetProperty();
}
public UpdateSourceTrigger getTriggerMode() {
return triggerMode;
}
public void setTriggerMode(UpdateSourceTrigger triggerMode) {
this.triggerMode = triggerMode;
}
}