| /** |
| * |
| * 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 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation |
| */ |
| package org.eclipse.osbp.infogrid.api; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.stream.Collectors; |
| |
| import org.apache.commons.lang3.ClassUtils; |
| import org.eclipse.core.databinding.beans.BeanProperties; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.osbp.ecview.core.common.model.core.YCompare; |
| import org.eclipse.osbp.ecview.core.common.model.core.YConverter; |
| import org.eclipse.osbp.ecview.core.common.model.core.YField; |
| import org.eclipse.osbp.ecview.extension.grid.CxGrid; |
| import org.eclipse.osbp.ecview.extension.grid.CxGridColumn; |
| import org.eclipse.osbp.ecview.extension.grid.CxGridFactory; |
| import org.eclipse.osbp.ecview.extension.grid.CxGridGroupedCell; |
| import org.eclipse.osbp.ecview.extension.grid.CxGridHeaderRow; |
| import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridBlobImageRenderer; |
| import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridButtonRenderer; |
| import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridDateRenderer; |
| import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridImageRenderer; |
| import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridIndicatorRenderer; |
| import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridNestedConverter; |
| import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridNumberRenderer; |
| import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridPriceRenderer; |
| import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridProgressBarRenderer; |
| import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridQuantityRenderer; |
| import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridRenderer; |
| import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridRendererFactory; |
| import org.eclipse.osbp.ecview.extension.model.converter.YConverterFactory; |
| import org.eclipse.osbp.ecview.extension.model.converter.YNumericToResourceConfig; |
| import org.eclipse.osbp.ecview.extension.model.converter.YNumericToResourceConverter; |
| import org.eclipse.osbp.ecview.extension.model.converter.YStringToResourceConfig; |
| import org.eclipse.osbp.ecview.extension.model.converter.YStringToResourceConverter; |
| import org.eclipse.osbp.infogrid.model.gridsource.CxGridProperty; |
| import org.eclipse.osbp.infogrid.model.gridsource.CxGridSource; |
| import org.eclipse.osbp.infogrid.model.gridsource.CxGridSourceEQFilter; |
| import org.eclipse.osbp.infogrid.model.gridsource.CxGridSourceInput; |
| import org.eclipse.osbp.infogrid.model.gridsource.style.CxGridCompare; |
| import org.eclipse.osbp.infogrid.model.gridsource.style.CxGridPropBlobImageStyle; |
| import org.eclipse.osbp.infogrid.model.gridsource.style.CxGridPropButtonStyle; |
| import org.eclipse.osbp.infogrid.model.gridsource.style.CxGridPropDateStyle; |
| import org.eclipse.osbp.infogrid.model.gridsource.style.CxGridPropImageStyle; |
| import org.eclipse.osbp.infogrid.model.gridsource.style.CxGridPropIndicatorStyle; |
| import org.eclipse.osbp.infogrid.model.gridsource.style.CxGridPropNumberStyle; |
| import org.eclipse.osbp.infogrid.model.gridsource.style.CxGridPropPriceStyle; |
| import org.eclipse.osbp.infogrid.model.gridsource.style.CxGridPropProgressbarStyle; |
| import org.eclipse.osbp.infogrid.model.gridsource.style.CxGridPropQuantityStyle; |
| import org.eclipse.osbp.infogrid.model.gridsource.style.CxGridStyleConfig; |
| import org.eclipse.osbp.infogrid.model.gridsource.style.CxGridStyleConfigNumericToResource; |
| import org.eclipse.osbp.infogrid.model.gridsource.style.CxGridStyleConfigStringToResource; |
| import org.eclipse.osbp.infogrid.model.gridsource.style.CxGridStylePackage; |
| import org.eclipse.osbp.runtime.common.types.IBundleSpace; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.FrameworkUtil; |
| import org.osgi.framework.ServiceReference; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class SingleECViewGridFactory implements IECViewGridFactory { |
| |
| private static final Logger LOGGER = LoggerFactory.getLogger(SingleECViewGridFactory.class); |
| |
| private CxGridFactory gridFactory = CxGridFactory.eINSTANCE; |
| |
| // make extendable by services later |
| private IECViewGridEditorFieldFactory editorFieldFactory = new ECViewGridEditorFieldFactory(); |
| |
| public SingleECViewGridFactory() { |
| |
| } |
| |
| @Override |
| public CxGrid createGrid(Class<?> inputType, CxGridSource gridSource) { |
| |
| BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); |
| ServiceReference<IBundleSpace> bsRef = bc.getServiceReference(IBundleSpace.class); |
| if (bsRef == null) { |
| LOGGER.error("No BundleSpace available."); |
| return gridFactory.createCxGrid(); |
| } |
| IBundleSpace bundleSpace = bc.getService(bsRef); |
| |
| Class<?> rootType = null; |
| try { |
| rootType = bundleSpace.forName(gridSource.getRootTypeFQN()); |
| } catch (ClassNotFoundException e) { |
| LOGGER.error("{}", e); |
| } |
| |
| bc.ungetService(bsRef); |
| |
| CxGrid grid = gridFactory.createCxGrid(); |
| grid.setId(GRID_ID); |
| grid.getProperties().put(GRIDSOURCE_ID, gridSource.getId()); |
| grid.setEditorEnabled(isEditable(gridSource)); |
| grid.setHeaderVisible(true); |
| grid.setCustomFilters(false); |
| grid.setFilteringVisible(true); |
| grid.setUseBeanService(!gridSource.getTags().contains(IECViewGridSourceDescriptor.PROP_MANUAL_BEANS)); |
| grid.setColumnReorderingAllowed(true); |
| if (rootType != null) { |
| |
| grid.setType(rootType); |
| grid.setTypeQualifiedName(rootType.getName()); |
| |
| List<Info> temp = new ArrayList<>(gridSource.getProperties().size()); |
| |
| // create the basic infos. In further steps we will group them and |
| // calculate editable states. |
| // |
| for (CxGridProperty prop : gridSource.getProperties()) { |
| |
| Info info = new Info(); |
| info.prop = prop; |
| temp.add(info); |
| |
| if (GridUtil.isNested(rootType, prop)) { |
| info.group = GridUtil.getGroup(rootType, prop); |
| info.firstNestedDtoType = GridUtil.getDtoType(rootType, prop); |
| info.nested = true; |
| boolean bindsRawDto = GridUtil.isBindsRawDto(rootType, prop); |
| info.rawDtoRef = bindsRawDto; |
| if (bindsRawDto) { |
| info.fullDotPath = prop.getDotPath() + "." + GridUtil.getDomainKeyName(rootType, prop); |
| info.prop.setDotPath(info.fullDotPath); |
| info.domainkey = true; |
| // ATTENTION: Here we need to use the dto type, since |
| // this type is bound to the grid column |
| info.type = GridUtil.getPropertyType(rootType, prop); |
| } else { |
| info.fullDotPath = prop.getDotPath(); |
| info.domainkey = GridUtil.isBindsDomainKey(rootType, prop); |
| |
| info.type = GridUtil.getPropertyType(rootType, prop); |
| } |
| } else { |
| info.group = ""; |
| info.fullDotPath = prop.getDotPath(); |
| info.type = GridUtil.getPropertyType(rootType, prop); |
| } |
| } |
| |
| // filter double entries and create a map for groupings |
| // |
| Map<String, List<Info>> infoGroup = new HashMap<>(); |
| List<Info> infos = new ArrayList<>(gridSource.getProperties().size()); |
| Set<String> dotPath = new HashSet<>(); |
| for (Info info : temp) { |
| if (dotPath.contains(info.fullDotPath)) { |
| continue; |
| } |
| |
| if (!infoGroup.containsKey(info.group)) { |
| infoGroup.put(info.group, new ArrayList<>()); |
| } |
| |
| List<Info> list = infoGroup.get(info.group); |
| list.add(info); |
| |
| dotPath.add(info.fullDotPath); |
| infos.add(info); |
| } |
| |
| // check which info is editable. Only one per group is editable. |
| // Preferred the domainkey property |
| for (Map.Entry<String, List<Info>> entry : infoGroup.entrySet()) { |
| boolean domainkeyFound = false; |
| for (Info info : entry.getValue()) { |
| |
| if (info.group.equals("")) { |
| // the root group is always editable according its |
| // property |
| info.editable = info.prop.isEditable(); |
| continue; |
| } |
| |
| if (info.domainkey) { |
| info.editable = true; |
| domainkeyFound = true; |
| break; |
| } |
| } |
| if (!domainkeyFound) { |
| entry.getValue().get(0).editable = true; |
| } |
| } |
| |
| // create a header row for the grouped columns |
| // |
| temp = new ArrayList<>(infos); |
| infos.clear(); |
| CxGridHeaderRow groupingRow = CxGridFactory.eINSTANCE.createCxGridHeaderRow(); |
| grid.getHeaders().add(groupingRow); |
| |
| for (String group : infoGroup.keySet()) { |
| CxGridGroupedCell groupedCell = CxGridFactory.eINSTANCE.createCxGridGroupedCell(); |
| groupedCell.setId(group + "Group"); |
| groupedCell.setName(group + "Group"); |
| groupedCell.setLabelI18nKey(group); |
| groupingRow.getGroupings().add(groupedCell); |
| |
| // find grouped infos |
| List<Info> groupedCells = temp.stream().filter(info -> info.group.equals(group)) |
| .collect(Collectors.toList()); |
| |
| // and apply the cxGridGroup |
| groupedCells.stream().forEach(info -> info.cxGridGroup = groupedCell); |
| |
| infos.addAll(groupedCells); |
| } |
| |
| for (Info info : infos) { |
| CxGridProperty prop = info.prop; |
| CxGridColumn column = gridFactory.createCxGridColumn(); |
| column.setType(info.type); |
| column.setTypeQualifiedName(info.type.getName()); |
| |
| if (info.cxGridGroup != null) { |
| info.cxGridGroup.getGroupables().add(column); |
| } |
| |
| if (info.editable) { |
| // we create the column based on the dto and use the |
| // converter to convert to the target property inside the |
| // dto |
| column.setPropertyPath(GridUtil.getDtoBindingPath(rootType, prop)); |
| } else { |
| // otherwise we create the column with the fully dto path |
| column.setPropertyPath(prop.getDotPath()); |
| } |
| column.setPropertyId(column.getPropertyPath()); |
| |
| column.setLabelI18nKey(prop.getDotPath()); |
| |
| Class<?> propertyType = BeanProperties.value(rootType, prop.getDotPath()).getPropertyDescriptor() |
| .getPropertyType(); |
| |
| // editable |
| if (info.editable) { |
| YField yEditorField = getEditorField(prop, propertyType, rootType); |
| column.setEditable(yEditorField != null); |
| column.setEditorField(yEditorField); |
| |
| if (info.nested) { |
| // only one nested property is editable. So it needs to |
| // edit the dto by combobox and requires a different |
| // filterPropertyPath. |
| // The bindings property path points directly to the dto |
| column.setEditsDto(true); |
| column.setFilterPropertyPathForEditsDto(info.fullDotPath); |
| } |
| } else { |
| column.setEditable(false); |
| } |
| |
| Pair pair = createRendererPair(rootType, prop, propertyType, info); |
| column.setRenderer(pair.renderer); |
| column.setConverter(pair.converter); |
| // column.setMaxWidthPixels(50); |
| grid.getColumns().add(column); |
| } |
| |
| } |
| |
| for (CxGridSourceInput input : gridSource.getInputs()) { |
| if (inputType.getName().equals(input.getInputTypeFQN())) { |
| for (CxGridSourceEQFilter filter : input.getFilters()) { |
| // take the filter value from the input |
| filter.getInputTypePropertyPath(); |
| } |
| } |
| } |
| return grid; |
| } |
| |
| /** |
| * Returns the editor field for the given propertyType. |
| * |
| * @param prop |
| * @param propertyType |
| * @param rootType |
| * @return |
| */ |
| protected YField getEditorField(CxGridProperty prop, Class<?> propertyType, Class<?> rootType) { |
| return editorFieldFactory.createEditorField(prop, propertyType, rootType); |
| } |
| |
| protected boolean isEditable(CxGridSource gridSource) { |
| for (CxGridProperty prop : gridSource.getProperties()) { |
| if (prop.isEditable()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Creates a renderer for the given property. |
| * |
| * @param prop |
| * @param propertyType |
| * @param editable |
| * @return |
| */ |
| protected Pair createRendererPair(Class<?> rootType, CxGridProperty prop, Class<?> propertyType, Info info) { |
| |
| Pair pair = new Pair(); |
| CxGridRendererFactory factory = CxGridRendererFactory.eINSTANCE; |
| if (prop.getStyle() == null) { |
| return createBadRenderer(); |
| } |
| |
| EClass styleClass = prop.getStyle().eClass(); |
| switch (styleClass.getClassifierID()) { |
| case CxGridStylePackage.CX_GRID_PROP_BOOLEAN_STYLE: |
| pair.renderer = factory.createCxGridBooleanRenderer(); |
| break; |
| case CxGridStylePackage.CX_GRID_PROP_DATE_STYLE: { |
| CxGridPropDateStyle style = (CxGridPropDateStyle) prop.getStyle(); |
| CxGridDateRenderer renderer = factory.createCxGridDateRenderer(); |
| renderer.setDateFormat(style.getDateFormat()); |
| pair.renderer = renderer; |
| } |
| break; |
| case CxGridStylePackage.CX_GRID_PROP_NUMBER_STYLE: { |
| if (!isNumeric(propertyType)) { |
| return createBadRenderer(); |
| } |
| CxGridPropNumberStyle style = (CxGridPropNumberStyle) prop.getStyle(); |
| CxGridNumberRenderer renderer = factory.createCxGridNumberRenderer(); |
| renderer.setNumberFormat(style.getNumberFormat()); |
| pair.renderer = renderer; |
| } |
| break; |
| case CxGridStylePackage.CX_GRID_PROP_BUTTON_STYLE: { |
| CxGridPropButtonStyle style = (CxGridPropButtonStyle) prop.getStyle(); |
| CxGridButtonRenderer renderer = factory.createCxGridButtonRenderer(); |
| renderer.setEventTopic(style.getEventTopic()); |
| pair.renderer = renderer; |
| } |
| break; |
| case CxGridStylePackage.CX_GRID_PROP_IMAGE_STYLE: { |
| CxGridPropImageStyle style = (CxGridPropImageStyle) prop.getStyle(); |
| YConverter converter = toConverter(style.getConfigs()); |
| CxGridImageRenderer renderer = factory.createCxGridImageRenderer(); |
| renderer.setEventTopic(style.getEventTopic()); |
| pair.renderer = renderer; |
| pair.converter = converter; |
| } |
| break; |
| case CxGridStylePackage.CX_GRID_PROP_BLOB_IMAGE_STYLE: { |
| YConverter converter = YConverterFactory.eINSTANCE.createYStringToByteArrayConverter(); |
| CxGridBlobImageRenderer renderer = factory.createCxGridBlobImageRenderer(); |
| pair.renderer = renderer; |
| pair.converter = converter; |
| } |
| break; |
| case CxGridStylePackage.CX_GRID_PROP_HTML_STYLE: |
| pair.renderer = factory.createCxGridHtmlRenderer(); |
| break; |
| case CxGridStylePackage.CX_GRID_PROP_PROGRESSBAR_STYLE: { |
| CxGridPropProgressbarStyle style = (CxGridPropProgressbarStyle) prop.getStyle(); |
| CxGridProgressBarRenderer renderer = factory.createCxGridProgressBarRenderer(); |
| renderer.setMaxValue(style.getMaxValue()); |
| pair.renderer = renderer; |
| } |
| break; |
| case CxGridStylePackage.CX_GRID_PROP_INDICATOR_STYLE: { |
| CxGridPropIndicatorStyle style = (CxGridPropIndicatorStyle) prop.getStyle(); |
| CxGridIndicatorRenderer renderer = factory.createCxGridIndicatorRenderer(); |
| renderer.setGreenStarts(style.getGreenStarts()); |
| renderer.setRedEnds(style.getRedEnds()); |
| pair.renderer = renderer; |
| } |
| break; |
| case CxGridStylePackage.CX_GRID_PROP_SPARKLINE_STYLE: |
| pair.renderer = factory.createCxGridHtmlRenderer(); |
| break; |
| case CxGridStylePackage.CX_GRID_PROP_TEXT_STYLE: |
| pair.renderer = factory.createCxGridHtmlRenderer(); |
| break; |
| case CxGridStylePackage.CX_GRID_PROP_QUANTITY_STYLE: { |
| CxGridPropQuantityStyle style = (CxGridPropQuantityStyle) prop.getStyle(); |
| CxGridQuantityRenderer renderer = factory.createCxGridQuantityRenderer(); |
| renderer.setHtmlPattern(style.getHtmlPattern()); |
| renderer.setNullRepresentation(""); |
| renderer.setNumberFormat(style.getValueNumberFormat()); |
| renderer.setUomPropertyPath(style.getUomPropertyDotPath()); |
| renderer.setValuePropertyPath(style.getValuePropertyDotPath()); |
| pair.renderer = renderer; |
| } |
| break; |
| case CxGridStylePackage.CX_GRID_PROP_PRICE_STYLE: { |
| CxGridPropPriceStyle style = (CxGridPropPriceStyle) prop.getStyle(); |
| CxGridPriceRenderer renderer = factory.createCxGridPriceRenderer(); |
| renderer.setHtmlPattern(style.getHtmlPattern()); |
| renderer.setNullRepresentation(""); |
| renderer.setNumberFormat(style.getValueNumberFormat()); |
| renderer.setCurrencyPropertyPath(style.getCurrencyPropertyDotPath()); |
| renderer.setValuePropertyPath(style.getValuePropertyDotPath()); |
| pair.renderer = renderer; |
| } |
| break; |
| } |
| |
| if (info.nested && info.editable) { |
| CxGridNestedConverter nestedConverter = CxGridRendererFactory.eINSTANCE.createCxGridNestedConverter(); |
| Class<?> dtoType = GridUtil.getDtoType(rootType, prop); |
| nestedConverter.setBaseType(dtoType); |
| nestedConverter.setBaseTypeQualifiedName(dtoType.getName()); |
| |
| if (propertyType.isPrimitive()) { |
| propertyType = ClassUtils.primitiveToWrapper(propertyType); |
| } |
| nestedConverter.setNestedType(propertyType); |
| nestedConverter.setNestedTypeQualifiedName(propertyType.getName()); |
| |
| // we create the column based on the dto and use the |
| // converter to point to the target property inside the dto |
| String nestedConverterTailPath = GridUtil.getNestedConverterTailDotPath(rootType, prop); |
| nestedConverter.setNestedDotPath(nestedConverterTailPath); |
| |
| // the nestedConverter needs to use the nested type converter to |
| // convert to the presentation. Eg, the nestedConverter extracts |
| // birthdate from Person and the nestedTypeConverter does pretty |
| // formatting of date |
| nestedConverter.setNestedTypeConverter(pair.converter); |
| pair.converter = nestedConverter; |
| } |
| |
| return pair; |
| } |
| |
| protected boolean isNumeric(Class<?> propertyType) { |
| boolean result = Number.class.isAssignableFrom(propertyType); |
| if (!result) { |
| if (propertyType.isPrimitive() && propertyType != Boolean.TYPE && propertyType != Void.TYPE) { |
| result = true; |
| } |
| } |
| return result; |
| } |
| |
| protected YConverter toConverter(EList<CxGridStyleConfig> configs) { |
| if (configs.isEmpty()) { |
| return null; |
| } |
| |
| CxGridStyleConfig cxConfig = configs.get(0); |
| if (cxConfig instanceof CxGridStyleConfigStringToResource) { |
| List<YStringToResourceConfig> newConfigs = toStringToResourceConfig(configs); |
| YStringToResourceConverter converter = YConverterFactory.eINSTANCE.createYStringToResourceConverter(); |
| converter.getConfigs().addAll(newConfigs); |
| return converter; |
| } else if (cxConfig instanceof CxGridStyleConfigNumericToResource) { |
| List<YNumericToResourceConfig> newConfigs = toNumberToResourceConfig(configs); |
| YNumericToResourceConverter converter = YConverterFactory.eINSTANCE.createYNumericToResourceConverter(); |
| converter.getConfigs().addAll(newConfigs); |
| return converter; |
| } |
| |
| return null; |
| } |
| |
| private List<YNumericToResourceConfig> toNumberToResourceConfig(EList<CxGridStyleConfig> configs) { |
| List<YNumericToResourceConfig> result = new ArrayList<>(configs.size()); |
| for (CxGridStyleConfig config : configs) { |
| if (!(config instanceof CxGridStyleConfigNumericToResource)) { |
| LOGGER.warn("you mixed up different style configs!"); |
| continue; |
| } |
| |
| CxGridStyleConfigNumericToResource givenConfig = (CxGridStyleConfigNumericToResource) config; |
| YNumericToResourceConfig newConfig = YConverterFactory.eINSTANCE.createYNumericToResourceConfig(); |
| newConfig.setResourceThemePath(givenConfig.getResourceThemePath()); |
| newConfig.setValue(givenConfig.getValue()); |
| newConfig.setCompare(toGridCompare(givenConfig.getCompare())); |
| result.add(newConfig); |
| } |
| |
| return result; |
| } |
| |
| private YCompare toGridCompare(CxGridCompare compare) { |
| switch (compare) { |
| case EQUAL: |
| return YCompare.EQUAL; |
| case GREATER_EQUAL: |
| return YCompare.GREATER_EQUAL; |
| case GREATER_THAN: |
| return YCompare.GREATER_THAN; |
| case LOWER_EQUAL: |
| return YCompare.LOWER_EQUAL; |
| case LOWER_THAN: |
| return YCompare.LOWER_THAN; |
| case NOT_EQUAL: |
| return YCompare.NOT_EQUAL; |
| } |
| return null; |
| } |
| |
| private List<YStringToResourceConfig> toStringToResourceConfig(EList<CxGridStyleConfig> configs) { |
| List<YStringToResourceConfig> result = new ArrayList<>(configs.size()); |
| for (CxGridStyleConfig config : configs) { |
| if (!(config instanceof CxGridStyleConfigStringToResource)) { |
| LOGGER.warn("you mixed up different style configs!"); |
| continue; |
| } |
| |
| CxGridStyleConfigStringToResource givenConfig = (CxGridStyleConfigStringToResource) config; |
| YStringToResourceConfig newConfig = YConverterFactory.eINSTANCE.createYStringToResourceConfig(); |
| newConfig.setResourceThemePath(givenConfig.getResourceThemePath()); |
| newConfig.setValue(givenConfig.getValue()); |
| newConfig.setCompare(toGridCompare(givenConfig.getCompare())); |
| result.add(newConfig); |
| } |
| |
| return result; |
| } |
| |
| protected Pair createBadRenderer() { |
| Pair pair = new Pair(); |
| pair.renderer = CxGridRendererFactory.eINSTANCE.createCxGridTextRenderer(); |
| return pair; |
| } |
| |
| protected static class Pair { |
| public CxGridRenderer renderer; |
| public YConverter converter; |
| } |
| |
| protected static class Info { |
| public CxGridGroupedCell cxGridGroup; |
| |
| CxGridProperty prop; |
| |
| // true, if the column is editable |
| boolean editable; |
| |
| // the name of the first bound dto |
| String group; |
| |
| // the dot path extended by the domainkey if rawDtoRef is true |
| String fullDotPath; |
| |
| // true if nested or rawDtoRef |
| boolean nested; |
| |
| // if true, then the prop binds to the domain key |
| boolean domainkey; |
| |
| // if true, we need to add the domainkey since the property points to a |
| // raw dto. Eg. person.country -> so we make it to |
| // person.country.isoCode |
| boolean rawDtoRef; |
| |
| // the first dtoType in the binding path used for groupings |
| Class<?> firstNestedDtoType; |
| |
| // the type of the bound property |
| Class<?> type; |
| } |
| } |