blob: 610e91596d6360b0fc3f3cee913051712263b9ac [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2020 Dirk Fauth and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Dirk Fauth - initial API and implementation
*******************************************************************************/
package org.eclipse.nebula.widgets.nattable.examples._500_Layers._512_SummaryRow;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.nebula.widgets.nattable.NatTable;
import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
import org.eclipse.nebula.widgets.nattable.copy.command.CopyDataCommandHandler;
import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.dataset.NumberValues;
import org.eclipse.nebula.widgets.nattable.examples.AbstractNatExample;
import org.eclipse.nebula.widgets.nattable.examples.runner.StandaloneNatExampleRunner;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultSummaryRowHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultColumnHeaderDataLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultRowHeaderDataLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;
import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
import org.eclipse.nebula.widgets.nattable.layer.LabelStack;
import org.eclipse.nebula.widgets.nattable.layer.cell.AbstractOverrider;
import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
import org.eclipse.nebula.widgets.nattable.summaryrow.DefaultSummaryRowConfiguration;
import org.eclipse.nebula.widgets.nattable.summaryrow.ISummaryProvider;
import org.eclipse.nebula.widgets.nattable.summaryrow.SummaryRowConfigAttributes;
import org.eclipse.nebula.widgets.nattable.summaryrow.SummaryRowLayer;
import org.eclipse.nebula.widgets.nattable.summaryrow.SummationSummaryProvider;
import org.eclipse.nebula.widgets.nattable.util.GUIHelper;
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
/**
* Example that demonstrates how to implement a NatTable instance that shows
* calculated values. Also demonstrates the usage of the SummaryRow on updating
* the NatTable.
*
* @author Dirk Fauth
*
*/
public class _5122_SummaryRowGridExample extends AbstractNatExample {
public static void main(String[] args) throws Exception {
StandaloneNatExampleRunner.run(600, 400,
new _5122_SummaryRowGridExample());
}
@Override
public String getDescription() {
return "This example demonstrates how to add a summary row to the end of a grid.\n"
+ "\n"
+ "Features\n"
+ " Different style can be applied to the whole row\n"
+ " Different style can be applied to the individual cells in the summary row\n"
+ " Plug-in your own summary formulas via ISummaryProvider interface (Default is summation)";
}
/*
* (non-Javadoc)
*
* @see org.eclipse.nebula.widgets.nattable.examples.INatExample#
* createExampleControl (org.eclipse.swt.widgets.Composite)
*/
@Override
public Control createExampleControl(Composite parent) {
// property names of the NumberValues class
String[] propertyNames = { "columnOneNumber", "columnTwoNumber",
"columnThreeNumber", "columnFourNumber", "columnFiveNumber" };
// mapping from property to label, needed for column header labels
Map<String, String> propertyToLabelMap = new HashMap<>();
propertyToLabelMap.put("columnOneNumber", "Column 1");
propertyToLabelMap.put("columnTwoNumber", "Column 2");
propertyToLabelMap.put("columnThreeNumber", "Column 3");
propertyToLabelMap.put("columnFourNumber", "Column 4");
propertyToLabelMap.put("columnFiveNumber", "Column 5");
IColumnPropertyAccessor<NumberValues> cpa = new ReflectiveColumnPropertyAccessor<>(
propertyNames);
IDataProvider dataProvider = new ListDataProvider<>(
createNumberValueList(), cpa);
ConfigRegistry configRegistry = new ConfigRegistry();
SummaryRowGridLayer gridLayer = new SummaryRowGridLayer(dataProvider,
configRegistry, propertyNames, propertyToLabelMap);
NatTable natTable = new NatTable(parent, gridLayer, false);
natTable.setConfigRegistry(configRegistry);
natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
natTable.configure();
return natTable;
}
private List<NumberValues> createNumberValueList() {
List<NumberValues> result = new ArrayList<>();
for (int i = 0; i < 25; i++) {
NumberValues nv = new NumberValues();
nv.setColumnOneNumber(5);
nv.setColumnTwoNumber(4);
nv.setColumnThreeNumber(3);
nv.setColumnFourNumber(1);
nv.setColumnFiveNumber(1);
result.add(nv);
nv = new NumberValues();
nv.setColumnOneNumber(1);
nv.setColumnTwoNumber(1);
nv.setColumnThreeNumber(2);
nv.setColumnFourNumber(2);
nv.setColumnFiveNumber(3);
result.add(nv);
nv = new NumberValues();
nv.setColumnOneNumber(1);
nv.setColumnTwoNumber(2);
nv.setColumnThreeNumber(2);
nv.setColumnFourNumber(3);
nv.setColumnFiveNumber(3);
result.add(nv);
nv = new NumberValues();
nv.setColumnOneNumber(1);
nv.setColumnTwoNumber(2);
nv.setColumnThreeNumber(4);
nv.setColumnFourNumber(4);
nv.setColumnFiveNumber(3);
result.add(nv);
nv = new NumberValues();
nv.setColumnOneNumber(5);
nv.setColumnTwoNumber(4);
nv.setColumnThreeNumber(4);
nv.setColumnFourNumber(4);
nv.setColumnFiveNumber(7);
result.add(nv);
}
return result;
}
}
/**
* The body layer stack for the {@link _5122_SummaryRowGridExample}. Consists of
* <ol>
* <li>ViewportLayer</li>
* <li>SelectionLayer</li>
* <li>ColumnHideShowLayer</li>
* <li>ColumnReorderLayer</li>
* <li>SummaryRowLayer</li>
* <li>DataLayer</li>
* </ol>
*/
class SummaryRowBodyLayerStack extends AbstractLayerTransform {
private final DataLayer bodyDataLayer;
private final SummaryRowLayer summaryRowLayer;
private final ColumnReorderLayer columnReorderLayer;
private final ColumnHideShowLayer columnHideShowLayer;
private final SelectionLayer selectionLayer;
private final ViewportLayer viewportLayer;
public SummaryRowBodyLayerStack(IDataProvider dataProvider,
ConfigRegistry configRegistry) {
this.bodyDataLayer = new DataLayer(dataProvider);
this.summaryRowLayer = new SummaryRowLayer(this.bodyDataLayer, configRegistry,
false);
this.summaryRowLayer
.addConfiguration(new ExampleSummaryRowGridConfiguration(
this.bodyDataLayer.getDataProvider()));
this.columnReorderLayer = new ColumnReorderLayer(this.summaryRowLayer);
this.columnHideShowLayer = new ColumnHideShowLayer(this.columnReorderLayer);
this.selectionLayer = new SelectionLayer(this.columnHideShowLayer);
this.viewportLayer = new ViewportLayer(this.selectionLayer);
setUnderlyingLayer(this.viewportLayer);
registerCommandHandler(new CopyDataCommandHandler(this.selectionLayer));
}
public DataLayer getDataLayer() {
return this.bodyDataLayer;
}
public SelectionLayer getSelectionLayer() {
return this.selectionLayer;
}
}
/**
* The {@link GridLayer} used by the {@link _5122_SummaryRowGridExample}.
*/
class SummaryRowGridLayer extends GridLayer {
public SummaryRowGridLayer(IDataProvider dataProvider,
ConfigRegistry configRegistry, final String[] propertyNames,
Map<String, String> propertyToLabelMap) {
super(true);
init(dataProvider, configRegistry, propertyNames, propertyToLabelMap);
}
private void init(IDataProvider dataProvider,
ConfigRegistry configRegistry, final String[] propertyNames,
Map<String, String> propertyToLabelMap) {
// Body
SummaryRowBodyLayerStack bodyLayer = new SummaryRowBodyLayerStack(
dataProvider, configRegistry);
SelectionLayer selectionLayer = bodyLayer.getSelectionLayer();
// Column header
IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(
propertyNames, propertyToLabelMap);
ILayer columnHeaderLayer = new ColumnHeaderLayer(
new DefaultColumnHeaderDataLayer(columnHeaderDataProvider),
bodyLayer, selectionLayer);
// Row header
// Adding the specialized DefaultSummaryRowHeaderDataProvider to
// indicate the summary row in the row header
IDataProvider rowHeaderDataProvider = new DefaultSummaryRowHeaderDataProvider(
bodyLayer.getDataLayer().getDataProvider(), "\u2211");
final DataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(
rowHeaderDataProvider);
// add a label to the row header summary row cell aswell, so it can be
// styled differently too
// in this case it will simply use the same styling as the summary row
// in the body
rowHeaderDataLayer.setConfigLabelAccumulator(new AbstractOverrider() {
@Override
public void accumulateConfigLabels(LabelStack configLabels,
int columnPosition, int rowPosition) {
if ((rowPosition + 1) == rowHeaderDataLayer.getRowCount()) {
configLabels
.addLabel(SummaryRowLayer.DEFAULT_SUMMARY_ROW_CONFIG_LABEL);
}
}
});
ILayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer,
bodyLayer, selectionLayer);
// Corner
ILayer cornerLayer = new CornerLayer(new DataLayer(
new DefaultCornerDataProvider(columnHeaderDataProvider,
rowHeaderDataProvider)),
rowHeaderLayer,
columnHeaderLayer);
setBodyLayer(bodyLayer);
setColumnHeaderLayer(columnHeaderLayer);
setRowHeaderLayer(rowHeaderLayer);
setCornerLayer(cornerLayer);
}
public DataLayer getBodyDataLayer() {
return ((SummaryRowBodyLayerStack) getBodyLayer()).getDataLayer();
}
}
class ExampleSummaryRowGridConfiguration extends DefaultSummaryRowConfiguration {
private final IDataProvider dataProvider;
public ExampleSummaryRowGridConfiguration(IDataProvider dataProvider) {
this.dataProvider = dataProvider;
this.summaryRowBgColor = GUIHelper.COLOR_BLUE;
this.summaryRowFgColor = GUIHelper.COLOR_WHITE;
}
@Override
public void addSummaryProviderConfig(IConfigRegistry configRegistry) {
// Labels are applied to the summary row and cells by default to make
// configuration easier.
// See the Javadoc for the SummaryRowLayer
// Default summary provider
configRegistry.registerConfigAttribute(
SummaryRowConfigAttributes.SUMMARY_PROVIDER,
new SummationSummaryProvider(this.dataProvider), DisplayMode.NORMAL,
SummaryRowLayer.DEFAULT_SUMMARY_ROW_CONFIG_LABEL);
// Average summary provider for column index 2
configRegistry.registerConfigAttribute(
SummaryRowConfigAttributes.SUMMARY_PROVIDER,
new AverageSummaryProvider(), DisplayMode.NORMAL,
SummaryRowLayer.DEFAULT_SUMMARY_COLUMN_CONFIG_LABEL_PREFIX + 4);
}
/**
* Custom summary provider which averages out the contents of the column
*/
class AverageSummaryProvider implements ISummaryProvider {
@Override
public Object summarize(int columnIndex) {
double total = 0;
int rowCount = ExampleSummaryRowGridConfiguration.this.dataProvider.getRowCount();
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
Object dataValue = ExampleSummaryRowGridConfiguration.this.dataProvider.getDataValue(columnIndex,
rowIndex);
total = total + Double.parseDouble(dataValue.toString());
}
return "Avg: " + total / rowCount;
}
}
}