/***************************************************************************** * Copyright (c) 2015 CEA LIST. * * 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: * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation * *****************************************************************************/ package org.eclipse.nebula.widgets.nattable.examples.e4.part; import java.util.HashMap; import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; import org.eclipse.e4.ui.css.swt.CSSSWTConstants; import org.eclipse.e4.ui.services.EMenuService; import org.eclipse.jface.layout.GridDataFactory; 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.DefaultNatTableStyleConfiguration; import org.eclipse.nebula.widgets.nattable.config.EditableRule; import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry; import org.eclipse.nebula.widgets.nattable.copy.command.CopyDataToClipboardCommand; import org.eclipse.nebula.widgets.nattable.data.ExtendedReflectiveColumnPropertyAccessor; import org.eclipse.nebula.widgets.nattable.data.IDataProvider; import org.eclipse.nebula.widgets.nattable.data.ListDataProvider; import org.eclipse.nebula.widgets.nattable.data.validate.DataValidator; import org.eclipse.nebula.widgets.nattable.dataset.person.ExtendedPersonWithAddress; import org.eclipse.nebula.widgets.nattable.dataset.person.PersonService; import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes; import org.eclipse.nebula.widgets.nattable.edit.config.DefaultEditBindings; import org.eclipse.nebula.widgets.nattable.edit.config.DefaultEditConfiguration; import org.eclipse.nebula.widgets.nattable.examples.e4.AbstractE4NatExamplePart; import org.eclipse.nebula.widgets.nattable.extension.e4.painterfactory.CellPainterFactory; 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.DefaultColumnHeaderDataProvider; import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultGridLayer; import org.eclipse.nebula.widgets.nattable.layer.DataLayer; import org.eclipse.nebula.widgets.nattable.layer.cell.AggregateConfigLabelAccumulator; import org.eclipse.nebula.widgets.nattable.layer.cell.ColumnLabelAccumulator; import org.eclipse.nebula.widgets.nattable.layer.cell.ColumnOverrideLabelAccumulator; import org.eclipse.nebula.widgets.nattable.painter.cell.TextPainter; import org.eclipse.nebula.widgets.nattable.painter.cell.decorator.CustomLineBorderDecorator; import org.eclipse.nebula.widgets.nattable.style.DisplayMode; import org.eclipse.nebula.widgets.nattable.style.IStyle; 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.PopupMenuAction; import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuBuilder; import org.eclipse.nebula.widgets.nattable.util.GUIHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; @SuppressWarnings("restriction") public class CSSExample extends AbstractE4NatExamplePart { @Inject EMenuService menuService; @PostConstruct public void postConstruct(Composite parent, Shell shell) { parent.setLayout(new GridLayout()); // property names of the Person class // property names of the Person class String[] propertyNames = { "firstName", "lastName", "password", "description", "age", "money", "married", "gender", "address.street", "address.city", "favouriteFood", "favouriteDrinks" }; // mapping from property to label, needed for column header labels Map<String, String> propertyToLabelMap = new HashMap<>(); propertyToLabelMap.put("firstName", "Firstname"); propertyToLabelMap.put("lastName", "Lastname"); propertyToLabelMap.put("password", "Password"); propertyToLabelMap.put("description", "Description"); propertyToLabelMap.put("age", "Age"); propertyToLabelMap.put("money", "Money"); propertyToLabelMap.put("married", "Married"); propertyToLabelMap.put("gender", "Gender"); propertyToLabelMap.put("address.street", "Street"); propertyToLabelMap.put("address.city", "City"); propertyToLabelMap.put("favouriteFood", "Food"); propertyToLabelMap.put("favouriteDrinks", "Drinks"); IDataProvider bodyDataProvider = new ListDataProvider<>( PersonService.getExtendedPersonsWithAddress(10), new ExtendedReflectiveColumnPropertyAccessor<ExtendedPersonWithAddress>(propertyNames)); DefaultGridLayer gridLayer = new DefaultGridLayer(bodyDataProvider, new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap)); // unregister the default registered commandhandler to make the fill // handle work here for the age column gridLayer.unregisterCommandHandler(CopyDataToClipboardCommand.class); gridLayer.getBodyLayer().unregisterCommandHandler(CopyDataToClipboardCommand.class); final DataLayer bodyDataLayer = (DataLayer) gridLayer.getBodyDataLayer(); AggregateConfigLabelAccumulator accumulator = new AggregateConfigLabelAccumulator(); // create the ColumnLabelAccumulator with IDataProvider to be able to // tell the CSS engine about the added labels accumulator.add(new ColumnLabelAccumulator(bodyDataProvider)); ColumnOverrideLabelAccumulator columnLabelAccumulator = new ColumnOverrideLabelAccumulator(bodyDataLayer); columnLabelAccumulator.registerColumnOverrides(5, CustomLineBorderDecorator.RIGHT_LINE_BORDER_LABEL); accumulator.add(columnLabelAccumulator); bodyDataLayer.setConfigLabelAccumulator(accumulator); NatTable natTable = new NatTable(parent, gridLayer, false); natTable.addConfiguration(new DefaultNatTableStyleConfiguration()); natTable.addConfiguration(new FillHandleConfiguration(gridLayer.getBodyLayer().getSelectionLayer())); gridLayer.addConfiguration(new DefaultEditConfiguration()); gridLayer.addConfiguration(new DefaultEditBindings()); natTable.addConfiguration(new AbstractRegistryConfiguration() { @Override public void configureRegistry(IConfigRegistry configRegistry) { configRegistry.registerConfigAttribute( EditConfigAttributes.CELL_EDITABLE_RULE, EditableRule.ALWAYS_EDITABLE, DisplayMode.NORMAL, "COLUMN_4"); configRegistry.registerConfigAttribute( EditConfigAttributes.DATA_VALIDATOR, new DataValidator() { @Override public boolean validate(int columnIndex, int rowIndex, Object newValue) { if (newValue instanceof Integer && ((Integer) newValue).intValue() > 100) { return false; } return true; } }, DisplayMode.NORMAL, "COLUMN_4"); } }); natTable.setData(CSSSWTConstants.CSS_CLASS_NAME_KEY, "basic"); // application model menu configuration menuService.registerContextMenu( natTable, "org.eclipse.nebula.widgets.nattable.examples.e4.popupmenu.0"); // get the menu registered by EMenuService final Menu e4Menu = natTable.getMenu(); // remove the menu reference from NatTable instance natTable.setMenu(null); natTable.addConfiguration(new AbstractUiBindingConfiguration() { @Override public void configureUiBindings(UiBindingRegistry uiBindingRegistry) { // add NatTable menu items // and register the DisposeListener new PopupMenuBuilder(natTable, e4Menu) .withInspectLabelsMenuItem() .build(); // register the UI binding uiBindingRegistry.registerMouseDownBinding( new MouseEventMatcher( SWT.NONE, GridRegion.BODY, MouseEventMatcher.RIGHT_BUTTON), new PopupMenuAction(e4Menu)); } }); natTable.configure(); GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable); // add a custom painter for key errortext int[] yErrorOffsets = { 0, 1, 2, 1 }; CellPainterFactory.getInstance().registerContentPainter("errortext", (properties, underlying) -> { return new TextPainter(true, true, false) { @Override protected void paintDecoration( IStyle cellStyle, GC gc, int x, int y, int length, int fontHeight) { int underlineY = y + fontHeight - (gc.getFontMetrics().getDescent() / 2); Color previousColor = gc.getForeground(); gc.setForeground(GUIHelper.COLOR_RED); int startX = x; underlineY--; int index = 0; while (startX <= (x + length)) { gc.drawPoint(startX, underlineY + yErrorOffsets[(index % 4)]); index++; startX++; } gc.setForeground(previousColor); } }; }); showSourceLinks(parent, getClass().getName()); } }