blob: 3f38199fa174e0a581035604a258d30a6ed0cd4b [file] [log] [blame]
/**
*
* Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
*
* 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:
* Florian Pirchner - Initial implementation
*
*/
package org.eclipse.osbp.ecview.extension.presentation.vaadin.components;
import java.util.Locale;
import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.conversion.Converter;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.databinding.EMFObservables;
import org.eclipse.emf.databinding.EMFProperties;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.osbp.ecview.core.common.editpart.IElementEditpart;
import org.eclipse.osbp.ecview.core.common.model.core.YEmbeddableBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.core.YEmbeddableCollectionEndpoint;
import org.eclipse.osbp.ecview.core.common.model.core.YEmbeddableSelectionEndpoint;
import org.eclipse.osbp.ecview.core.databinding.emf.model.ECViewModelBindable;
import org.eclipse.osbp.ecview.extension.editparts.components.IPairComboBoxEditpart;
import org.eclipse.osbp.ecview.extension.model.YECviewPackage;
import org.eclipse.osbp.ecview.extension.model.YPairComboBox;
import org.eclipse.osbp.runtime.common.state.ISharedStateContext;
import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.IBindingManager;
import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.AbstractFieldWidgetPresenter;
import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.internal.util.Util;
import org.eclipse.osbp.runtime.web.vaadin.common.data.BeanServiceLazyLoadingContainer;
import org.eclipse.osbp.runtime.web.vaadin.common.data.DeepResolvingBeanItemContainer;
import org.eclipse.osbp.runtime.web.vaadin.common.data.IBeanSearchServiceFactory;
import org.eclipse.osbp.runtime.web.vaadin.components.widget.LazyLoadingComboBox;
import org.eclipse.osbp.runtime.web.vaadin.databinding.VaadinObservables;
import org.eclipse.xtext.util.Pair;
import org.eclipse.xtext.util.Tuples;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.vaadin.data.Container;
import com.vaadin.data.Container.Sortable;
import com.vaadin.data.Property;
import com.vaadin.data.util.ObjectProperty;
import com.vaadin.server.Resource;
import com.vaadin.server.ThemeResource;
import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.Field;
@SuppressWarnings("restriction")
public class PairComboBoxPresentation extends AbstractFieldWidgetPresenter<Component> {
/** The Constant LOGGER. */
private static final Logger LOGGER = LoggerFactory.getLogger(PairComboBoxPresentation.class);
/** The model access. */
private final ModelAccess modelAccess;
/** The combo. */
private LazyLoadingComboBox combo;
/** The property. */
@SuppressWarnings("rawtypes")
private ObjectProperty property;
/**
* Constructor.
*
* @param editpart
* The editpart of that presenter
*/
public PairComboBoxPresentation(IElementEditpart editpart) {
super((IPairComboBoxEditpart) editpart);
this.modelAccess = new ModelAccess((YPairComboBox) editpart.getModel());
}
/**
* {@inheritDoc}
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Component doCreateWidget(Object parent) {
if (combo == null) {
combo = new CustomComboBox();
combo.addStyleName(CSS_CLASS_CONTROL);
combo.setImmediate(true);
setupComponent(combo, getCastedModel());
associateWidget(combo, modelAccess.yField);
if (modelAccess.isCssIdValid()) {
combo.setId(modelAccess.getCssID());
} else {
combo.setId(getEditpart().getId());
}
if (modelAccess.isCssClassValid()) {
combo.addStyleName(modelAccess.getCssClass());
}
try {
property = new ObjectProperty(null, modelAccess.yField.getType());
combo.setPropertyDataSource(property);
if (modelAccess.yField.getType() != null) {
if (!modelAccess.yField.isUseBeanService()) {
DeepResolvingBeanItemContainer datasource = new DeepResolvingBeanItemContainer(modelAccess.yField.getType());
combo.setContainerDataSource(datasource);
} else {
IBeanSearchServiceFactory factory = getViewContext().getService(IBeanSearchServiceFactory.class.getName());
if (factory != null) {
ISharedStateContext sharedState = getViewContext().getService(ISharedStateContext.class.getName());
BeanServiceLazyLoadingContainer<?> datasource = new BeanServiceLazyLoadingContainer(
factory.createService(modelAccess.yField.getType()), modelAccess.yField.getType(), sharedState);
combo.setContainerDataSource(datasource);
}
}
}
String itemCaptionProperty = modelAccess.yField.getCaptionProperty();
if (itemCaptionProperty != null && !itemCaptionProperty.equals("")) {
combo.setItemCaptionPropertyId(itemCaptionProperty);
combo.setItemCaptionMode(ItemCaptionMode.PROPERTY);
Container container = combo.getContainerDataSource();
if (container instanceof Container.Sortable) {
Container.Sortable sortable = (Sortable) container;
sortable.sort(new Object[] { itemCaptionProperty }, new boolean[] { true });
}
} else {
combo.setItemCaptionMode(ItemCaptionMode.ID);
}
String itemImageProperty = modelAccess.yField.getImageProperty();
if (itemImageProperty != null && !itemImageProperty.equals("")) {
combo.setItemIconPropertyId(itemImageProperty);
}
// creates the binding for the field
createBindings(modelAccess.yField, combo);
if (modelAccess.isCssClassValid()) {
combo.addStyleName(modelAccess.getCssClass());
}
applyCaptions();
initializeField(combo);
} catch (Exception e) {
LOGGER.error("{}", e);
}
}
return combo;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.
* AbstractVaadinWidgetPresenter#doUpdateLocale(java.util.Locale)
*/
@Override
protected void doUpdateLocale(Locale locale) {
// no need to set the locale to the ui elements. Is handled by vaadin
// internally.
// update the captions
applyCaptions();
}
/**
* Applies the labels to the widgets.
*/
protected void applyCaptions() {
Util.applyCaptions(getI18nService(), modelAccess.getLabel(), modelAccess.getLabelI18nKey(), getLocale(), combo);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.
* AbstractFieldWidgetPresenter#doGetField()
*/
@Override
protected Field<?> doGetField() {
return combo;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.
* AbstractVaadinWidgetPresenter
* #internalGetObservableEndpoint(org.eclipse.osbp
* .ecview.core.common.model.core.YEmbeddableBindingEndpoint)
*/
@Override
protected IObservable internalGetObservableEndpoint(YEmbeddableBindingEndpoint bindableValue) {
if (bindableValue == null) {
throw new IllegalArgumentException("BindableValue must not be null!");
}
if (bindableValue instanceof YEmbeddableCollectionEndpoint) {
return internalGetCollectionEndpoint();
} else if (bindableValue instanceof YEmbeddableSelectionEndpoint) {
return internalGetSelectionEndpoint((YEmbeddableSelectionEndpoint) bindableValue);
}
throw new IllegalArgumentException("Not a valid input: " + bindableValue);
}
/**
* Returns the observable to observe the collection.
*
* @return the i observable list
*/
protected IObservableList internalGetCollectionEndpoint() {
// return the observable value for text
return EMFProperties.list(YECviewPackage.Literals.YPAIR_COMBO_BOX__COLLECTION).observe(getModel());
}
/**
* Returns the observable to observe the selection.
*
* @param yEndpoint
* the y endpoint
* @return the i observable value
*/
protected IObservableValue internalGetSelectionEndpoint(YEmbeddableSelectionEndpoint yEndpoint) {
String attributePath = ECViewModelBindable.getAttributePath(YECviewPackage.Literals.YPAIR_COMBO_BOX__SELECTION,
yEndpoint.getAttributePath());
// return the observable value for text
return ECViewModelBindable.observeValue(castEObject(getModel()), attributePath, modelAccess.yField.getType(),
modelAccess.yField.getEmfNsURI());
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.osbp.ecview.core.common.presentation.IWidgetPresentation#
* getWidget()
*/
@Override
public Component getWidget() {
return combo;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.osbp.ecview.core.common.presentation.IWidgetPresentation#
* isRendered()
*/
@Override
public boolean isRendered() {
return combo != null;
}
/**
* {@inheritDoc}
*/
@Override
public void doUnrender() {
if (combo != null) {
// unbind all active bindings
unbind();
Component parent = ((Component) combo.getParent());
if (parent != null && parent instanceof ComponentContainer) {
((ComponentContainer) parent).removeComponent(combo);
}
// remove assocations
unassociateWidget(combo);
combo = null;
}
}
/**
* {@inheritDoc}
*/
@Override
protected void internalDispose() {
try {
unrender();
} finally {
super.internalDispose();
}
}
/**
* A helper class.
*/
private static class ModelAccess {
/** The y field. */
private final YPairComboBox yField;
/**
* Instantiates a new model access.
*
* @param yField
* the y field
*/
public ModelAccess(YPairComboBox yField) {
super();
this.yField = yField;
}
/**
* Gets the css class.
*
* @return the css class
* @see org.eclipse.osbp.ecview.core.ui.core.model.core.YCssAble#getCssClass()
*/
public String getCssClass() {
return yField.getCssClass();
}
/**
* Returns true, if the css class is not null and not empty.
*
* @return true, if is css class valid
*/
public boolean isCssClassValid() {
return getCssClass() != null && !getCssClass().equals("");
}
/**
* Gets the css id.
*
* @return the css id
* @see org.eclipse.osbp.ecview.core.ui.core.model.core.YCssAble#getCssID()
*/
public String getCssID() {
return yField.getCssID();
}
/**
* Returns true, if the css id is not null and not empty.
*
* @return true, if is css id valid
*/
public boolean isCssIdValid() {
return getCssID() != null && !getCssID().equals("");
}
/**
* Returns the label.
*
* @return the label
*/
public String getLabel() {
return yField.getDatadescription() != null ? yField.getDatadescription().getLabel() : null;
}
/**
* Returns the label.
*
* @return the label i18n key
*/
public String getLabelI18nKey() {
return yField.getDatadescription() != null ? yField.getDatadescription().getLabelI18nKey() : null;
}
}
/**
* Converts the string value of the item icon property to
* {@link ThemeResource}.
*/
@SuppressWarnings("serial")
private static class CustomComboBox extends LazyLoadingComboBox {
/** The item icon property id. */
private Object itemIconPropertyId;
/*
* (non-Javadoc)
*
* @see
* com.vaadin.ui.AbstractSelect#setItemIconPropertyId(java.lang.Object)
*/
@Override
public void setItemIconPropertyId(Object propertyId) throws IllegalArgumentException {
if (propertyId == null) {
super.setItemIconPropertyId(propertyId);
} else if (!getContainerPropertyIds().contains(propertyId)) {
super.setItemIconPropertyId(propertyId);
} else if (String.class.isAssignableFrom(getType(propertyId))) {
itemIconPropertyId = propertyId;
} else {
super.setItemIconPropertyId(propertyId);
}
}
/*
* (non-Javadoc)
*
* @see com.vaadin.ui.AbstractSelect#getItemIconPropertyId()
*/
public Object getItemIconPropertyId() {
return itemIconPropertyId != null ? itemIconPropertyId : super.getItemIconPropertyId();
}
/*
* (non-Javadoc)
*
* @see com.vaadin.ui.AbstractSelect#getItemIcon(java.lang.Object)
*/
public Resource getItemIcon(Object itemId) {
if (itemIconPropertyId == null) {
return super.getItemIcon(itemId);
} else {
final Property<?> ip = getContainerProperty(itemId, getItemIconPropertyId());
if (ip == null) {
return null;
}
final Object icon = ip.getValue();
try {
if (icon instanceof String) {
return new ThemeResource((String) icon);
}
} catch (Exception e) {
// nothing to do
}
}
return null;
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.
* AbstractFieldWidgetPresenter#setConverter(java.lang.Object)
*/
@Override
public void setConverter(Object object) {
if (object == null) {
}
super.setConverter(object);
}
/**
* Creates the bindings for the given values.
*
* @param yField
* the y field
* @param field
* the field
*/
protected void createBindings(YPairComboBox yField, LazyLoadingComboBox field) {
// create the model binding from ridget to ECView-model
// registerBinding(createBindings_ContainerContents(castEObject(getModel()),
// YECviewPackage.Literals.YPAIR_COMBO_BOX__COLLECTION,
// field));
// create the model binding from ridget to ECView-model
registerBinding(createBindings_ContainerContents(castEObject(getModel()), YECviewPackage.Literals.YPAIR_COMBO_BOX__COLLECTION,
field, yField.getType()));
// create the model binding from ridget to ECView-model
// registerBinding(createBindingsPairSelection(castEObject(getModel()),
// YECviewPackage.Literals.YPAIR_COMBO_BOX__SELECTION, field,
// yField.getType()));
registerBinding(createBindingsPairSelection(castEObject(getModel()), YECviewPackage.Literals.YPAIR_COMBO_BOX__SELECTION, field));
super.createBindings(yField, field, null);
}
/**
* Binds the value attribute from the ecview model to the ui element.
*
* @param model
* the model
* @param modelFeature
* the model feature
* @param field
* the field
* @param targetToModel
* the target to model
* @param modelToTarget
* the model to target
* @return Binding - the created binding
*/
protected Binding createBindingsPairSelection(EObject model, EStructuralFeature modelFeature, Field<?> field) {
IBindingManager bindingManager = getViewContext().getService(
org.eclipse.osbp.ecview.core.common.binding.IECViewBindingManager.class.getName());
if (bindingManager != null) {
UpdateValueStrategy targetToModel = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE);
targetToModel.setConverter(new PairToTextConverter());
UpdateValueStrategy modelToTarget = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE);
modelToTarget.setConverter(new TextToPairConverter());
// bind the value of yText to textRidget
IObservableValue modelObservable = EMFObservables.observeValue(model, modelFeature);
IObservableValue uiObservable = VaadinObservables.observeValue(field);
return bindingManager.bindValue(uiObservable, modelObservable, targetToModel, modelToTarget);
}
return null;
}
private static class TextToPairConverter extends Converter {
public TextToPairConverter() {
super(String.class, Pair.class);
}
@Override
public Object convert(Object fromObject) {
if (fromObject == null) {
return null;
}
return Tuples.create(extractSimpleName((String) fromObject), (String) fromObject);
// return fromObject;
}
private String extractSimpleName(String fqn) {
String[] splittedFqn = fqn.split("\\.");
String name = "";
int length = splittedFqn.length;
if (length > 0) {
name = splittedFqn[length - 1];
}
return name;
}
}
private static class PairToTextConverter extends Converter {
public PairToTextConverter() {
super(Pair.class, String.class);
}
@SuppressWarnings("unchecked")
@Override
public Object convert(Object fromObject) {
if (fromObject == null) {
return "";
}
return ((Pair<String, String>) fromObject).getSecond();
}
}
}