/*******************************************************************************
* 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.papyrus.xwt.internal.core;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.papyrus.xwt.IDataBindingInfo;
import org.eclipse.papyrus.xwt.IDataProvider;
import org.eclipse.papyrus.xwt.IMultiValueConverter;
import org.eclipse.papyrus.xwt.IValidationRule;
import org.eclipse.papyrus.xwt.XWT;
import org.eclipse.papyrus.xwt.XWTException;
import org.eclipse.papyrus.xwt.converters.StringMultiValueConerter;
import org.eclipse.papyrus.xwt.core.IDynamicBinding;
import org.eclipse.papyrus.xwt.databinding.AggregateObservableValue;
import org.eclipse.papyrus.xwt.databinding.IBindingContext;
import org.eclipse.papyrus.xwt.internal.utils.LoggerManager;
import org.eclipse.papyrus.xwt.internal.utils.UserData;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Text;
/**
* Support the aggregation of data binding
*
* @author yyang (yves.yang@soyatec.com)
*/
public class MultiBinding extends DynamicBinding implements IDataBindingInfo {
private Binding[] bindings = Binding.EMPTY_ARRAY;
private IMultiValueConverter valueConverter;
private IValidationRule[] valueValidators = IValidationRule.EMPTY_ARRAY;
private AggregateObservableValue observableValue;
private IObservableValue observableWidget;
private BindingExpressionPath targetPropertySegments;
/**
* <p>
* Default
* </p>
*
*/
private UpdateSourceTrigger updateSourceTrigger = UpdateSourceTrigger.Default;
private BindingGate bindingGate;
public UpdateSourceTrigger getUpdateSourceTrigger() {
return updateSourceTrigger;
}
public void setUpdateSourceTrigger(UpdateSourceTrigger updateSourceTrigger) {
this.updateSourceTrigger = updateSourceTrigger;
}
public Binding[] getBindings() {
return bindings;
}
public void setBindings(Binding[] bindings) {
this.bindings = bindings;
}
public IMultiValueConverter getConverter() {
if(valueConverter == null) {
valueConverter = new StringMultiValueConerter();
}
return valueConverter;
}
public void setConverter(IMultiValueConverter valueConverter) {
this.valueConverter = valueConverter;
}
public boolean isSourcePropertyReadOnly() {
for(Binding binding : bindings) {
if(binding.isSourcePropertyReadOnly()) {
return true;
}
}
return false;
}
public Object getValue(Class<?> targetType) {
if(observableValue == null) {
IObservableValue[] values = new IObservableValue[bindings.length];
for(int i = 0; i < values.length; i++) {
bindings[i].getValue(targetType);
IObservable observable = bindings[i].getObservableSource();
if(observable instanceof IObservableValue) {
values[i] = (IObservableValue)observable;
} else {
LoggerManager.log("Binding expression has a problem with " + bindings[i].getPath());
return null;
}
}
observableValue = new AggregateObservableValue(values, getConverter());
}
IObservableValue observableWidget = getObservableWidget();
IDataProvider dataProvider = getDataProvider();
if(dataProvider != null) {
BindingGate bindingGate = getBindingGate();
if(bindingGate != null) {
Object target = getControl();
if(target instanceof Text && getType().equalsIgnoreCase("text")) {
if(isSourcePropertyReadOnly()) {
Text text = (Text)target;
text.setEditable(false);
}
} else if(target instanceof Button && getType().equalsIgnoreCase("selection")) {
if(isSourcePropertyReadOnly()) {
Button button = (Button)target;
button.setEnabled(false);
}
} else if((target instanceof Combo || target instanceof CCombo) && getType().equalsIgnoreCase("text")) {
if(isSourcePropertyReadOnly()) {
Control control = (Control)target;
control.setEnabled(false);
}
} else if(target instanceof MenuItem && getType().equalsIgnoreCase("selection")) {
if(isSourcePropertyReadOnly()) {
MenuItem menuItem = (MenuItem)target;
menuItem.setEnabled(false);
}
}
}
bindingGate.bind(observableValue, observableWidget, this);
}
if(targetType == null || !targetType.isInstance(observableValue)) {
return observableValue.getValue();
}
return observableValue;
}
private BindingGate getBindingGate() {
if(this.bindingGate == null) {
IBindingContext dataBindingContext = XWT.getBindingContext(getControl());
this.bindingGate = new BindingGate(dataBindingContext);
}
return this.bindingGate;
}
public IObservableValue getObservableWidget() {
if(observableWidget == null) {
Object target = getControl();
Object host = getHost();
try {
observableWidget = ScopeManager.observeValue(target, host, getTargettPropertyExpression(), getUpdateSourceTrigger());
} catch (XWTException e) {
}
}
return observableWidget;
}
public Object createBoundSource() {
Object control = getControl();
Object source = XWT.getDataContext(control);
Object localDataContext = UserData.getLocalDataContext(control);
if(localDataContext == this) {
return source;
}
if(source instanceof IDynamicBinding) {
return ((IDynamicBinding)source).createBoundSource();
}
return source;
}
public boolean isSourceControl() {
Object source = null;
Object dataContextHost = getDataContextHost();
if(dataContextHost != null) {
source = UserData.getLocalDataContext(dataContextHost);
}
if(source instanceof IDynamicBinding) {
return ((IDynamicBinding)source).isSourceControl();
}
return false;
}
public BindingExpressionPath getTargettPropertyExpression() {
if(targetPropertySegments == null) {
targetPropertySegments = new BindingExpressionPath(getType());
}
return targetPropertySegments;
}
public IValidationRule[] getValidators() {
return valueValidators;
}
public void setValidators(IValidationRule[] valueValidators) {
this.valueValidators = valueValidators;
}
public void reset() {
for(Binding binding : bindings) {
binding.reset();
}
}
}