| /** |
| * 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 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.runtime.web.ecview.presentation.vaadin.internal; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| import java.util.Timer; |
| import java.util.TimerTask; |
| import java.util.stream.Collectors; |
| import java.util.stream.Stream; |
| |
| 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.common.notify.Notification; |
| import org.eclipse.emf.common.notify.impl.AdapterImpl; |
| import org.eclipse.emf.databinding.EMFProperties; |
| import org.eclipse.osbp.blob.component.BlobComponent; |
| import org.eclipse.osbp.dsl.semantic.dto.util.NamingConventionsUtil; |
| import org.eclipse.osbp.ecview.core.common.editpart.IConverterEditpart; |
| import org.eclipse.osbp.ecview.core.common.editpart.IElementEditpart; |
| import org.eclipse.osbp.ecview.core.common.editpart.emf.ElementEditpart; |
| import org.eclipse.osbp.ecview.core.common.filter.IFilterablePresentation; |
| import org.eclipse.osbp.ecview.core.common.filter.IRefreshRowsPresentation; |
| 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.YEmbeddableMultiSelectionEndpoint; |
| import org.eclipse.osbp.ecview.core.common.model.core.YEmbeddableSelectionEndpoint; |
| import org.eclipse.osbp.ecview.core.common.model.core.YFlatAlignment; |
| import org.eclipse.osbp.ecview.core.common.model.datatypes.YDatadescription; |
| import org.eclipse.osbp.ecview.core.common.notification.ILifecycleEvent; |
| import org.eclipse.osbp.ecview.core.common.notification.ILifecycleService; |
| import org.eclipse.osbp.ecview.core.common.presentation.DelegatingConverterFactory; |
| import org.eclipse.osbp.ecview.core.databinding.emf.model.ECViewModelBindable; |
| import org.eclipse.osbp.ecview.core.extension.model.extension.ExtensionModelPackage; |
| import org.eclipse.osbp.ecview.core.extension.model.extension.YColumn; |
| import org.eclipse.osbp.ecview.core.extension.model.extension.YSelectionType; |
| import org.eclipse.osbp.ecview.core.extension.model.extension.YSortColumn; |
| import org.eclipse.osbp.ecview.core.extension.model.extension.YTable; |
| import org.eclipse.osbp.ecview.core.ui.core.editparts.extension.ITableEditpart; |
| import org.eclipse.osbp.ecview.extension.api.ILayoutingStrategy; |
| import org.eclipse.osbp.runtime.common.annotations.DtoUtils; |
| import org.eclipse.osbp.runtime.common.annotations.PropertiesUtil; |
| import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent; |
| import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent.EventDispatcherCommand; |
| import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent.EventDispatcherDataTag; |
| import org.eclipse.osbp.runtime.common.event.IEventDispatcher; |
| import org.eclipse.osbp.runtime.common.i18n.I18nUtil; |
| import org.eclipse.osbp.runtime.common.i18n.II18nService; |
| import org.eclipse.osbp.runtime.common.state.ISharedStateContext; |
| 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.converter.StringToFormattedNumberConverter; |
| import org.eclipse.osbp.runtime.web.vaadin.common.data.BeanServiceLazyLoadingContainer; |
| import org.eclipse.osbp.runtime.web.vaadin.common.data.DeepResolvingBeanItem; |
| import org.eclipse.osbp.runtime.web.vaadin.common.data.DeepResolvingBeanItemContainer; |
| import org.eclipse.osbp.runtime.web.vaadin.common.data.IBeanSearchService; |
| import org.eclipse.osbp.runtime.web.vaadin.common.data.IBeanSearchServiceFactory; |
| import org.eclipse.osbp.runtime.web.vaadin.common.data.IBeanToUniqueHashIdProvider; |
| import org.eclipse.osbp.runtime.web.vaadin.common.data.ILazyRefreshFilterable; |
| import org.eclipse.osbp.runtime.web.vaadin.common.data.INestedPropertyAble; |
| import org.eclipse.osbp.runtime.web.vaadin.common.resource.IResourceProvider; |
| import org.eclipse.osbp.ui.api.customfields.IBlobService; |
| |
| import com.vaadin.data.Container; |
| import com.vaadin.data.Container.Filter; |
| import com.vaadin.data.Container.Filterable; |
| import com.vaadin.data.Item; |
| import com.vaadin.data.Property; |
| import com.vaadin.data.Property.ValueChangeListener; |
| import com.vaadin.data.util.IndexedContainer; |
| import com.vaadin.data.util.ObjectProperty; |
| import com.vaadin.data.util.converter.Converter; |
| import com.vaadin.data.util.converter.ConverterUtil; |
| import com.vaadin.server.ClientConnector; |
| import com.vaadin.server.ClientConnector.AttachEvent; |
| import com.vaadin.server.ClientConnector.DetachEvent; |
| import com.vaadin.server.ErrorMessage; |
| import com.vaadin.server.Resource; |
| import com.vaadin.server.ThemeResource; |
| import com.vaadin.ui.AbstractSelect.ItemCaptionMode; |
| import com.vaadin.ui.CheckBox; |
| import com.vaadin.ui.Component; |
| import com.vaadin.ui.ComponentContainer; |
| import com.vaadin.ui.Field; |
| import com.vaadin.ui.Table; |
| import com.vaadin.ui.Table.Align; |
| import com.vaadin.ui.Table.RowHeaderMode; |
| import com.vaadin.ui.UI; |
| |
| /** |
| * This presenter is responsible to render a table on the given layout. |
| */ |
| @SuppressWarnings({ "restriction", "serial" }) |
| public class TablePresentation extends AbstractFieldWidgetPresenter<Component> |
| implements IFilterablePresentation, IRefreshRowsPresentation, ClientConnector.DetachListener, |
| ClientConnector.AttachListener, IEventDispatcher.Receiver { |
| |
| /** The model access. */ |
| private final ModelAccess modelAccess; |
| |
| /** The table. */ |
| private Table table; |
| |
| /** The property. */ |
| @SuppressWarnings("rawtypes") |
| private ObjectProperty property; |
| |
| /** The apply columns. */ |
| private boolean applyColumns; |
| |
| private boolean containerReadonly; |
| |
| private AdapterCustom adapter; |
| |
| private IEventDispatcher eventDispatcher; |
| |
| private IBlobService blobService; |
| |
| /** |
| * Constructor. |
| * |
| * @param editpart |
| * The editpart of that presenter |
| */ |
| public TablePresentation(IElementEditpart editpart) { |
| super((ITableEditpart) editpart); |
| this.modelAccess = new ModelAccess((YTable) editpart.getModel()); |
| adapter = new AdapterCustom(); |
| this.modelAccess.yField.eAdapters().add(adapter); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @SuppressWarnings({ "rawtypes", "unchecked" }) |
| @Override |
| public Component doCreateWidget(Object parent) { |
| if (table == null) { |
| table = new CustomTable(); |
| table.addStyleName(CSS_CLASS_CONTROL); |
| table.setMultiSelect(modelAccess.yField.getSelectionType() == YSelectionType.MULTI); |
| table.setSelectable(true); |
| table.setImmediate(true); |
| setupComponent(table, getCastedModel()); |
| |
| table.addValueChangeListener(new ValueChangeListener() { |
| @Override |
| public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) { |
| Class<?> bean = modelAccess.yField.getType(); |
| if (bean != null) { |
| eventDispatcher = getViewContext().getService(IEventDispatcher.class.getName()); |
| blobService = getViewContext().getService(IBlobService.class.getName()); |
| String topic = NamingConventionsUtil.toFqnEntityName(bean.getName()) + "." |
| + DtoUtils.getIdField(bean).getName(); |
| EventDispatcherEvent evnt = new EventDispatcherEvent(EventDispatcherCommand.SELECT, topic, |
| toString()); |
| Object value = table.getValue(); |
| if (value != null) { |
| if (table.getContainerDataSource() instanceof DeepResolvingBeanItemContainer) { |
| DeepResolvingBeanItemContainer container = (DeepResolvingBeanItemContainer) table |
| .getContainerDataSource(); |
| DeepResolvingBeanItem<?> item = container.getItem(value); |
| if (item != null) { |
| evnt.addItem(EventDispatcherDataTag.ID, DtoUtils.getIdValue(item.getBean())); |
| eventDispatcher.sendEvent(evnt); |
| } |
| } |
| } else { |
| evnt.addItem(EventDispatcherDataTag.ID, null); |
| eventDispatcher.sendEvent(evnt); |
| } |
| } |
| } |
| }); |
| |
| associateWidget(table, modelAccess.yField); |
| if (modelAccess.isCssIdValid()) { |
| table.setId(modelAccess.getCssID()); |
| } else { |
| table.setId(getEditpart().getId()); |
| } |
| |
| if (table.isMultiSelect()) { |
| property = new ObjectProperty(new HashSet(), Set.class); |
| } else { |
| if (modelAccess.yField.getType() != null) { |
| property = new ObjectProperty(null, modelAccess.yField.getType()); |
| } else { |
| property = new ObjectProperty(null, Object.class); |
| } |
| } |
| table.setPropertyDataSource(property); |
| |
| applyColumns = false; |
| if (modelAccess.yField.getType() == String.class) { |
| IndexedContainer datasource = new IndexedContainer(); |
| table.setContainerDataSource(datasource); |
| table.setItemCaptionMode(ItemCaptionMode.ID); |
| } else { |
| if (modelAccess.yField.getType() != null) { |
| IBeanSearchService<?> service = null; |
| IBeanSearchServiceFactory factory = getViewContext() |
| .getService(IBeanSearchServiceFactory.class.getName()); |
| if (factory != null) { |
| service = factory.createService(modelAccess.yField.getType()); |
| } |
| if (modelAccess.yField.isUseBeanService() && service != null) { |
| ISharedStateContext sharedState = getViewContext() |
| .getService(ISharedStateContext.class.getName()); |
| BeanServiceLazyLoadingContainer<?> datasource = new BeanServiceLazyLoadingContainer(service, |
| modelAccess.yField.getType(), sharedState); |
| table.setContainerDataSource(datasource); |
| containerReadonly = true; |
| } else { |
| DeepResolvingBeanItemContainer datasource = new DeepResolvingBeanItemContainer( |
| modelAccess.yField.getType()); |
| table.setContainerDataSource(datasource); |
| } |
| applyColumns = true; |
| } else { |
| IndexedContainer container = new IndexedContainer(); |
| container.addContainerProperty("for", String.class, null); |
| container.addContainerProperty("preview", String.class, null); |
| container.addItem(new String[] { "Some value", "other" }); |
| table.setContainerDataSource(container); |
| } |
| } |
| |
| String itemImageProperty = modelAccess.yField.getItemImageProperty(); |
| if (itemImageProperty != null && !itemImageProperty.equals("")) { |
| table.setItemIconPropertyId(itemImageProperty); |
| table.setRowHeaderMode(RowHeaderMode.EXPLICIT); |
| } |
| |
| // creates the binding for the field |
| createBindings(modelAccess.yField, table); |
| |
| if (modelAccess.isCssClassValid()) { |
| table.addStyleName(modelAccess.getCssClass()); |
| } |
| |
| applyCaptions(); |
| |
| initializeField(table); |
| } |
| return table; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.ecview.core.common.filter.IRefreshRowsPresentation# |
| * refreshRows() |
| */ |
| @Override |
| public void refreshRows() { |
| if (isRendered()) { |
| table.refreshRowCache(); |
| } |
| } |
| |
| /** |
| * Applies the column setting to the table. |
| */ |
| @SuppressWarnings({ "serial", "unchecked" }) |
| protected void applyColumns() { |
| Class<?> type = modelAccess.yField.getType(); |
| |
| // set the visible columns and icons |
| List<String> columns = new ArrayList<>(); |
| Collection<?> propertyIds = table.getContainerDataSource().getContainerPropertyIds(); |
| |
| if (!modelAccess.yField.getColumns().isEmpty()) { |
| for (YColumn yColumn : modelAccess.yField.getColumns()) { |
| if (yColumn.isVisible() && propertyIds.contains(yColumn.getPropertyPath()) || isNestedColumn(yColumn)) { |
| columns.add(yColumn.getPropertyPath()); |
| } |
| } |
| |
| // add nested properties |
| if (table.getContainerDataSource() instanceof INestedPropertyAble) { |
| INestedPropertyAble<?> container = (INestedPropertyAble<?>) table.getContainerDataSource(); |
| for (String property : columns) { |
| if (property.contains(".")) { |
| container.addNestedContainerProperty(property); |
| } |
| } |
| } |
| |
| table.setVisibleColumns(columns.toArray(new Object[columns.size()])); |
| table.setColumnCollapsingAllowed(true); |
| |
| II18nService i18nService = getViewContext().getService(II18nService.class.getName()); |
| IResourceProvider resourceProvider = (IResourceProvider) getViewContext() |
| .getService(IResourceProvider.class.getName()); |
| // traverse the columns again and set other properties |
| for (YColumn yColumn : modelAccess.yField.getColumns()) { |
| if (yColumn.isVisible() |
| && (propertyIds.contains(yColumn.getPropertyPath()) || isNestedColumn(yColumn))) { |
| String columnId = yColumn.getPropertyPath(); |
| |
| table.setColumnHeader(columnId, getColumnHeader(yColumn)); |
| table.setColumnAlignment(columnId, toAlign(yColumn.getAlignment())); |
| table.setColumnCollapsed(columnId, yColumn.isCollapsed()); |
| table.setColumnCollapsible(columnId, yColumn.isCollapsible()); |
| if (yColumn.getExpandRatio() >= 0) { |
| table.setColumnExpandRatio(columnId, yColumn.getExpandRatio()); |
| } |
| // Boolean check to display a checkbox instead of the |
| // boolean value as String. |
| if (yColumn.getType() == Boolean.class) { |
| // check to avoid an IllegalArgumentException adding an |
| // already existing ColumnGenerator. |
| if (table.getColumnGenerator(columnId) == null) { |
| table.addGeneratedColumn(columnId, new Table.ColumnGenerator() { |
| @Override |
| public Component generateCell(Table source, Object itemId, Object columnId) { |
| Item item = table.getItem(itemId); |
| CheckBox box = new CheckBox(); |
| box.setEnabled(false); |
| Boolean value = (Boolean) item.getItemProperty(columnId).getValue(); |
| box.setValue(value); |
| return box; |
| } |
| }); |
| } |
| } |
| // -------------- |
| if (yColumn.getIcon() != null && !yColumn.getIcon().equals("")) { |
| if (i18nService != null) { |
| String translation = i18nService.getValue(yColumn.getIcon(), UI.getCurrent().getLocale()); |
| if (translation != null && !translation.equals("")) { |
| Resource icon = resourceProvider.getResource(translation); |
| if (icon != null) { |
| table.setColumnIcon(columnId, icon); |
| } |
| } |
| } else { |
| table.setColumnIcon(columnId, resourceProvider.getResource(yColumn.getIcon())); |
| } |
| } |
| // Blob check to display a blob image |
| if ((yColumn.getType() == String.class) |
| && ((yColumn.getProperties() != null) && (!yColumn.getProperties().isEmpty()))) { |
| Stream<Entry<String, String>> propertyStream = yColumn.getProperties().stream() |
| .filter(prop -> prop.getKey().equalsIgnoreCase(ILayoutingStrategy.PROPERTY_BLOB)); |
| // Only if one 'Blob' or 'blob' property entry exists |
| if (propertyStream.count() == 1) { |
| String displayResolution = yColumn.getProperties().stream() |
| .filter(prop -> prop.getKey().equalsIgnoreCase(ILayoutingStrategy.PROPERTY_BLOB)) |
| .map(p -> p.getValue()).collect(Collectors.joining()); |
| // check to avoid an IllegalArgumentException adding |
| // an |
| // already existing ColumnGenerator. |
| if (table.getColumnGenerator(columnId) == null) { |
| table.addGeneratedColumn(columnId, new Table.ColumnGenerator() { |
| |
| @Override |
| public Component generateCell(Table source, Object itemId, Object columnId) { |
| Item item = table.getItem(itemId); |
| BlobComponent blob = new BlobComponent(blobService, (String) item.getItemProperty(columnId).getValue(), Integer.parseInt(displayResolution)); |
| return blob; |
| } |
| }); |
| } |
| } |
| } |
| |
| } |
| } |
| |
| // apply the converters |
| // |
| for ( |
| |
| YColumn yColumn : modelAccess.yField.getColumns()) { |
| if (yColumn.getConverter() == null) { |
| // try to derive the converter from the datatype property at |
| // field level |
| String columnId = yColumn.getPropertyPath(); |
| Class<?> resultClass = table.getContainerDataSource().getType(columnId); |
| if (Number.class.isAssignableFrom(resultClass) |
| && PropertiesUtil.hasKey(type, columnId, "decimalformat")) { |
| String format = PropertiesUtil.getValue(type, columnId, "decimalformat"); |
| if (format != null && !format.isEmpty()) { |
| table.setConverter(columnId, new StringToFormattedNumberConverter(format, |
| (Class<? extends Number>) resultClass)); |
| } |
| } |
| } else { |
| @SuppressWarnings("rawtypes") |
| Converter converter = (Converter) DelegatingConverterFactory.getInstance().createConverter( |
| getViewContext(), |
| (IConverterEditpart) ElementEditpart.getEditpart(getViewContext(), yColumn.getConverter())); |
| if (converter != null) { |
| String columnId = yColumn.getPropertyPath(); |
| table.setConverter(columnId, converter); |
| } |
| } |
| } |
| } |
| |
| // apply the sort order |
| applySortOrder(); |
| |
| applyCellStyles(); |
| |
| // apply the dirty flag |
| // applyDirtyFlag(type); |
| } |
| |
| @SuppressWarnings("serial") |
| protected void applyCellStyles() { |
| table.setCellStyleGenerator(new Table.CellStyleGenerator() { |
| |
| @Override |
| public String getStyle(Table source, Object itemId, Object propertyId) { |
| if (itemId == null || propertyId == null) { |
| return ""; |
| } |
| if (Number.class.isAssignableFrom(source.getContainerDataSource().getType(propertyId))) { |
| return " v-align-right"; |
| } |
| return ""; |
| } |
| }); |
| } |
| |
| // protected void applyDirtyFlag(Class<?> type) { |
| // final String dirtyProperty = getDirtyProperty(type); |
| // // if a dirty property is available, we use it |
| // if (dirtyProperty != null) { |
| // table.setCellStyleGenerator(new Table.CellStyleGenerator() { |
| // private static final long serialVersionUID = -2462674164411654020L; |
| // @Override |
| // public String getStyle(Table source, Object itemId, |
| // Object propertyId) { |
| // if (propertyId == null) { |
| // return null; |
| // } |
| // if (propertyId.equals(dirtyProperty)) { |
| // try { |
| // boolean dirty = DtoUtils.invokeDirtyGetter(itemId); |
| // return dirty ? "dirty" : null; |
| // } catch (IllegalAccessException e) { |
| // } |
| // } else { |
| // Class<?> propertyType = source.getContainerDataSource() |
| // .getType(propertyId); |
| // if (Number.class.isAssignableFrom(propertyType)) { |
| // return "v-align-right"; |
| // } |
| // } |
| // } |
| // table.setCellStyleGenerator(new Table.CellStyleGenerator() { |
| // @Override |
| // public String getStyle(Table source, Object itemId, |
| // Object propertyId) { |
| // if (propertyId == null) { |
| // return null; |
| // } |
| // }); |
| // } |
| |
| protected void applySortOrder() { |
| if (!modelAccess.yField.getSortOrder().isEmpty() |
| && table.getContainerDataSource() instanceof Container.Sortable) { |
| List<String> sortCol = new ArrayList<>(); |
| List<Boolean> sortDirection = new ArrayList<>(); |
| for (YSortColumn yColumn : modelAccess.yField.getSortOrder()) { |
| // add the nested sort columns to the container |
| if (isNestedColumn(yColumn)) { |
| if (table.getContainerDataSource() instanceof INestedPropertyAble) { |
| INestedPropertyAble<?> container = (INestedPropertyAble<?>) table.getContainerDataSource(); |
| container.addNestedContainerProperty(yColumn.getPropertyPath()); |
| } |
| } |
| |
| sortCol.add(yColumn.getPropertyPath()); |
| sortDirection.add(yColumn.isAsc()); |
| } |
| Container.Sortable sortable = (Container.Sortable) table.getContainerDataSource(); |
| |
| boolean[] asc = new boolean[sortDirection.size()]; |
| for (int i = 0; i < sortDirection.size(); i++) { |
| asc[i] = sortDirection.get(i); |
| } |
| |
| ILifecycleService lfService = getViewContext().getService(ILifecycleService.class.getName()); |
| if(!lfService.getState().equals(ILifecycleEvent.TYPE_RENDERING)) { |
| sortable.sort(sortCol.toArray(new String[sortCol.size()]), asc); |
| if (!sortCol.isEmpty()) { |
| table.setSortContainerPropertyId(sortCol.get(0)); |
| table.setSortAscending(asc[0]); |
| } |
| } |
| |
| } |
| } |
| |
| public void doSort() { |
| if (table != null) { |
| table.sort(); |
| } |
| } |
| |
| /** |
| * Gets the dirty property. |
| * |
| * @param type |
| * the type |
| * @return the dirty property |
| */ |
| protected String getDirtyProperty(Class<?> type) { |
| String temp = null; |
| java.lang.reflect.Field dirtyField = DtoUtils.getDirtyField(type); |
| if (dirtyField != null) { |
| temp = dirtyField.getName(); |
| } |
| return temp; |
| } |
| |
| /** |
| * Checks if is nested column. |
| * |
| * @param yColumn |
| * the y column |
| * @return true, if is nested column |
| */ |
| protected boolean isNestedColumn(YColumn yColumn) { |
| return yColumn.getPropertyPath() != null && yColumn.getPropertyPath().contains("."); |
| } |
| |
| /** |
| * Checks if is nested column. |
| * |
| * @param yColumn |
| * the y column |
| * @return true, if is nested column |
| */ |
| protected boolean isNestedColumn(YSortColumn yColumn) { |
| return yColumn.getPropertyPath() != null && yColumn.getPropertyPath().contains("."); |
| } |
| |
| /** |
| * Returns the column header. |
| * |
| * @param yColumn |
| * the y column |
| * @return the column header |
| */ |
| private String getColumnHeader(YColumn yColumn) { |
| YDatadescription yDt = yColumn.getDatadescription(); |
| if (yDt == null) { |
| return yColumn.getPropertyPath(); |
| } |
| |
| String result = null; |
| II18nService service = getI18nService(); |
| if (service != null && yDt.getLabelI18nKey() != null) { |
| result = service.getValue(yDt.getLabelI18nKey(), getLocale()); |
| } |
| |
| if (result == null || result.equals("")) { |
| result = yDt.getLabel(); |
| } |
| |
| if (result == null || result.equals("")) { |
| result = yColumn.getPropertyPath(); |
| } |
| |
| return result; |
| } |
| |
| /** |
| * To align. |
| * |
| * @param alignment |
| * the alignment |
| * @return the align |
| */ |
| private Align toAlign(YFlatAlignment alignment) { |
| switch (alignment) { |
| case LEFT: |
| return Align.LEFT; |
| case CENTER: |
| return Align.CENTER; |
| case RIGHT: |
| return Align.RIGHT; |
| } |
| return Align.LEFT; |
| } |
| |
| /* |
| * (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() { |
| |
| // applies the column properties |
| if (applyColumns) { |
| applyColumns(); |
| } |
| |
| Util.applyCaptions(getI18nService(), modelAccess.getLabel(), modelAccess.getLabelI18nKey(), getLocale(), table); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.ecview.core.common.filter.IFilterablePresentation# |
| * applyFilter(java.lang.Object) |
| */ |
| @Override |
| public void applyFilter(Object filter) { |
| Container container = table.getContainerDataSource(); |
| if (container instanceof Container.Filterable) { |
| Container.Filterable filterable = (Filterable) container; |
| filterable.removeAllContainerFilters(); |
| if (filter != null) { |
| filterable.addContainerFilter((Filter) filter); |
| } else if (container instanceof ILazyRefreshFilterable) { |
| ILazyRefreshFilterable lazyFilterable = (ILazyRefreshFilterable) container; |
| lazyFilterable.removeAllContainerFilters(); |
| } |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common. |
| * AbstractFieldWidgetPresenter#doGetField() |
| */ |
| @Override |
| protected Field<?> doGetField() { |
| return table; |
| } |
| |
| /* |
| * (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); |
| } else if (bindableValue instanceof YEmbeddableMultiSelectionEndpoint) { |
| return internalGetMultiSelectionEndpoint(); |
| } |
| 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(ExtensionModelPackage.Literals.YTABLE__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(ExtensionModelPackage.Literals.YTABLE__SELECTION, |
| yEndpoint.getAttributePath()); |
| |
| // return the observable value for text |
| return ECViewModelBindable.observeValue(castEObject(getModel()), attributePath, modelAccess.yField.getType(), |
| modelAccess.yField.getEmfNsURI()); |
| } |
| |
| /** |
| * Returns the observable to observe the selection. |
| * |
| * @return the i observable list |
| */ |
| protected IObservableList internalGetMultiSelectionEndpoint() { |
| // return the observable value for text |
| return EMFProperties.list(ExtensionModelPackage.Literals.YTABLE__MULTI_SELECTION).observe(getModel()); |
| } |
| |
| /** |
| * Creates the bindings for the given values. |
| * |
| * @param yField |
| * the y field |
| * @param field |
| * the field |
| */ |
| protected void createBindings(YTable yField, Table field) { |
| // create the model binding from ridget to ECView-model |
| registerBinding(createBindingsContainerContents(castEObject(getModel()), |
| ExtensionModelPackage.Literals.YTABLE__COLLECTION, field, yField.getType(), containerReadonly)); |
| |
| // create the model binding from ridget to ECView-model |
| if (modelAccess.yField.getSelectionType() == YSelectionType.MULTI) { |
| // create the model binding from ridget to ECView-model |
| registerBinding(createBindingsMultiSelection(castEObject(getModel()), |
| ExtensionModelPackage.Literals.YTABLE__MULTI_SELECTION, field, yField.getType())); |
| } else { |
| // create the model binding from ridget to ECView-model |
| registerBinding(createBindingsSelection(castEObject(getModel()), |
| ExtensionModelPackage.Literals.YTABLE__SELECTION, field, yField.getType())); |
| |
| } |
| |
| super.createBindings(yField, field, null); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.ecview.core.common.presentation.IWidgetPresentation# |
| * getWidget() |
| */ |
| @Override |
| public Component getWidget() { |
| return table; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.ecview.core.common.presentation.IWidgetPresentation# |
| * isRendered() |
| */ |
| @Override |
| public boolean isRendered() { |
| return table != null; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void doUnrender() { |
| if (table != null) { |
| |
| // unbind all active bindings |
| unbind(); |
| |
| Component parent = (table.getParent()); |
| if (parent != null && parent instanceof ComponentContainer) { |
| ((ComponentContainer) parent).removeComponent(table); |
| } |
| |
| // remove assocations |
| unassociateWidget(table); |
| |
| table = null; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| protected void internalDispose() { |
| try { |
| unrender(); |
| |
| modelAccess.yField.eAdapters().remove(adapter); |
| |
| } finally { |
| super.internalDispose(); |
| } |
| } |
| |
| /** |
| * A helper class. |
| */ |
| private static class ModelAccess { |
| |
| /** The y field. */ |
| private final YTable yField; |
| |
| /** |
| * Instantiates a new model access. |
| * |
| * @param yField |
| * the y field |
| */ |
| public ModelAccess(YTable 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 class CustomTable extends Table { |
| |
| /** The item icon property id. */ |
| private Object itemIconPropertyId; |
| private String itemIdHash; |
| private boolean updateMode; |
| |
| private Timer sortTimer; |
| private boolean isSorting; |
| |
| @SuppressWarnings("unchecked") |
| CustomTable() { |
| addValueChangeListener(e -> { |
| if (getContainerDataSource() instanceof IBeanToUniqueHashIdProvider) { |
| IBeanToUniqueHashIdProvider<Object> hashIdProvider = (IBeanToUniqueHashIdProvider<Object>) getContainerDataSource(); |
| Object selection = e.getProperty().getValue(); |
| this.itemIdHash = hashIdProvider.getUniqueHashId(selection); |
| } |
| }); |
| addItemSetChangeListener(e -> { |
| if (isSorting || getSortContainerPropertyId() == null || getUI() == null) { |
| return; |
| } |
| if (sortTimer != null) { |
| sortTimer.cancel(); |
| } |
| sortTimer = new Timer(); |
| sortTimer.schedule(new TimerTask() { |
| @Override |
| public void run() { |
| try { |
| isSorting = true; |
| getUI().accessSynchronously(() -> { |
| sort(); |
| if (modelAccess.yField.isScrollToBottom()) { |
| setCurrentPageFirstItemIndex(size() - 1); |
| } |
| }); |
| } finally { |
| isSorting = false; |
| } |
| } |
| }, 125); |
| }); |
| } |
| |
| /* |
| * (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() |
| */ |
| @Override |
| public Object getItemIconPropertyId() { |
| return itemIconPropertyId != null ? itemIconPropertyId : super.getItemIconPropertyId(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see com.vaadin.ui.AbstractSelect#getItemIcon(java.lang.Object) |
| */ |
| @Override |
| 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(); |
| if (icon instanceof String) { |
| return new ThemeResource((String) icon); |
| } |
| } |
| return null; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see com.vaadin.ui.Table#formatPropertyValue(java.lang.Object, |
| * java.lang.Object, com.vaadin.data.Property) |
| */ |
| @Override |
| @SuppressWarnings({ "unchecked", "rawtypes" }) |
| protected String formatPropertyValue(Object rowId, Object colId, Property<?> property) { |
| if (property == null) { |
| return ""; |
| } |
| Converter<String, Object> converter = null; |
| |
| if (hasConverter(colId)) { |
| converter = getConverter(colId); |
| } else { |
| converter = (Converter) ConverterUtil.getConverter(String.class, property.getType(), getSession()); |
| } |
| Object value = property.getValue(); |
| if (converter != null) { |
| return converter.convertToPresentation(value, String.class, getLocale()); |
| } else { |
| if (value instanceof Enum<?>) { |
| return I18nUtil.translateEnum(getI18nService(), value, getLocale()); |
| } else if (value instanceof Boolean) { |
| return I18nUtil.translateBoolean(getI18nService(), (Boolean) value, getLocale()); |
| } else if (value instanceof Number) { |
| return I18nUtil.translateNumber(getI18nService(), (Number) value, getLocale()); |
| } |
| } |
| return (null != value) ? value.toString() : ""; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see com.vaadin.ui.AbstractField#getErrorMessage() |
| */ |
| @Override |
| public ErrorMessage getErrorMessage() { |
| if (isDisposed()) { |
| // after disposal, Vaadin will call this method once. |
| return null; |
| } |
| |
| ErrorMessage message = super.getErrorMessage(); |
| reportValidationError(message); |
| return message; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see com.vaadin.ui.AbstractField#focus() |
| */ |
| @Override |
| public void focus() { |
| super.focus(); |
| |
| setValue(getCurrentPageFirstItemId()); |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| public void setContainerDataSource(Container newDataSource) { |
| super.setContainerDataSource(newDataSource); |
| |
| if (getContainerDataSource() instanceof DeepResolvingBeanItemContainer) { |
| @SuppressWarnings("rawtypes") |
| final DeepResolvingBeanItemContainer ds = (DeepResolvingBeanItemContainer) getContainerDataSource(); |
| ds.addItemSetChangeListener(e -> { |
| |
| // lazy update the table selection |
| if (!updateMode && itemIdHash != null) { |
| updateMode = true; |
| final String targetItemIdHash = itemIdHash; |
| getUI().accessSynchronously(() -> { |
| for (Object itemId : e.getContainer().getItemIds()) { |
| if (targetItemIdHash.equals(ds.getUniqueHashId(itemId))) { |
| table.setValue(itemId); |
| break; |
| } |
| } |
| updateMode = false; |
| }); |
| } |
| }); |
| } |
| } |
| } |
| |
| private class AdapterCustom extends AdapterImpl { |
| @Override |
| public void notifyChanged(Notification notification) { |
| int featureId = notification.getFeatureID(YTable.class); |
| switch (notification.getEventType()) { |
| case Notification.SET: |
| if (featureId == ExtensionModelPackage.YTABLE__DO_SORT) { |
| doSort(); |
| } |
| break; |
| default: |
| |
| } |
| } |
| } |
| |
| @Override |
| public void receiveEvent(EventDispatcherEvent event) { |
| switch (event.getCommand()) { |
| case REFRESH: |
| // if(!event.getSender().equals("net.osbee.sample.foodmart.tables.CashRegister")) |
| // { |
| // if(event.getTopic().equals("net.osbee.sample.foodmart.entities.CashRegister")){ |
| refreshRows(); |
| // } |
| // } |
| break; |
| case SELECT: |
| break; |
| default: |
| break; |
| } |
| } |
| |
| @Override |
| public void attach(AttachEvent event) { |
| eventDispatcher.addEventReceiver(this); |
| } |
| |
| @Override |
| public void detach(DetachEvent event) { |
| eventDispatcher.removeEventReceiver(this); |
| } |
| } |