blob: b49bde980ec3f4054e72d938643461b1609aef37 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019, 2020 Dirk Fauth.
*
* 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 <dirk.fauth@googlemail.com> - initial API and implementation
******************************************************************************/
package org.eclipse.nebula.widgets.nattable.examples._500_Layers._511_Grouping;
import org.eclipse.nebula.widgets.nattable.NatTable;
import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration;
import org.eclipse.nebula.widgets.nattable.config.AbstractUiBindingConfiguration;
import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes;
import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
import org.eclipse.nebula.widgets.nattable.examples.AbstractNatExample;
import org.eclipse.nebula.widgets.nattable.examples.runner.StandaloneNatExampleRunner;
import org.eclipse.nebula.widgets.nattable.fillhandle.config.FillHandleConfiguration;
import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;
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.group.performance.ColumnGroupExpandCollapseLayer;
import org.eclipse.nebula.widgets.nattable.group.performance.ColumnGroupHeaderLayer;
import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
import org.eclipse.nebula.widgets.nattable.hideshow.RowHideShowLayer;
import org.eclipse.nebula.widgets.nattable.hideshow.indicator.HideIndicatorOverlayPainter;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
import org.eclipse.nebula.widgets.nattable.painter.cell.ICellPainter;
import org.eclipse.nebula.widgets.nattable.painter.cell.VerticalTextPainter;
import org.eclipse.nebula.widgets.nattable.painter.cell.decorator.BeveledBorderDecorator;
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.ui.binding.UiBindingRegistry;
import org.eclipse.nebula.widgets.nattable.ui.matcher.MouseEventMatcher;
import org.eclipse.nebula.widgets.nattable.ui.menu.AbstractHeaderMenuConfiguration;
import org.eclipse.nebula.widgets.nattable.ui.menu.IMenuItemProvider;
import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuAction;
import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuBuilder;
import org.eclipse.nebula.widgets.nattable.ui.menu.VisibleColumnsRemaining;
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
import org.eclipse.nebula.widgets.nattable.viewport.command.ShowColumnInViewportCommand;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
/**
* This example shows the usage of the performance
* {@link ColumnGroupHeaderLayer} in a layer composition of a grid for a huge
* number of columns that are grouped.
*/
public class _5115_HugeColumnGroupingExample extends AbstractNatExample {
public static void main(String[] args) throws Exception {
StandaloneNatExampleRunner.run(1010, 500, new _5115_HugeColumnGroupingExample());
}
@Override
public String getDescription() {
return "This example shows the usage of the performance {@link ColumnGroupHeaderLayer} in a "
+ "layer composition of a grid for a huge number of columns that are grouped.";
}
@Override
public Control createExampleControl(Composite parent) {
int rowCount = 20;
int columnCount = 900000;
int groupWidth = columnCount / 3;
// build the body layer stack
// Usually you would create a new layer stack by extending
// AbstractIndexLayerTransform and setting the ViewportLayer as
// underlying layer. But in this case using the ViewportLayer
// directly as body layer is also working.
IDataProvider bodyDataProvider = new HugeBodyDataProvider(rowCount, columnCount);
DataLayer bodyDataLayer =
new DataLayer(bodyDataProvider);
RowHideShowLayer rowHideShowLayer =
new RowHideShowLayer(bodyDataLayer);
ColumnReorderLayer columnReorderLayer =
new ColumnReorderLayer(rowHideShowLayer);
ColumnHideShowLayer columnHideShowLayer =
new ColumnHideShowLayer(columnReorderLayer);
ColumnGroupExpandCollapseLayer columnGroupExpandCollapseLayer =
new ColumnGroupExpandCollapseLayer(columnHideShowLayer);
final SelectionLayer selectionLayer =
new SelectionLayer(columnGroupExpandCollapseLayer);
ViewportLayer viewportLayer =
new ViewportLayer(selectionLayer);
// build the column header layer
IDataProvider columnHeaderDataProvider = new HugeColumnHeaderDataProvider(columnCount);
DataLayer columnHeaderDataLayer =
new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);
ColumnHeaderLayer columnHeaderLayer =
new ColumnHeaderLayer(columnHeaderDataLayer, viewportLayer, selectionLayer);
ColumnGroupHeaderLayer columnGroupHeaderLayer =
new ColumnGroupHeaderLayer(columnHeaderLayer, selectionLayer);
columnGroupHeaderLayer.setShowAlwaysGroupNames(true);
// configure the column groups
columnGroupHeaderLayer.setDefaultUnbreakable(true);
columnGroupHeaderLayer.addGroup("First", 0, groupWidth);
columnGroupHeaderLayer.addGroup("Second", groupWidth, groupWidth);
columnGroupHeaderLayer.addGroup("Third", (groupWidth * 2), groupWidth);
// columnGroupHeaderLayer.addGroupingLevel();
// columnGroupHeaderLayer.addGroup(1, "Test", 0, 7);
// build the row header layer
IDataProvider rowHeaderDataProvider =
new DefaultRowHeaderDataProvider(bodyDataProvider);
DataLayer rowHeaderDataLayer =
new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
ILayer rowHeaderLayer =
new RowHeaderLayer(rowHeaderDataLayer, viewportLayer, selectionLayer);
// build the corner layer
IDataProvider cornerDataProvider =
new DefaultCornerDataProvider(columnHeaderDataProvider, rowHeaderDataProvider);
DataLayer cornerDataLayer =
new DataLayer(cornerDataProvider);
ILayer cornerLayer =
new CornerLayer(cornerDataLayer, rowHeaderLayer, columnGroupHeaderLayer);
// build the grid layer
GridLayer gridLayer =
new GridLayer(viewportLayer, columnGroupHeaderLayer, rowHeaderLayer, cornerLayer);
// turn the auto configuration off as we want to add our header menu
// configuration
NatTable natTable = new NatTable(parent, gridLayer, false);
// as the autoconfiguration of the NatTable is turned off, we have to
// add the DefaultNatTableStyleConfiguration manually
natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
natTable.addConfiguration(new AbstractHeaderMenuConfiguration(natTable) {
@Override
protected PopupMenuBuilder createColumnHeaderMenu(NatTable natTable) {
PopupMenuBuilder builder = super.createColumnHeaderMenu(natTable)
.withHideColumnMenuItem()
.withShowAllColumnsMenuItem()
// the performance column group menu, not the old one
.withCreateColumnGroupMenuItem()
.withUngroupColumnsMenuItem()
.withAutoResizeSelectedColumnsMenuItem()
.withColumnRenameDialog()
.withColumnChooserMenuItem()
.withMenuItemProvider(new IMenuItemProvider() {
@Override
public void addMenuItem(NatTable natTable, Menu popupMenu) {
MenuItem scroll = new MenuItem(popupMenu, SWT.PUSH);
scroll.setText("Scroll");
scroll.setEnabled(true);
scroll.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
natTable.doCommand(
new ShowColumnInViewportCommand(11));
}
});
}
});
builder.withEnabledState(
PopupMenuBuilder.HIDE_COLUMN_MENU_ITEM_ID,
new VisibleColumnsRemaining(selectionLayer));
return builder;
}
@Override
protected PopupMenuBuilder createRowHeaderMenu(NatTable natTable) {
return super.createRowHeaderMenu(natTable)
.withAutoResizeSelectedRowsMenuItem();
}
@Override
protected PopupMenuBuilder createCornerMenu(NatTable natTable) {
return super.createCornerMenu(natTable).withShowAllColumnsMenuItem();
}
});
// Column group header menu
final Menu columnGroupHeaderMenu = new PopupMenuBuilder(natTable)
.withRenameColumnGroupMenuItem()
.withRemoveColumnGroupMenuItem()
.build();
natTable.addConfiguration(new AbstractUiBindingConfiguration() {
@Override
public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
uiBindingRegistry.registerFirstMouseDownBinding(
new MouseEventMatcher(
SWT.NONE,
GridRegion.COLUMN_GROUP_HEADER,
MouseEventMatcher.RIGHT_BUTTON),
new PopupMenuAction(columnGroupHeaderMenu));
}
});
// TODO additional configs
natTable.addConfiguration(new FillHandleConfiguration(selectionLayer));
HideIndicatorOverlayPainter overlayPainter =
new HideIndicatorOverlayPainter(columnHeaderLayer, rowHeaderLayer);
natTable.addOverlayPainter(overlayPainter);
// enable this configuration to verify the automatic height calculation
// when using vertical text painter
natTable.addConfiguration(new AbstractRegistryConfiguration() {
@Override
public void configureRegistry(IConfigRegistry configRegistry) {
ICellPainter cellPainter = new BeveledBorderDecorator(new VerticalTextPainter(false, true, 5, true, true));
configRegistry.registerConfigAttribute(
CellConfigAttributes.CELL_PAINTER, cellPainter,
DisplayMode.NORMAL,
GridRegion.COLUMN_HEADER);
}
});
// TODO
// Register column chooser
// DisplayColumnChooserCommandHandler columnChooserCommandHandler =
// new DisplayColumnChooserCommandHandler(
// selectionLayer,
// columnHideShowLayer,
// columnHeaderLayer,
// columnHeaderDataLayer,
// columnGroupHeaderLayer,
// columnGroupModel,
// false,
// true);
//
// viewportLayer.registerCommandHandler(columnChooserCommandHandler);
natTable.configure();
return natTable;
}
private class HugeColumnHeaderDataProvider implements IDataProvider {
private final int columnCount;
public HugeColumnHeaderDataProvider(int columnCount) {
this.columnCount = columnCount;
}
@Override
public Object getDataValue(int columnIndex, int rowIndex) {
return "Column Header" + columnIndex;
}
@Override
public void setDataValue(int columnIndex, int rowIndex, Object newValue) {
throw new UnsupportedOperationException();
}
@Override
public int getColumnCount() {
return this.columnCount;
}
@Override
public int getRowCount() {
return 1;
}
}
private class HugeBodyDataProvider implements IDataProvider {
private final int rowCount;
private final int columnCount;
public HugeBodyDataProvider(int rowCount, int columnCount) {
this.rowCount = rowCount;
this.columnCount = columnCount;
}
@Override
public Object getDataValue(int columnIndex, int rowIndex) {
return "Body data " + columnIndex + "/" + rowIndex;
}
@Override
public void setDataValue(int columnIndex, int rowIndex, Object newValue) {
throw new UnsupportedOperationException();
}
@Override
public int getColumnCount() {
return this.columnCount;
}
@Override
public int getRowCount() {
return this.rowCount;
}
}
// private class HugeListDataProvider extends ListDataProvider<T>
}