| /** |
| * |
| * 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.grid.presentation; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.Objects; |
| import java.util.Set; |
| |
| import org.eclipse.core.databinding.Binding; |
| 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.core.databinding.observable.value.WritableValue; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.impl.AdapterImpl; |
| import org.eclipse.emf.databinding.EMFObservables; |
| import org.eclipse.emf.databinding.EMFProperties; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.osbp.dsl.semantic.dto.util.NamingConventionsUtil; |
| 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.editpart.IFieldEditpart; |
| import org.eclipse.osbp.ecview.core.common.model.core.YConverter; |
| 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.YField; |
| import org.eclipse.osbp.ecview.core.databinding.emf.model.ECViewModelBindable; |
| import org.eclipse.osbp.ecview.core.extension.model.extension.YSearchField; |
| import org.eclipse.osbp.ecview.core.extension.model.extension.YSelectionType; |
| import org.eclipse.osbp.ecview.core.ui.core.editparts.extension.ISearchFieldEditpart; |
| import org.eclipse.osbp.ecview.core.util.emf.ModelUtil; |
| import org.eclipse.osbp.ecview.extension.grid.CxGrid; |
| import org.eclipse.osbp.ecview.extension.grid.CxGridCellStyleGenerator; |
| import org.eclipse.osbp.ecview.extension.grid.CxGridColumn; |
| import org.eclipse.osbp.ecview.extension.grid.CxGridFactory; |
| import org.eclipse.osbp.ecview.extension.grid.CxGridFooterRow; |
| import org.eclipse.osbp.ecview.extension.grid.CxGridGroupable; |
| import org.eclipse.osbp.ecview.extension.grid.CxGridGroupedCell; |
| import org.eclipse.osbp.ecview.extension.grid.CxGridHeaderRow; |
| import org.eclipse.osbp.ecview.extension.grid.CxGridMetaCell; |
| import org.eclipse.osbp.ecview.extension.grid.CxGridPackage; |
| import org.eclipse.osbp.ecview.extension.grid.CxGridSortable; |
| import org.eclipse.osbp.ecview.extension.grid.editparts.IGridCellStyleGeneratorEditpart; |
| import org.eclipse.osbp.ecview.extension.grid.editparts.IGridColumnEditpart; |
| import org.eclipse.osbp.ecview.extension.grid.editparts.IGridEditpart; |
| import org.eclipse.osbp.ecview.extension.grid.editparts.presentation.IGridPresentation; |
| import org.eclipse.osbp.ecview.extension.grid.memento.CxGridMemento; |
| import org.eclipse.osbp.ecview.extension.grid.memento.CxGridMementoColumn; |
| import org.eclipse.osbp.ecview.extension.grid.memento.CxGridMementoFactory; |
| import org.eclipse.osbp.ecview.extension.grid.memento.CxGridMementoSortable; |
| import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridNestedConverter; |
| import org.eclipse.osbp.runtime.common.annotations.DtoUtils; |
| import org.eclipse.osbp.runtime.common.dispose.AbstractDisposable; |
| 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.II18nService; |
| import org.eclipse.osbp.runtime.common.state.ISharedStateContext; |
| import org.eclipse.osbp.runtime.designer.api.IDesignerService.IDesignListener; |
| import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.IBindingManager; |
| import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.AbstractEmbeddedWidgetPresenter; |
| 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.IBeanSearchService; |
| import org.eclipse.osbp.runtime.web.vaadin.common.data.IBeanSearchServiceFactory; |
| import org.eclipse.osbp.runtime.web.vaadin.common.data.INestedPropertyAble; |
| import org.eclipse.osbp.runtime.web.vaadin.components.fields.search.ISearchField; |
| import org.eclipse.osbp.runtime.web.vaadin.databinding.VaadinProperties; |
| import org.eclipse.osbp.runtime.web.vaadin.databinding.values.IVaadinObservableList; |
| import org.eclipse.osbp.runtime.web.vaadin.databinding.values.IVaadinObservableValue; |
| import org.eclipse.osbp.runtime.web.vaadin.databinding.values.SetToListAdapter; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.vaadin.data.Container; |
| import com.vaadin.data.fieldgroup.FieldGroup; |
| import com.vaadin.data.fieldgroup.FieldGroup.CommitEvent; |
| import com.vaadin.data.fieldgroup.FieldGroup.CommitException; |
| import com.vaadin.data.sort.Sort; |
| import com.vaadin.data.sort.SortOrder; |
| import com.vaadin.data.util.IndexedContainer; |
| import com.vaadin.data.util.converter.Converter; |
| import com.vaadin.data.util.filter.And; |
| import com.vaadin.data.util.filter.Compare; |
| import com.vaadin.event.SortEvent; |
| import com.vaadin.shared.data.sort.SortDirection; |
| import com.vaadin.ui.Component; |
| import com.vaadin.ui.Field; |
| import com.vaadin.ui.Grid; |
| import com.vaadin.ui.Grid.ColumnVisibilityChangeEvent; |
| import com.vaadin.ui.Grid.FooterRow; |
| import com.vaadin.ui.Grid.HeaderRow; |
| import com.vaadin.ui.renderers.Renderer; |
| |
| /** |
| * This presenter is responsible to render a text field on the given layout. |
| */ |
| public class GridPresentation extends AbstractEmbeddedWidgetPresenter<Grid> implements IGridPresentation<Grid>, // NOSONAR |
| IDesignListener { |
| |
| /** The Constant LOGGER. */ |
| private static final Logger LOGGER = LoggerFactory.getLogger(GridPresentation.class); |
| |
| /** The grid. */ |
| private CustomGrid grid; |
| |
| /** The model access. */ |
| private ModelAccess modelAccess; |
| |
| /** The user changed handler. */ |
| private UserChangedHandler userChangedHandler = new UserChangedHandler(); |
| |
| /** The create columns. */ |
| private boolean createColumns; |
| |
| /** The columns. */ |
| private Set<ColumnWrapper> columns = new HashSet<>(); |
| |
| /** The grouping headers. */ |
| private Map<CxGridHeaderRow, HeaderRow> groupingHeaders = new HashMap<CxGridHeaderRow, HeaderRow>(); |
| |
| /** The grouping footers. */ |
| private Map<CxGridFooterRow, FooterRow> groupingFooters = new HashMap<CxGridFooterRow, FooterRow>(); |
| |
| /** The filtering header. */ |
| private HeaderRow filteringHeader; |
| |
| /** The filtering header fields. */ |
| private Map<CxGridColumn, ISearchFieldEditpart> filteringHeaderFields = new HashMap<CxGridColumn, ISearchFieldEditpart>(); |
| |
| /** The selection binding. */ |
| private Binding selectionBinding; |
| |
| /** The filter changed tracker. */ |
| // to handle changed filters |
| private WritableValue filterChangedTracker; |
| |
| /** The current memento. */ |
| private CxGridMemento currentMemento; |
| |
| /** The cell filters. */ |
| private GridCellFilter cellFilters; |
| |
| /** |
| * The constructor. |
| * |
| * @param editpart |
| * The editpart of that editpart. |
| */ |
| public GridPresentation(IElementEditpart editpart) { |
| super((IGridEditpart) editpart); |
| this.modelAccess = new ModelAccess((CxGrid) editpart.getModel()); |
| } |
| |
| /* |
| * (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 (createColumns) { |
| createColumns(); |
| } |
| |
| Util.applyCaptions(getI18nService(), modelAccess.getLabel(), modelAccess.getLabelI18nKey(), getLocale(), grid); |
| |
| grid.setEditorCancelCaption(Util.getCaption(getI18nService(), "Cancel", |
| modelAccess.yField.getEditorCancelI18nLabelKey(), getLocale())); |
| grid.setEditorSaveCaption( |
| Util.getCaption(getI18nService(), "Save", modelAccess.yField.getEditorSaveI18nLabelKey(), getLocale())); |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.ecview.extension.grid.editparts.presentation. |
| * IGridPresentation#setFilter(java.util.Map) |
| */ |
| @Override |
| public void setFilter(Map<String, Object> filter) { |
| List<Container.Filter> filters = new ArrayList<>(); |
| for (Map.Entry<String, Object> entry : filter.entrySet()) { |
| filters.add(new Compare.Equal(entry.getKey(), entry.getValue())); |
| } |
| |
| Container.Filterable filterable = (Container.Filterable) grid.getContainerDataSource(); |
| filterable.removeAllContainerFilters(); |
| filterable.addContainerFilter(new And(filters.toArray(new Container.Filter[filters.size()]))); |
| } |
| |
| /** |
| * Applies the column setting to the grid. |
| */ |
| protected void createColumns() { |
| |
| resetHeader(); |
| resetFooter(); |
| |
| // reset the column reference in the editparts |
| for (CxGridColumn cxColumn : modelAccess.yField.getColumns()) { |
| IGridColumnEditpart editpart = ModelUtil.getEditpart(getViewContext(), cxColumn); |
| editpart.setColumnReference(null); |
| } |
| |
| // set the visible columns and icons |
| List<String> visibleColumns = new ArrayList<>(); |
| List<CxGridColumn> visibleColumnObjs = new ArrayList<>(); |
| Collection<?> propertyIds = grid.getContainerDataSource().getContainerPropertyIds(); |
| for (CxGridColumn cxColumn : modelAccess.yField.getColumns()) { |
| if (!cxColumn.isHidden() |
| && (propertyIds.contains(cxColumn.getPropertyPath()) || isNestedColumn(cxColumn))) { |
| visibleColumns.add(cxColumn.getPropertyPath()); |
| visibleColumnObjs.add(cxColumn); |
| if(cxColumn.getLabelI18nKey() == null || cxColumn.getLabelI18nKey().equals("")){ |
| cxColumn.setLabelI18nKey(cxColumn.getPropertyPath()); |
| } |
| YConverter converter = cxColumn.getConverter(); |
| if (converter instanceof CxGridNestedConverter) { |
| CxGridNestedConverter nestedConverter = (CxGridNestedConverter) converter; |
| } |
| } |
| } |
| |
| if (visibleColumns.size() > 0) { |
| // reset all columns |
| grid.removeAllColumns(); |
| } |
| |
| // add nested properties |
| if (grid.getContainerDataSource() instanceof INestedPropertyAble) { |
| INestedPropertyAble<?> container = (INestedPropertyAble<?>) grid.getContainerDataSource(); |
| for (String property : visibleColumns) { |
| if (property.contains(".")) { |
| container.addNestedContainerProperty(property); |
| } |
| } |
| } |
| |
| if (visibleColumns.size() > 0) { |
| // create the columns based on the model |
| // |
| grid.setColumns(visibleColumns.toArray(new Object[visibleColumns.size()])); |
| grid.setColumnOrder(visibleColumns.toArray(new Object[visibleColumns.size()])); |
| |
| // traverse the columns again and set other properties |
| for (CxGridColumn cxColumn : modelAccess.yField.getColumns()) { |
| if (!cxColumn.isHidden() |
| && (propertyIds.contains(cxColumn.getPropertyPath()) || isNestedColumn(cxColumn))) { |
| String columnId = cxColumn.getPropertyPath(); |
| |
| IGridColumnEditpart editpart = ModelUtil.getEditpart(getViewContext(), cxColumn); |
| Grid.Column column = grid.getColumn(columnId); |
| |
| editpart.setColumnReference(new ColumnWrapper(cxColumn, column)); |
| editpart.initializeColumn(); |
| } |
| } |
| } else { |
| Class<?> rootType = modelAccess.yField.getType(); |
| // order columns by field order in rootType |
| List<String> fieldNames = DtoUtils.getFieldNames(rootType); |
| for (Iterator<String> iterator = fieldNames.iterator(); iterator.hasNext();) { |
| String name = iterator.next(); |
| if (grid.getColumn(name) == null) { |
| iterator.remove(); |
| } |
| } |
| grid.setColumnOrder(fieldNames.toArray(new Object[fieldNames.size()])); |
| // remove not used fields |
| for (Grid.Column col : new ArrayList<>(grid.getColumns())) { |
| String propId = (String) col.getPropertyId(); |
| if (!propId.contains(".")) { |
| // only check not nested fields |
| if (DtoUtils.isIdField(rootType, propId) || DtoUtils.isVersionField(rootType, propId) |
| || DtoUtils.isDisposeField(rootType, propId) || DtoUtils.isDirtyField(rootType, propId)) { |
| grid.removeColumn(propId); |
| } |
| } |
| } |
| } |
| |
| updateCellStyleGenerator(); |
| createHeaderMetaCells(); |
| createFilteringHeader(); |
| createFooterMetaCells(); |
| createSortOrder(); |
| } |
| |
| /** |
| * Creates the sort order. |
| */ |
| protected void createSortOrder() { |
| CxGrid cxGrid = modelAccess.yField; |
| |
| if (cxGrid.getSortOrder().size() > 0) { |
| Sort sort = null; |
| for (CxGridSortable memSort : cxGrid.getSortOrder()) { |
| if (sort == null) { |
| sort = Sort.by(memSort.getColumn().getPropertyId(), toDirection(memSort)); |
| } else { |
| sort = sort.then(memSort.getColumn().getPropertyId(), toDirection(memSort)); |
| } |
| } |
| grid.sort(sort); |
| } |
| } |
| |
| /** |
| * Creates the header meta cells. |
| */ |
| protected void createHeaderMetaCells() { |
| |
| resetHeader(); |
| |
| // create the new header |
| CxGrid cxGrid = modelAccess.yField; |
| |
| for (CxGridHeaderRow cxHeader : cxGrid.getHeaders()) { |
| |
| boolean addedCells = false; |
| HeaderRow headerRow = grid.prependHeaderRow(); |
| groupingHeaders.put(cxHeader, headerRow); |
| |
| // create the grouping headers |
| // |
| for (CxGridGroupedCell groupingColumn : cxHeader.getGroupings()) { |
| if (groupingColumn.getGroupables().size() <= 1) { |
| continue; |
| } |
| addedCells = true; |
| |
| List<Grid.HeaderCell> headerCells = getCells(headerRow, groupingColumn); |
| Grid.HeaderCell cell = headerRow.join(headerCells.toArray(new Grid.HeaderCell[headerCells.size()])); |
| |
| // apply the caption of the cell |
| String caption = Util.getCaption(getI18nService(), groupingColumn.getLabel(), |
| groupingColumn.getLabelI18nKey(), getLocale()); |
| |
| if (groupingColumn.isUseHTML()) { |
| cell.setHtml(caption); |
| } else { |
| cell.setText(caption); |
| } |
| } |
| |
| if (!addedCells) { |
| grid.removeHeaderRow(headerRow); |
| } |
| |
| // create the custom cells |
| // |
| for (CxGridMetaCell cxCell : cxHeader.getCustomCells()) { |
| Grid.HeaderCell cell = headerRow.getCell(cxCell.getTarget().getPropertyId()); |
| if (cell == null) { |
| continue; |
| } |
| |
| if (cxCell.getElement() != null) { |
| IEmbeddableEditpart ep = ModelUtil.getEditpart(getViewContext(), cxCell.getElement()); |
| if (ep != null) { |
| Component component = (Component) ep.render(null); |
| cell.setComponent(component); |
| } |
| } else { |
| String caption = Util.getCaption(getI18nService(), cxCell.getLabel(), cxCell.getLabelI18nKey(), |
| getLocale()); |
| if (cxCell.isUseHTML()) { |
| cell.setHtml(caption); |
| } else { |
| cell.setText(caption); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Reset header. |
| */ |
| protected void resetHeader() { |
| // reset the old header |
| for (HeaderRow header : groupingHeaders.values()) { |
| grid.removeHeaderRow(header); |
| } |
| groupingHeaders.clear(); |
| |
| // dispose the cell component field |
| // |
| for (CxGridHeaderRow cxHeader : modelAccess.yField.getHeaders()) { |
| for (CxGridMetaCell cxCell : cxHeader.getCustomCells()) { |
| if (cxCell.getElement() != null) { |
| IEmbeddableEditpart ep = ModelUtil.findEditpart(cxCell.getElement()); |
| if (ep != null && !ep.isDisposed()) { |
| ep.requestDispose(); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Reset filter. |
| */ |
| protected void resetFilter() { |
| // dispose all the rendered search fields |
| for (ISearchFieldEditpart ep : filteringHeaderFields.values()) { |
| ep.dispose(); |
| } |
| filteringHeaderFields.clear(); |
| |
| if (cellFilters != null) { |
| cellFilters.destroy(); |
| cellFilters = null; |
| } else { |
| // reset the old header |
| if (filteringHeader != null) { |
| grid.removeHeaderRow(filteringHeader); |
| } |
| } |
| |
| filteringHeader = null; |
| } |
| |
| /** |
| * Creates the filtering header. |
| */ |
| protected void createFilteringHeader() { |
| |
| resetFilter(); |
| |
| CxGrid cxGrid = modelAccess.yField; |
| if (!cxGrid.isFilteringVisible()) { |
| return; |
| } |
| |
| if (cxGrid.isCustomFilters()) { |
| createCustomFilters(cxGrid); |
| } else { |
| createAutoFilters(); |
| } |
| } |
| |
| /** |
| * Creates the auto filters. |
| */ |
| protected void createAutoFilters() { |
| cellFilters = new GridCellFilter(grid); |
| for (CxGridColumn cxColumn : modelAccess.yField.getColumns()) { |
| Class<?> propertyType = cxColumn.getType(); |
| |
| String propertyPath = cxColumn.getPropertyPath(); |
| String filterPropertyPath = cxColumn.getPropertyPath(); |
| if (cxColumn.isEditsDto()) { |
| // if the column edits a dto, its property path points to |
| // the dto. Eg. person.country. |
| // So we need to use a special path for filtering which |
| // points |
| // to the domainkey. person.country.isoCode |
| filterPropertyPath = cxColumn.getFilterPropertyPathForEditsDto(); |
| } |
| if (Number.class.isAssignableFrom(propertyType) || isPrimitiveNumber(propertyType)) { |
| cellFilters.setNumberFilter(propertyPath, filterPropertyPath); |
| } else if (propertyType == String.class) { |
| cellFilters.setTextFilter(propertyPath, filterPropertyPath, true, false, null); |
| } else if (propertyType == Date.class) { |
| cellFilters.setDateFilter(propertyPath, filterPropertyPath); |
| // otherwise the column is to wide |
| grid.getColumn(propertyPath).setMaximumWidth(175); |
| } else if (propertyType == Boolean.class || propertyType == Boolean.TYPE) { |
| cellFilters.setBooleanFilter(propertyPath, filterPropertyPath); |
| } else if (propertyType.isEnum()) { |
| cellFilters.setComboBoxFilter(propertyPath, filterPropertyPath, |
| Arrays.asList(propertyType.getEnumConstants())); |
| } else if (DtoUtils.getDomainKeyField(propertyType) != null) { |
| cellFilters.setDtoFilter(propertyPath, propertyType, ""); |
| } |
| } |
| } |
| |
| /** |
| * Checks if is primitive number. |
| * |
| * @param propertyType |
| * the property type |
| * @return true, if is primitive number |
| */ |
| private boolean isPrimitiveNumber(Class<?> propertyType) { |
| return propertyType == Byte.TYPE || propertyType == Double.TYPE || propertyType == Float.TYPE |
| || propertyType == Integer.TYPE || propertyType == Long.TYPE || propertyType == Short.TYPE; |
| } |
| |
| /** |
| * Creates the custom filters. |
| * |
| * @param cxGrid |
| * the cx grid |
| */ |
| protected void createCustomFilters(CxGrid cxGrid) { |
| filteringHeader = grid.appendHeaderRow(); |
| for (CxGridColumn cxColumn : cxGrid.getColumns()) { |
| Grid.HeaderCell cell = filteringHeader.getCell(cxColumn.getPropertyId()); |
| if (cell == null) { |
| continue; |
| } |
| |
| // render the search field |
| YSearchField cxSearchField = cxColumn.getSearchField(); |
| if (cxSearchField != null) { |
| ISearchFieldEditpart editpart = ModelUtil.getEditpart(getViewContext(), cxSearchField); |
| filteringHeaderFields.put(cxColumn, editpart); |
| ISearchField component = (ISearchField) editpart.render(null); |
| component.bindFilterChanged(filterChangedTracker); |
| |
| cell.setComponent((Component) component); |
| } |
| } |
| } |
| |
| /** |
| * Refresh filter. |
| * |
| * @return the object |
| */ |
| private Object refreshFilter() { |
| Set<Container.Filter> filters = new HashSet<Container.Filter>(); |
| for (ISearchFieldEditpart ep : filteringHeaderFields.values()) { |
| Container.Filter f = (Container.Filter) ep.getFilter(); |
| if (f != null) { |
| filters.add(f); |
| } |
| } |
| |
| try { |
| Container.Filterable filterable = (Container.Filterable) grid.getContainerDataSource(); |
| filterable.removeAllContainerFilters(); |
| filterable.addContainerFilter(new And(filters.toArray(new Container.Filter[filters.size()]))); |
| } catch (Exception e) { |
| LOGGER.error("{}", e); |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Creates the footer meta cells. |
| */ |
| protected void createFooterMetaCells() { |
| |
| resetFooter(); |
| |
| // create the new header |
| CxGrid cxGrid = modelAccess.yField; |
| |
| for (CxGridFooterRow cxFooter : cxGrid.getFooters()) { |
| FooterRow footerRow = grid.appendFooterRow(); |
| groupingFooters.put(cxFooter, footerRow); |
| for (CxGridGroupedCell groupingColumn : cxFooter.getGroupings()) { |
| List<Grid.FooterCell> footerCells = getCells(footerRow, groupingColumn); |
| Grid.FooterCell cell = footerRow.join(footerCells.toArray(new Grid.FooterCell[footerCells.size()])); |
| |
| // apply the caption of the cell |
| String caption = Util.getCaption(getI18nService(), groupingColumn.getLabel(), |
| groupingColumn.getLabelI18nKey(), getLocale()); |
| |
| if (groupingColumn.isUseHTML()) { |
| cell.setHtml(caption); |
| } else { |
| cell.setText(caption); |
| } |
| } |
| |
| // create the custom cells |
| // |
| for (CxGridMetaCell cxCell : cxFooter.getCustomCells()) { |
| Grid.FooterCell cell = footerRow.getCell(cxCell.getTarget().getPropertyId()); |
| if (cell == null) { |
| continue; |
| } |
| |
| if (cxCell.getElement() != null) { |
| IEmbeddableEditpart ep = ModelUtil.getEditpart(getViewContext(), cxCell.getElement()); |
| if (ep != null) { |
| Component component = (Component) ep.render(null); |
| cell.setComponent(component); |
| } |
| } else { |
| String caption = Util.getCaption(getI18nService(), cxCell.getLabel(), cxCell.getLabelI18nKey(), |
| getLocale()); |
| if (cxCell.isUseHTML()) { |
| cell.setHtml(caption); |
| } else { |
| cell.setText(caption); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Reset footer. |
| */ |
| protected void resetFooter() { |
| // reset the old header |
| for (FooterRow header : groupingFooters.values()) { |
| grid.removeFooterRow(header); |
| } |
| groupingFooters.clear(); |
| |
| // dispose the cell component field |
| // |
| for (CxGridFooterRow cxFooter : modelAccess.yField.getFooters()) { |
| for (CxGridMetaCell cxCell : cxFooter.getCustomCells()) { |
| if (cxCell.getElement() != null) { |
| IEmbeddableEditpart ep = ModelUtil.findEditpart(cxCell.getElement()); |
| if (ep != null && !ep.isDisposed()) { |
| ep.requestDispose(); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Gets the cells. |
| * |
| * @param row |
| * the row |
| * @param groupingColumn |
| * the grouping column |
| * @return the cells |
| */ |
| private List<Grid.HeaderCell> getCells(HeaderRow row, CxGridGroupedCell groupingColumn) { |
| List<Grid.HeaderCell> cells = new ArrayList<Grid.HeaderCell>(); |
| for (CxGridGroupable column : groupingColumn.getGroupables()) { |
| if (column instanceof CxGridColumn) { |
| // if it is a column, then use the property id to get the cell |
| // |
| String id = ((CxGridColumn) column).getPropertyId(); |
| Grid.HeaderCell cell = row.getCell(id); |
| if (cell != null) { |
| cells.add(cell); |
| } |
| } else if (column instanceof CxGridGroupedCell) { |
| // if it is a grouped cell, then collect all properties of it |
| // |
| cells.addAll(getCells(row, (CxGridGroupedCell) column)); |
| } |
| } |
| return cells; |
| } |
| |
| /** |
| * Gets the cells. |
| * |
| * @param row |
| * the row |
| * @param groupingColumn |
| * the grouping column |
| * @return the cells |
| */ |
| private List<Grid.FooterCell> getCells(FooterRow row, CxGridGroupedCell groupingColumn) { |
| List<Grid.FooterCell> cells = new ArrayList<Grid.FooterCell>(); |
| for (CxGridGroupable column : groupingColumn.getGroupables()) { |
| if (column instanceof CxGridColumn) { |
| // if it is a column, then use the property id to get the cell |
| // |
| String id = ((CxGridColumn) column).getPropertyId(); |
| Grid.FooterCell cell = row.getCell(id); |
| if (cell != null) { |
| cells.add(cell); |
| } |
| } else if (column instanceof CxGridGroupedCell) { |
| // if it is a grouped cell, then collect all properties of it |
| // |
| cells.addAll(getCells(row, (CxGridGroupedCell) column)); |
| } |
| } |
| return cells; |
| } |
| |
| /** |
| * Checks if is nested column. |
| * |
| * @param cxColumn |
| * the cx column |
| * @return true, if is nested column |
| */ |
| protected boolean isNestedColumn(CxGridColumn cxColumn) { |
| return cxColumn.getPropertyPath() != null && cxColumn.getPropertyPath().contains("."); |
| } |
| |
| /** |
| * Returns the column header. |
| * |
| * @param cxColumn |
| * the cx column |
| * @return the column header |
| */ |
| private String getColumnHeader(CxGridColumn cxColumn) { |
| String result = null; |
| II18nService service = getI18nService(); |
| if (service != null && cxColumn.getLabelI18nKey() != null) { |
| result = service.getValue(cxColumn.getLabelI18nKey(), getLocale()); |
| } |
| |
| if (result == null || result.equals("")) { |
| result = cxColumn.getLabel(); |
| } |
| |
| if (result == null || result.equals("")) { |
| result = cxColumn.getPropertyPath(); |
| } |
| |
| return result; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common. |
| * AbstractVaadinWidgetPresenter#doCreateWidget(java.lang.Object) |
| */ |
| @SuppressWarnings({ "unchecked", "rawtypes", "serial" }) |
| @Override |
| public Grid doCreateWidget(Object parent) { |
| if (grid == null) { |
| |
| // tracks changes in the filters |
| filterChangedTracker = new WritableValue(); |
| filterChangedTracker.addValueChangeListener(e -> refreshFilter()); |
| |
| CxGrid cxGrid = modelAccess.yField; |
| |
| grid = new CustomGrid(); |
| setupComponent(grid, getCastedModel()); |
| |
| associateWidget(grid, cxGrid); |
| |
| if (modelAccess.isCssIdValid()) { |
| grid.setId(modelAccess.getCssID()); |
| } else { |
| grid.setId(getEditpart().getId()); |
| } |
| |
| if (modelAccess.isCssClassValid()) { |
| grid.addStyleName(modelAccess.getCssClass()); |
| } else { |
| grid.addStyleName(CSS_CLASS_CONTROL); |
| } |
| |
| cxGrid.eAdapters().add(new AdapterImpl() { |
| @Override |
| public void notifyChanged(Notification msg) { |
| if (msg.getFeature() == CxGridPackage.Literals.CX_GRID__SELECTION) { |
| Class<?> bean = modelAccess.yField.getType(); |
| if (bean != null) { |
| IEventDispatcher eventDispatcher = getViewContext() |
| .getService(IEventDispatcher.class.getName()); |
| if (eventDispatcher == null) { |
| return; |
| } |
| String topic = NamingConventionsUtil.toEntityName(bean.getSimpleName()) + "." |
| + DtoUtils.getIdField(bean).getName(); |
| EventDispatcherEvent evnt = new EventDispatcherEvent(EventDispatcherCommand.SELECT, topic, |
| toString()); |
| if (msg.getNewValue() != null) { |
| evnt.addItem(EventDispatcherDataTag.ID, DtoUtils.getIdValue(msg.getNewValue())); |
| } else { |
| evnt.addItem(EventDispatcherDataTag.ID, null); |
| } |
| eventDispatcher.sendEvent(evnt); |
| } |
| } |
| } |
| }); |
| |
| createColumns = false; |
| if (cxGrid.getType() == String.class) { |
| IndexedContainer datasource = new IndexedContainer(); |
| grid.setContainerDataSource(datasource); |
| } else { |
| if (cxGrid.getType() != null) { |
| IBeanSearchService<?> service = null; |
| IBeanSearchServiceFactory factory = getViewContext() |
| .getService(IBeanSearchServiceFactory.class.getName()); |
| if (factory != null) { |
| service = factory.createService(cxGrid.getType()); |
| } |
| if (cxGrid.isUseBeanService() && service != null) { |
| ISharedStateContext sharedState = getViewContext() |
| .getService(ISharedStateContext.class.getName()); |
| IEventDispatcher eventDispatcher = (IEventDispatcher) getViewContext() |
| .getService(IEventDispatcher.class.getName()); |
| BeanServiceLazyLoadingContainer<?> datasource = new BeanServiceLazyLoadingContainer(service, |
| cxGrid.getType(), sharedState, eventDispatcher); |
| |
| grid.setContainerDataSource(datasource); |
| } else { |
| DeepResolvingBeanItemContainer datasource = new DeepResolvingBeanItemContainer( |
| cxGrid.getType()); |
| grid.setContainerDataSource(datasource); |
| } |
| createColumns = 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" }); |
| grid.setContainerDataSource(container); |
| } |
| } |
| |
| // updates the selection type |
| updateSelectionType(); |
| |
| // creates the binding for the field |
| createBindings(cxGrid, grid); |
| |
| if (modelAccess.isCssClassValid()) { |
| grid.addStyleName(modelAccess.getCssClass()); |
| } |
| |
| // notify field about save |
| grid.getEditorFieldGroup().addCommitHandler(new FieldGroup.CommitHandler() { |
| @Override |
| public void preCommit(CommitEvent commitEvent) throws CommitException { |
| |
| } |
| |
| @Override |
| public void postCommit(CommitEvent commitEvent) throws CommitException { |
| Object itemId = grid.getEditedItemId(); |
| modelAccess.yField.setEditorSaved(itemId); |
| grid.refreshRows(itemId); |
| } |
| }); |
| |
| applyCaptions(); |
| |
| setupUserCallbacks(cxGrid); |
| |
| } |
| |
| return grid; |
| } |
| |
| /** |
| * // * Creates a predefined filter for the grid. // * // * @return // |
| */ |
| // private Filter createFilter() { |
| // CxGrid grid = modelAccess.yField; |
| // if (grid.getFilters().isEmpty()) { |
| // return null; |
| // } |
| // |
| // List<Filter> filters = new ArrayList<>(); |
| // for (YFilter yFilter : grid.getFilters()) { |
| // Filter filter = new Compare.Equal(yFilter.getPropertyPath(), |
| // yFilter.getFilterValue()); |
| // filters.add(filter); |
| // } |
| // return new And(filters.toArray(new Filter[filters.size()])); |
| // } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common. |
| * AbstractVaadinWidgetPresenter#castEObject(java.lang.Object) |
| */ |
| @Override |
| protected CxGrid castEObject(Object model) { |
| return (CxGrid) super.castEObject(model); |
| } |
| |
| /** |
| * Creates the bindings. |
| * |
| * @param yGrid |
| * the y grid |
| * @param widget |
| * the widget |
| */ |
| protected void createBindings(CxGrid yGrid, Grid widget) { |
| super.createBindings(yGrid, widget, null); |
| |
| // bind the editorEnabled property |
| IVaadinObservableValue editorEnabledUiObservable = VaadinProperties.accessor(Grid.class, "editorEnabled") |
| .observe(widget); |
| IObservableValue editorEnabledModelObservable = EMFObservables.observeValue(castEObject(yGrid), |
| CxGridPackage.eINSTANCE.getCxGrid_EditorEnabled()); |
| registerBinding(createBindings(editorEnabledUiObservable, editorEnabledModelObservable)); |
| |
| // bind the footerVisible property |
| IVaadinObservableValue footerVisibleUiObservable = VaadinProperties.accessor(Grid.class, "footerVisible") |
| .observe(widget); |
| IObservableValue footerVisibleModelObservable = EMFObservables.observeValue(castEObject(yGrid), |
| CxGridPackage.eINSTANCE.getCxGrid_FooterVisible()); |
| registerBinding(createBindings(footerVisibleUiObservable, footerVisibleModelObservable)); |
| // add a value change listener to update the memento |
| footerVisibleModelObservable.addValueChangeListener(e -> { |
| if (currentMemento == null || currentMemento.isFooterVisible() != grid.isFooterVisible()) { |
| updateMemento(); |
| } |
| }); |
| |
| // bind the headerVisible property |
| IVaadinObservableValue headerVisibleUiObservable = VaadinProperties.accessor(Grid.class, "headerVisible") |
| .observe(widget); |
| IObservableValue headerVisibleModelObservable = EMFObservables.observeValue(castEObject(yGrid), |
| CxGridPackage.eINSTANCE.getCxGrid_HeaderVisible()); |
| registerBinding(createBindings(headerVisibleUiObservable, headerVisibleModelObservable)); |
| // add a value change listener to update the memento |
| headerVisibleModelObservable.addValueChangeListener(e -> { |
| if (currentMemento == null || currentMemento.isHeaderVisible() != grid.isHeaderVisible()) { |
| updateMemento(); |
| } |
| }); |
| |
| // bind the columnReorderingAllowed property |
| IVaadinObservableValue columnReorderingAllowedUiObservable = VaadinProperties |
| .accessor(Grid.class, "columnReorderingAllowed").observe(widget); |
| IObservableValue columnReorderingAllowedModelObservable = EMFObservables.observeValue(castEObject(yGrid), |
| CxGridPackage.eINSTANCE.getCxGrid_ColumnReorderingAllowed()); |
| registerBinding(createBindings(columnReorderingAllowedUiObservable, columnReorderingAllowedModelObservable)); |
| |
| // bind the editorEnabled property |
| IVaadinObservableValue refreshUiObservable = VaadinProperties.accessor(CustomGrid.class, "refresh") |
| .observe(widget); |
| IObservableValue refreshModelObservable = EMFObservables.observeValue(castEObject(yGrid), |
| CxGridPackage.eINSTANCE.getCxGrid_SetLastRefreshTime()); |
| registerBinding(createBindings(refreshUiObservable, refreshModelObservable)); |
| |
| if (!modelAccess.yField.isUseBeanService()) { |
| // if use bean service, the container is responsible to collect |
| // data. So we must not have a binding from the container to the |
| // YGrid#collection attribute. |
| Container.Indexed container = grid.getContainerDataSource(); |
| // bind the rows |
| registerBinding(createBindings_ContainerContents(castEObject(getModel()), |
| CxGridPackage.Literals.CX_GRID__COLLECTION, (Container.ItemSetChangeNotifier) container, |
| yGrid.getType())); |
| } |
| // update the selection binding |
| updateSelectionBinding(); |
| } |
| |
| /** |
| * Updates the selection binding for the grid. |
| */ |
| protected void updateSelectionBinding() { |
| |
| CxGrid yGrid = modelAccess.yField; |
| |
| if (selectionBinding != null) { |
| unregisterBinding(selectionBinding); |
| selectionBinding = null; |
| } |
| |
| // create the model binding from widget to ECView-model |
| if (yGrid.getSelectionType() == YSelectionType.MULTI) { |
| selectionBinding = createBindingsMultiSelection(castEObject(getModel()), |
| CxGridPackage.Literals.CX_GRID__MULTI_SELECTION, grid, yGrid.getType()); |
| // create the model binding from widget to ECView-model |
| registerBinding(selectionBinding); |
| } else { |
| // create the model binding from widget to ECView-model |
| selectionBinding = createBindingsSingleSelection(castEObject(getModel()), |
| CxGridPackage.Literals.CX_GRID__SELECTION, grid, yGrid.getType()); |
| registerBinding(selectionBinding); |
| } |
| } |
| |
| @Override |
| public void updateSelectionType() { |
| |
| if (modelAccess.yField.getSelectionType() == YSelectionType.MULTI) { |
| grid.setSelectionMode(Grid.SelectionMode.MULTI); |
| } else { |
| grid.setSelectionModel(new CustomSelectionModel()); |
| } |
| |
| updateSelectionBinding(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.ecview.core.common.presentation.IWidgetPresentation# |
| * getWidget() |
| */ |
| @Override |
| public Grid getWidget() { |
| return grid; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.ecview.core.common.presentation.IWidgetPresentation# |
| * isRendered() |
| */ |
| @Override |
| public boolean isRendered() { |
| return grid != null; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common. |
| * AbstractVaadinWidgetPresenter#internalDispose() |
| */ |
| @Override |
| protected void internalDispose() { |
| try { |
| unrender(); |
| } finally { |
| super.internalDispose(); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common. |
| * AbstractVaadinWidgetPresenter#doUnrender() |
| */ |
| @Override |
| public void doUnrender() { |
| if (grid != null) { |
| |
| // unbind all active bindings |
| unbind(); |
| |
| // remove assocations |
| unassociateWidget(grid); |
| |
| resetFooter(); |
| resetHeader(); |
| resetFilter(); |
| |
| currentMemento = null; |
| grid = null; |
| } |
| } |
| |
| /** |
| * Creates the bindings single selection. |
| * |
| * @param model |
| * the model |
| * @param modelFeature |
| * the model feature |
| * @param field |
| * the field |
| * @param collectionType |
| * the collection type |
| * @return the binding |
| */ |
| protected Binding createBindingsSingleSelection(CxGrid model, EStructuralFeature modelFeature, final Grid field, |
| Class<?> collectionType) { |
| IBindingManager bindingManager = getViewContext() |
| .getService(org.eclipse.osbp.ecview.core.common.binding.IECViewBindingManager.class.getName()); |
| if (bindingManager != null) { |
| // bind the value of yText to textRidget |
| IObservableValue modelObservable = EMFProperties.value(modelFeature).observe(model); |
| IVaadinObservableValue uiObservable = VaadinProperties.propertyGridSelectionValueProperty(collectionType) |
| .observe(field); |
| final Binding binding = bindingManager.bindValue(uiObservable, modelObservable, null, null); |
| |
| return binding; |
| } |
| return null; |
| } |
| |
| /** |
| * Creates the bindings multi selection. |
| * |
| * @param model |
| * the model |
| * @param modelFeature |
| * the model feature |
| * @param field |
| * the field |
| * @param collectionType |
| * the collection type |
| * @return the binding |
| */ |
| protected Binding createBindingsMultiSelection(CxGrid model, EStructuralFeature modelFeature, final Grid field, |
| Class<?> collectionType) { |
| IBindingManager bindingManager = getViewContext() |
| .getService(org.eclipse.osbp.ecview.core.common.binding.IECViewBindingManager.class.getName()); |
| if (bindingManager != null) { |
| // bind the value of yText to textRidget |
| IObservableList modelObservable = EMFProperties.list(modelFeature).observe(model); |
| IVaadinObservableList uiObservable = new SetToListAdapter( |
| VaadinProperties.propertyGridSelectionSetPropertyAsSet(collectionType).observe(field), field); |
| |
| final Binding binding = bindingManager.bindList(uiObservable, modelObservable, null, null); |
| |
| return binding; |
| } |
| return null; |
| } |
| |
| /** |
| * Is used by the editpart to update the header. |
| */ |
| public void updateHeader() { |
| createHeaderMetaCells(); |
| updateMemento(); |
| } |
| |
| /** |
| * Is used by the editpart to update the footer. |
| */ |
| public void updateFooter() { |
| createFooterMetaCells(); |
| updateMemento(); |
| } |
| |
| /** |
| * Is used by the editpart to update the columns. |
| */ |
| public void updateColumns() { |
| createColumns(); |
| updateMemento(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.ecview.extension.grid.editparts.presentation. |
| * IGridPresentation#updateFilter() |
| */ |
| @Override |
| public void updateFilter() { |
| createFilteringHeader(); |
| updateMemento(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.ecview.extension.grid.editparts.presentation. |
| * IGridPresentation#updateCellStyleGenerator() |
| */ |
| @Override |
| public void updateCellStyleGenerator() { |
| CxGridCellStyleGenerator cxGenerator = modelAccess.yField.getCellStyleGenerator(); |
| if (cxGenerator != null) { |
| IGridCellStyleGeneratorEditpart ep = ModelUtil.getEditpart(getViewContext(), cxGenerator); |
| Grid.CellStyleGenerator generator = (Grid.CellStyleGenerator) ep.getDelegate(); |
| grid.setCellStyleGenerator(generator); |
| } else { |
| grid.setCellStyleGenerator(null); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.runtime.common.memento.IMementoHandler#applyMemento(java |
| * .lang.Object) |
| */ |
| @Override |
| public void applyMemento(Object value) { |
| boolean isRendered = isRendered(); |
| try { |
| if (isRendered) { |
| // unrender the grid to increase performance |
| getEditpart().requestUnrender(); |
| } |
| |
| doApplyMemento(value); |
| } finally { |
| if (isRendered) { |
| // render the grid again |
| getEditpart().requestRender(); |
| } |
| } |
| } |
| |
| /** |
| * Do apply memento. |
| * |
| * @param value |
| * the value |
| */ |
| protected void doApplyMemento(Object value) { |
| CxGrid cxGrid = modelAccess.yField; |
| |
| CxGridMemento cxMemento = (CxGridMemento) value; |
| currentMemento = cxMemento; |
| |
| // apply the grid properties |
| // |
| cxGrid.setEditorEnabled(cxMemento.isEditorEnabled()); |
| cxGrid.setFilteringVisible(cxMemento.isFilterVisible()); |
| cxGrid.setHeaderVisible(cxMemento.isHeaderVisible()); |
| cxGrid.setFooterVisible(cxMemento.isFooterVisible()); |
| |
| // apply the columns to the grid and the setting to each column |
| // |
| List<CxGridColumn> tempColumns = new ArrayList<>(cxGrid.getColumns()); |
| List<CxGridColumn> cxOrderedColumns = new ArrayList<>(cxGrid.getColumns().size()); |
| for (CxGridMementoColumn memColumn : cxMemento.getColumns()) { |
| CxGridColumn cxColumn = findCxColumn(memColumn.getPropertyId()); |
| if (cxColumn != null) { |
| // add the columns in the order of the memento |
| cxOrderedColumns.add(cxColumn); |
| tempColumns.remove(cxColumn); |
| |
| cxColumn.setEditable(memColumn.isEditable()); |
| cxColumn.setHidden(memColumn.isHidden()); |
| cxColumn.setHideable(memColumn.isHideable()); |
| cxColumn.setSortable(memColumn.isSortable()); |
| cxColumn.setExpandRatio(memColumn.getExpandRatio()); |
| if (memColumn.getWidth() > 0) { |
| cxColumn.setWidth(memColumn.getWidth()); |
| } |
| } |
| } |
| |
| // set all columns that are not in the memento as hidden |
| // |
| for (CxGridColumn cxColumn : tempColumns) { |
| cxColumn.setHideable(true); |
| cxColumn.setHidden(true); |
| } |
| |
| // set the new columns to the grid |
| cxGrid.getColumns().clear(); |
| cxGrid.getColumns().addAll(cxOrderedColumns); |
| |
| // update the sortorder |
| // |
| List<CxGridSortable> cxSortables = new ArrayList<>(cxMemento.getSortOrders().size()); |
| if (cxMemento.getSortOrders().size() > 0) { |
| for (CxGridMementoSortable memSort : cxMemento.getSortOrders()) { |
| |
| CxGridColumn cxColumn = findCxColumn(memSort.getColumn().getPropertyId()); |
| if (cxColumn != null) { |
| CxGridSortable cxSortable = CxGridFactory.eINSTANCE.createCxGridSortable(); |
| cxSortable.setColumn(cxColumn); |
| cxSortable.setDescending(memSort.isDescending()); |
| cxSortables.add(cxSortable); |
| } |
| } |
| cxGrid.getSortOrder().addAll(cxSortables); |
| } |
| } |
| |
| /** |
| * To direction. |
| * |
| * @param cxSortable |
| * the cx sortable |
| * @return the sort direction |
| */ |
| private SortDirection toDirection(CxGridSortable cxSortable) { |
| return cxSortable.isDescending() ? SortDirection.DESCENDING : SortDirection.ASCENDING; |
| } |
| |
| /** |
| * Gets the memento. |
| * |
| * @return the memento |
| */ |
| private Object getMemento() { |
| CxGridMemento cxMemento = CxGridMementoFactory.eINSTANCE.createCxGridMemento(); |
| |
| currentMemento = cxMemento; |
| |
| cxMemento.setId(getMementoId()); |
| cxMemento.setGridId(getCastedModel().getId()); |
| cxMemento.setEditorEnabled(grid.isEditorEnabled()); |
| cxMemento.setHeaderVisible(grid.isHeaderVisible()); |
| cxMemento.setFooterVisible(grid.isFooterVisible()); |
| cxMemento.setFilterVisible(filteringHeader != null); |
| |
| Map<Object, CxGridMementoColumn> tempColumns = new HashMap<>(); |
| for (Grid.Column column : grid.getColumns()) { |
| CxGridMementoColumn cxColumn = CxGridMementoFactory.eINSTANCE.createCxGridMementoColumn(); |
| cxColumn.setEditable(column.isEditable()); |
| cxColumn.setExpandRatio(column.getExpandRatio()); |
| cxColumn.setHideable(column.isHidable()); |
| cxColumn.setHidden(column.isHidden()); |
| cxColumn.setSortable(column.isSortable()); |
| cxColumn.setWidth((int) column.getWidth()); |
| cxColumn.setPropertyId((String) column.getPropertyId()); |
| cxMemento.getColumns().add(cxColumn); |
| |
| tempColumns.put(cxColumn.getPropertyId(), cxColumn); |
| } |
| |
| for (SortOrder sortOrder : grid.getSortOrder()) { |
| CxGridMementoSortable cxSortable = CxGridMementoFactory.eINSTANCE.createCxGridMementoSortable(); |
| CxGridMementoColumn cxColumn = tempColumns.get(sortOrder.getPropertyId()); |
| if (cxColumn == null) { |
| LOGGER.warn("Column is not available :" + sortOrder.getPropertyId()); |
| continue; |
| } |
| |
| cxSortable.setColumn(cxColumn); |
| cxSortable.setDescending(sortOrder.getDirection() == SortDirection.DESCENDING); |
| |
| cxMemento.getSortOrders().add(cxSortable); |
| } |
| |
| return cxMemento; |
| } |
| |
| /** |
| * Gets the memento id. |
| * |
| * @return the memento id |
| */ |
| protected String getMementoId() { |
| return castEObject(getCastedModel()).getMementoId(); |
| } |
| |
| /** |
| * Handles the memento, if it is enabled by the grid. |
| * |
| * @param cxGrid |
| * the new up user callbacks |
| */ |
| protected void setupUserCallbacks(CxGrid cxGrid) { |
| // then add listeners to the grid |
| // |
| grid.addColumnReorderListener(e -> { |
| if (e.isUserOriginated()) { |
| userChangedHandler.userChangedColumnOrder(); |
| updateMemento(); |
| } |
| }); |
| |
| grid.addColumnVisibilityChangeListener(e -> { |
| if (e.isUserOriginated()) { |
| userChangedHandler.userChangedColumnVisibility(e); |
| updateMemento(); |
| } |
| }); |
| |
| grid.addSortListener(e -> { |
| if (e.isUserOriginated()) { |
| userChangedHandler.userChangedSortOrder(e); |
| updateMemento(); |
| } |
| }); |
| } |
| |
| /** |
| * Find column wrapper. |
| * |
| * @param column |
| * the column |
| * @return the column wrapper |
| */ |
| private ColumnWrapper findColumnWrapper(Grid.Column column) { |
| return columns.stream().filter(e -> e.column == column).findFirst().orElse(null); |
| } |
| |
| /** |
| * Find column wrapper. |
| * |
| * @param propertyId |
| * the property id |
| * @return the column wrapper |
| */ |
| private ColumnWrapper findColumnWrapper(String propertyId) { |
| return columns.stream().filter(e -> e.column.getPropertyId().equals(propertyId)).findFirst().orElse(null); |
| } |
| |
| /** |
| * Find cx column. |
| * |
| * @param propertyId |
| * the property id |
| * @return the cx grid column |
| */ |
| private CxGridColumn findCxColumn(String propertyId) { |
| CxGrid cxGrid = modelAccess.yField; |
| return cxGrid.getColumns().stream().filter(e -> e.getPropertyId().equals(propertyId)).findFirst().orElse(null); |
| } |
| |
| /** |
| * Updates the memento. |
| */ |
| protected void updateMemento() { |
| if (modelAccess.yField.isMementoEnabled()) { |
| IGridEditpart ep = (IGridEditpart) getEditpart(); |
| ep.saveMemento(getMemento()); |
| } |
| } |
| |
| /* |
| * (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(CxGridPackage.Literals.CX_GRID__COLLECTION).observe(getModel()); |
| } |
| |
| /** |
| * Returns the observable to observe the selection. |
| * |
| * @param yEndpoint |
| * the y endpoint |
| * @return the i observable value |
| */ |
| @SuppressWarnings("restriction") |
| protected IObservableValue internalGetSelectionEndpoint(YEmbeddableSelectionEndpoint yEndpoint) { |
| |
| String attributePath = ECViewModelBindable.getAttributePath(CxGridPackage.Literals.CX_GRID__SELECTION, |
| yEndpoint.getAttributePath()); |
| |
| // return the observable value |
| 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(CxGridPackage.Literals.CX_GRID__SELECTION).observe(getModel()); |
| } |
| |
| /** |
| * An internal helper class. |
| */ |
| private static class ModelAccess { |
| |
| /** The y field. */ |
| private final CxGrid yField; |
| |
| /** |
| * Instantiates a new model access. |
| * |
| * @param yLayout |
| * the y layout |
| */ |
| public ModelAccess(CxGrid yLayout) { |
| super(); |
| this.yField = yLayout; |
| } |
| |
| /** |
| * 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.getLabel(); |
| } |
| |
| /** |
| * Returns the label I18n key. |
| * |
| * @return the label i18n key |
| */ |
| public String getLabelI18nKey() { |
| return yField.getLabelI18nKey(); |
| } |
| } |
| |
| /** |
| * The Class ColumnWrapper. |
| */ |
| private class ColumnWrapper extends AbstractDisposable implements IGridColumnEditpart.ColumnReference { |
| |
| /** The cx column. */ |
| private CxGridColumn cxColumn; |
| |
| /** The column. */ |
| private Grid.Column column; |
| |
| /** |
| * Instantiates a new column wrapper. |
| * |
| * @param cxColumn |
| * the cx column |
| * @param column |
| * the column |
| */ |
| public ColumnWrapper(CxGridColumn cxColumn, Grid.Column column) { |
| super(); |
| this.cxColumn = cxColumn; |
| this.column = column; |
| |
| columns.add(this); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.ecview.extension.grid.editparts.IGridColumnEditpart. |
| * ColumnReference#setConverter(java.lang.Object) |
| */ |
| @Override |
| public void setConverter(Object converter) { |
| if (converter != null && converter instanceof Converter) { |
| column.setConverter((Converter<?, ?>) converter); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.ecview.extension.grid.editparts.IGridColumnEditpart. |
| * ColumnReference#setRenderer(java.lang.Object, java.lang.Object) |
| */ |
| @SuppressWarnings({ "unchecked", "rawtypes" }) |
| @Override |
| public void setRenderer(Object renderer, Object converter) { |
| if (renderer == null) { |
| LOGGER.debug("Null renderer not allowed"); |
| return; |
| } |
| if (converter == null) { |
| column.setRenderer((Renderer) renderer); |
| } else { |
| column.setRenderer((Renderer) renderer, (Converter) converter); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.ecview.extension.grid.editparts.IGridColumnEditpart. |
| * ColumnReference#updateProperties() |
| */ |
| @Override |
| public void updateProperties() { |
| column.setHeaderCaption(getColumnHeader(cxColumn)); |
| column.setHidden(cxColumn.isHidden()); |
| column.setHidable(cxColumn.isHideable()); |
| column.setEditable(cxColumn.isEditable()); |
| if (cxColumn.getMinWidthPixels() > -1) { |
| column.setMinimumWidth(cxColumn.getMinWidthPixels()); |
| } |
| if (cxColumn.getMaxWidthPixels() > 0) { |
| column.setMaximumWidth(cxColumn.getMaxWidthPixels()); |
| } |
| if (cxColumn.getWidth() > -1) { |
| column.setWidth(cxColumn.getWidth()); |
| } else { |
| column.setWidthUndefined(); |
| } |
| column.setSortable(cxColumn.isSortable()); |
| if (cxColumn.getExpandRatio() > -1) { |
| column.setExpandRatio(cxColumn.getExpandRatio()); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.ecview.extension.grid.editparts.IGridColumnEditpart. |
| * ColumnReference#updateEditorField() |
| */ |
| @Override |
| public void updateEditorField() { |
| if (!cxColumn.isEditable()) { |
| column.setEditorField(null); |
| } else { |
| YField cxField = cxColumn.getEditorField(); |
| Field<?> field = null; |
| if (cxField != null) { |
| IFieldEditpart editpart = ModelUtil.getEditpart(getViewContext(), cxField); |
| field = (Field<?>) editpart.render(null); |
| field.setSizeFull(); |
| } |
| column.setEditorField(field); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.runtime.common.dispose.AbstractDisposable# |
| * internalDispose() |
| */ |
| @Override |
| protected void internalDispose() { |
| |
| // remove this column from the cached columns |
| columns.remove(this); |
| |
| YField cxField = cxColumn.getEditorField(); |
| if (cxField != null) { |
| IFieldEditpart editpart = ModelUtil.findEditpart(cxField); |
| if (editpart != null) { |
| editpart.dispose(); |
| } |
| } |
| } |
| } |
| |
| /** |
| * The Class UserChangedHandler. |
| */ |
| private class UserChangedHandler { |
| |
| /** |
| * User changed sort order. |
| * |
| * @param e |
| * the e |
| */ |
| private void userChangedSortOrder(SortEvent e) { |
| List<CxGridSortable> cxSortOrder = new ArrayList<>(); |
| for (SortOrder sortOrder : e.getSortOrder()) { |
| ColumnWrapper wrapper = findColumnWrapper((String) sortOrder.getPropertyId()); |
| |
| CxGridSortable cxSortable = CxGridFactory.eINSTANCE.createCxGridSortable(); |
| cxSortOrder.add(cxSortable); |
| if (wrapper != null) { |
| cxSortable.setColumn(wrapper.cxColumn); |
| } |
| cxSortable.setDescending(sortOrder.getDirection() == SortDirection.DESCENDING); |
| } |
| |
| CxGrid cxGrid = modelAccess.yField; |
| try { |
| cxGrid.eSetDeliver(false); |
| modelAccess.yField.getSortOrder().clear(); |
| modelAccess.yField.getSortOrder().addAll(cxSortOrder); |
| } finally { |
| cxGrid.eSetDeliver(true); |
| } |
| |
| } |
| |
| /** |
| * User changed column visibility. |
| * |
| * @param e |
| * the e |
| */ |
| private void userChangedColumnVisibility(ColumnVisibilityChangeEvent e) { |
| Grid.Column affected = e.getColumn(); |
| ColumnWrapper wrapper = findColumnWrapper(affected); |
| if (wrapper == null) { |
| LOGGER.warn("No column available for " + affected.getHeaderCaption()); |
| return; |
| } |
| |
| CxGrid cxGrid = modelAccess.yField; |
| try { |
| cxGrid.eSetDeliver(false); |
| // update the column in the model |
| CxGridColumn cxColumn = wrapper.cxColumn; |
| cxColumn.setHidden(e.isHidden()); |
| } finally { |
| cxGrid.eSetDeliver(true); |
| } |
| } |
| |
| /** |
| * User changed column order. |
| */ |
| private void userChangedColumnOrder() { |
| List<CxGridColumn> cxColumns = new ArrayList<>(); |
| for (Grid.Column column : grid.getColumns()) { |
| ColumnWrapper wrapper = findColumnWrapper(column); |
| if (wrapper != null) { |
| cxColumns.add(wrapper.cxColumn); |
| } |
| } |
| |
| CxGrid cxGrid = modelAccess.yField; |
| try { |
| cxGrid.eSetDeliver(false); |
| cxGrid.getColumns().clear(); |
| cxGrid.getColumns().addAll(cxColumns); |
| } finally { |
| cxGrid.eSetDeliver(true); |
| } |
| } |
| } |
| |
| /** |
| * The Class CustomTextField. |
| */ |
| @SuppressWarnings("serial") |
| public class CustomGrid extends Grid { |
| |
| // only required to be able to create a binding between |
| // org.eclipse.osbp.ecview.extension.grid.CxGrid and com.vaadin.ui.Grid |
| // to call this method which refresh the grid. |
| public long getRefresh() { |
| return 0; |
| } |
| |
| // only required to be able to create a binding between |
| // org.eclipse.osbp.ecview.extension.grid.CxGrid and com.vaadin.ui.Grid |
| // to call this method which refresh the grid. |
| public void setRefresh(long time) { |
| List<SortOrder> sort = getSortOrder(); |
| clearSortOrder(); |
| setSortOrder(sort); |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public class CustomSelectionModel extends Grid.SingleSelectionModel { |
| @Override |
| public boolean isSelected(Object itemId) { |
| boolean result = super.isSelected(itemId); |
| if (!result) { |
| Object selectedItemId = getSelectedRow(); |
| if (selectedItemId != null && itemId != selectedItemId) { |
| Object id1 = DtoUtils.getIdValue(itemId); |
| Object id2 = DtoUtils.getIdValue(selectedItemId); |
| result = Objects.equals(id1, id2); |
| if (result) { |
| reset(); |
| select(itemId); |
| } |
| } |
| } |
| return result; |
| } |
| } |
| } |