| /** |
| * Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), 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 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Florian Pirchner - Initial implementation |
| */ |
| package org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.internal; |
| |
| import java.util.Date; |
| import java.util.Locale; |
| |
| import org.eclipse.core.databinding.Binding; |
| import org.eclipse.core.databinding.UpdateValueStrategy; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.impl.AdapterImpl; |
| import org.eclipse.osbp.ecview.core.common.context.IViewContext; |
| import org.eclipse.osbp.ecview.core.common.editpart.IElementEditpart; |
| import org.eclipse.osbp.ecview.core.common.editpart.IEmbeddableEditpart; |
| import org.eclipse.osbp.ecview.core.common.filter.IFilterProvidingPresentation; |
| import org.eclipse.osbp.ecview.core.extension.model.extension.ExtensionModelPackage; |
| import org.eclipse.osbp.ecview.core.extension.model.extension.YFilterDescriptor; |
| import org.eclipse.osbp.ecview.core.extension.model.extension.YFilterTableDescriptor; |
| import org.eclipse.osbp.ecview.core.extension.model.extension.YFilteringComponent; |
| import org.eclipse.osbp.runtime.common.util.BeanUtils; |
| import org.eclipse.osbp.runtime.designer.api.IDesignerService.DesignEvent; |
| import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.AbstractEmbeddedWidgetPresenter; |
| import org.eclipse.osbp.runtime.web.vaadin.components.fields.filter2.FilteringComponent; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * This presenter is responsible to render a text field on the given layout. |
| */ |
| public class FilteringComponentPresentation<T> extends AbstractEmbeddedWidgetPresenter<FilteringComponent<T>> |
| implements IFilterProvidingPresentation { |
| |
| @SuppressWarnings("unused") |
| private static final Logger LOGGER = LoggerFactory.getLogger(FilteringComponentPresentation.class); |
| |
| private FilteringComponent<T> layout; |
| private ModelAccess modelAccess; |
| |
| private int currentChildIndex; |
| |
| private Adapter adapter; |
| |
| private Binding filterBinding; |
| |
| /** |
| * The constructor. |
| * |
| * @param editpart |
| * The editpart of that editpart. |
| */ |
| public FilteringComponentPresentation(IElementEditpart editpart) { |
| super((IEmbeddableEditpart) editpart); |
| this.modelAccess = new ModelAccess((YFilteringComponent) editpart.getModel()); |
| } |
| |
| @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() { |
| } |
| |
| /** |
| * Is called to refresh the UI. The element will be removed from the layout |
| * and added to it again afterwards. |
| */ |
| protected void refreshUI() { |
| |
| // iterate all elements and build the child element |
| // |
| currentChildIndex = 0; |
| |
| unrenderChildren(); |
| renderChildren(); |
| } |
| |
| private void addFilter(YFilterDescriptor child) { |
| currentChildIndex++; |
| switch (child.getType()) { |
| case COMPARE: |
| if (isString(child)) { |
| layout.addCompareTextComponent(child.getPropertyPath(), currentChildIndex); |
| } else if (isDecimal(child)) { |
| layout.addCompareDecimalComponent(child.getPropertyPath(), toDecimalType(child), currentChildIndex); |
| } else if (isDate(child)) { |
| layout.addCompareDateComponent(child.getPropertyPath(), currentChildIndex); |
| } else if (isBoolean(child)) { |
| layout.addCompareBooleanComponent(child.getPropertyPath(), currentChildIndex); |
| } |
| break; |
| case RANGE: |
| if (isString(child)) { |
| layout.addBetweenTextComponent(child.getPropertyPath(), currentChildIndex); |
| } else if (isDecimal(child)) { |
| layout.addBetweenDecimalComponent(child.getPropertyPath(), toCompareType(child), currentChildIndex); |
| } else if (isDate(child)) { |
| layout.addBetweenDateComponent(child.getPropertyPath(), currentChildIndex); |
| } |
| break; |
| } |
| } |
| |
| private void addColumn(YFilterTableDescriptor desc) { |
| layout.addGridColumn(desc.getPropertyPath()); |
| } |
| |
| private Class<?> getType(YFilterDescriptor child) { |
| Class<?> rootType = modelAccess.yLayout.getType(); |
| return BeanUtils.getNestedFieldType(rootType, child.getPropertyPath()); |
| } |
| |
| private boolean isBoolean(YFilterDescriptor child) { |
| Class<?> type = getType(child); |
| return type == Boolean.class || type == Boolean.TYPE; |
| } |
| |
| private boolean isDate(YFilterDescriptor child) { |
| Class<?> type = getType(child); |
| return Date.class.isAssignableFrom(type); |
| } |
| |
| private boolean isDecimal(YFilterDescriptor child) { |
| Class<?> type = getType(child); |
| return type != String.class && type != Boolean.class && type != Boolean.TYPE |
| && (type.isPrimitive() || Number.class.isAssignableFrom(type)); |
| } |
| |
| private boolean isString(YFilterDescriptor child) { |
| Class<?> type = getType(child); |
| return type == String.class; |
| } |
| |
| @SuppressWarnings("unchecked") |
| private <X extends Number & Comparable<?>> Class<X> toCompareType(YFilterDescriptor child) { |
| return (Class<X>) getType(child); |
| } |
| |
| @SuppressWarnings("unchecked") |
| private Class<? extends Number> toDecimalType(YFilterDescriptor child) { |
| return (Class<? extends Number>) getType(child); |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public FilteringComponent<T> doCreateWidget(Object parent) { |
| if (layout == null) { |
| |
| layout = new FiltersComponentCustom(getViewContext(), (Class<T>) modelAccess.yLayout.getType(), |
| modelAccess.yLayout.getFilterCols(), modelAccess.yLayout.isHideGrid()); |
| setupComponent(layout, getCastedModel()); |
| |
| associateWidget(layout, modelAccess.yLayout); |
| |
| if (modelAccess.isCssIdValid()) { |
| layout.setId(modelAccess.getCssID()); |
| } else { |
| layout.setId(getEditpart().getId()); |
| } |
| |
| if (modelAccess.isCssClassValid()) { |
| layout.addStyleName(modelAccess.getCssClass()); |
| } else { |
| layout.addStyleName(CSS_CLASS_CONTROL); |
| } |
| |
| // creates the binding for the field |
| createBindings(modelAccess.yLayout, layout); |
| |
| // initialize all children |
| refreshUI(); |
| |
| adapter = new Adapter(modelAccess.yLayout); |
| |
| // create the bean slot eager |
| getViewContext().createBeanSlot(modelAccess.yLayout.getSelectionBeanSlotName(), |
| modelAccess.yLayout.getType()); |
| |
| // set the selection into the proper beanslot |
| layout.setSelectionConsumer((s) -> { |
| getViewContext().setBean(modelAccess.yLayout.getSelectionBeanSlotName(), s); |
| }); |
| } |
| |
| return layout; |
| } |
| |
| protected void createBindings(YFilteringComponent yField, FilteringComponent<T> field) { |
| { |
| // filter property |
| UpdateValueStrategy modelToTarget = new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER); |
| UpdateValueStrategy targetToModel = new UpdateValueStrategy(UpdateValueStrategy.POLICY_ON_REQUEST); |
| filterBinding = createBindingsByAccessor(castEObject(getModel()), |
| ExtensionModelPackage.Literals.YFILTERING_COMPONENT__FILTER, layout, "filter", targetToModel, |
| modelToTarget); |
| registerBinding(filterBinding); |
| } |
| |
| { |
| // apply filter property |
| UpdateValueStrategy modelToTarget = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE); |
| UpdateValueStrategy targetToModel = new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER); |
| Binding binding = createBindingsByAccessor(castEObject(getModel()), |
| ExtensionModelPackage.Literals.YFILTERING_COMPONENT__APPLY_FILTER, this, "applyFilter", |
| targetToModel, modelToTarget); |
| registerBinding(binding); |
| } |
| |
| { |
| // reset filter property |
| UpdateValueStrategy modelToTarget = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE); |
| UpdateValueStrategy targetToModel = new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER); |
| Binding binding = createBindingsByAccessor(castEObject(getModel()), |
| ExtensionModelPackage.Literals.YFILTERING_COMPONENT__RESET_FILTER, this, "resetFilter", |
| targetToModel, modelToTarget); |
| registerBinding(binding); |
| } |
| |
| super.createBindings(yField, field, null); |
| } |
| |
| // helper methods for binding |
| public void setApplyFilter(Object value) { |
| layout.applyFilters(); |
| } |
| |
| // helper methods for binding |
| public Object getApplyFilter() { |
| return new Date(); |
| } |
| |
| // helper methods for binding |
| public void setResetFilter(Object value) { |
| layout.resetAllFilters(); |
| } |
| |
| // helper methods for binding |
| public Object getResetFilter() { |
| return new Date(); |
| } |
| |
| protected void renderChildren() { |
| for (YFilterDescriptor desc : modelAccess.yLayout.getFilterDescriptors()) { |
| addFilter(desc); |
| } |
| |
| for (YFilterTableDescriptor desc : modelAccess.yLayout.getTableDescriptors()) { |
| addColumn(desc); |
| } |
| } |
| |
| protected void unrenderChildren() { |
| layout.removeAllComponents(); |
| } |
| |
| @Override |
| public Object getFilter() { |
| return layout.getFilter(); |
| } |
| |
| @Override |
| public FilteringComponent<T> getWidget() { |
| return layout; |
| } |
| |
| @Override |
| public boolean isRendered() { |
| return layout != null; |
| } |
| |
| @Override |
| protected void internalDispose() { |
| try { |
| unrender(); |
| } finally { |
| super.internalDispose(); |
| } |
| } |
| |
| @Override |
| public void doUnrender() { |
| if (layout != null) { |
| |
| filterBinding.dispose(); |
| filterBinding = null; |
| |
| adapter.dispose(); |
| adapter = null; |
| |
| // unbind all active bindings |
| unbind(); |
| |
| // remove assocations |
| unassociateWidget(layout); |
| |
| unrenderChildren(); |
| |
| layout.dispose(); |
| layout = null; |
| } |
| } |
| |
| @Override |
| public void notify(DesignEvent event) { |
| // nothing to do |
| } |
| |
| /** |
| * An internal helper class. |
| */ |
| private static class ModelAccess { |
| private final YFilteringComponent yLayout; |
| |
| public ModelAccess(YFilteringComponent yLayout) { |
| super(); |
| this.yLayout = yLayout; |
| } |
| |
| /** |
| * @return |
| * @see org.eclipse.osbp.ecview.core.ui.core.model.core.YCssAble#getCssClass() |
| */ |
| public String getCssClass() { |
| return yLayout.getCssClass(); |
| } |
| |
| /** |
| * Returns true, if the css class is not null and not empty. |
| * |
| * @return |
| */ |
| public boolean isCssClassValid() { |
| return getCssClass() != null && !getCssClass().equals(""); |
| } |
| |
| /** |
| * @return |
| * @see org.eclipse.osbp.ecview.core.ui.core.model.core.YCssAble#getCssID() |
| */ |
| public String getCssID() { |
| return yLayout.getCssID(); |
| } |
| |
| /** |
| * Returns true, if the css id is not null and not empty. |
| * |
| * @return |
| */ |
| public boolean isCssIdValid() { |
| return getCssID() != null && !getCssID().equals(""); |
| } |
| |
| } |
| |
| class Adapter extends AdapterImpl { |
| |
| final YFilteringComponent component; |
| |
| Adapter(YFilteringComponent component) { |
| this.component = component; |
| component.eAdapters().add(this); |
| } |
| |
| @Override |
| public void notifyChanged(Notification msg) { |
| if (msg.getFeature() == ExtensionModelPackage.Literals.YFILTERING_COMPONENT__FILTER_DESCRIPTORS) { |
| refreshUI(); |
| } else if (msg.getFeature() == ExtensionModelPackage.Literals.YFILTERING_COMPONENT__TABLE_DESCRIPTORS) { |
| refreshUI(); |
| } |
| } |
| |
| void dispose() { |
| component.eAdapters().remove(this); |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| class FiltersComponentCustom extends FilteringComponent<T> { |
| |
| public FiltersComponentCustom(IViewContext viewContext, Class<T> type, boolean hideGrid) { |
| super(viewContext, type, hideGrid); |
| } |
| |
| public FiltersComponentCustom(IViewContext viewContext, Class<T> rootType, int filterCols, boolean hideGrid) { |
| super(viewContext, rootType, filterCols, hideGrid); |
| } |
| |
| private Object resetFilters; |
| private Object applyFilters; |
| |
| // binding support |
| public Object getResetFilters() { |
| return resetFilters; |
| } |
| |
| // binding support |
| public void setResetFilters(Object resetFilters) { |
| this.resetFilters = resetFilters; |
| super.resetAllFilters(); |
| } |
| |
| // binding support |
| public Object getApplyFilters() { |
| return applyFilters; |
| } |
| |
| public void applyFilters() { |
| super.applyFilters(); |
| |
| // invoke the filter binding to update the model |
| filterBinding.updateTargetToModel(); |
| } |
| |
| // binding support |
| public void setApplyFilters(Object applyFilters) { |
| this.applyFilters = applyFilters; |
| |
| // invoke the filter binding to update the model |
| filterBinding.updateTargetToModel(); |
| } |
| } |
| |
| } |