Skip to main content



      Home
Home » Eclipse Projects » NatTable » Create nattable with two column ,the second column has multiple dynamic rows inside.(Creating a customise nattable)
Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1763830] Sun, 21 May 2017 09:42 Go to next message
Eclipse UserFriend
I am struggling for a while with a problem.Please help me if you can.
I am trying to create a table in nattable that has two column.
The firs column is straight-forward but the second one is the the part that I don`t know how to create.
Each cell of the second column has to to have a dynamic number of rows, like in the image provided.Or to be more specific,each cell of the second column is divided into a variable number of rows.
I am using Nattable because of it`s capacity to handle large data, but any solution is good at this point. (JFace..etc)
Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1763895 is a reply to message #1763830] Mon, 22 May 2017 12:57 Go to previous messageGo to next message
Eclipse UserFriend
Was my answer on stackoverflow not good enough?

https://stackoverflow.com/questions/44097628/create-nattable-with-two-column-the-second-column-has-multiple-dynamic-rows-ins/44101095#44101095
Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1763898 is a reply to message #1763895] Mon, 22 May 2017 13:22 Go to previous messageGo to next message
Eclipse UserFriend
Hello.
I`ve posted the question at the same time on both sites,hoping that I would get a faster replay and because I was not sure that I will get an answer on StackOverflow.
Currently, I have some other problems with my code.
I will update you with the status of my project as soon as I will try to integrate the solution into my project.
Thank you for your interest.
Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1764100 is a reply to message #1763898] Wed, 24 May 2017 16:31 Go to previous messageGo to next message
Eclipse UserFriend
I tried the example from https://eclipse.org/nattable/nandn/nandn_110.php but it seems I am doing something wrong because the cell in`s not splitted. :(.
@Creatable
public class Part {
public void createNatTable(Composite parent) {
        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));

        final DataLayer bodyDataLayer = (DataLayer)gridLayer.getBodyDataLayer();

        final ColumnOverrideLabelAccumulator columnLabelAccumulator = new ColumnOverrideLabelAccumulator(bodyDataLayer);
        bodyDataLayer.setConfigLabelAccumulator(columnLabelAccumulator);
        registerColumnLabels(columnLabelAccumulator);

        this.natTable = new NatTable(parent, gridLayer, false);
        this.natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
        this.natTable.addConfiguration(new PainterConfiguration());
        this.natTable.configure();

        new NatTableContentTooltip(this.natTable, GridRegion.BODY);
    }

    private void registerColumnLabels(ColumnOverrideLabelAccumulator columnLabelAccumulator) {
        columnLabelAccumulator.registerColumnOverrides(0, COLUMN_ELEVEN_LABEL);

    }



    public class PainterConfiguration extends AbstractRegistryConfiguration {

        @Override
        public void configureRegistry(IConfigRegistry configRegistry) {
            registerPainters(configRegistry);
        }

        private void registerPainters(IConfigRegistry configRegistry) {

            registerColumnElevenTablePainter(configRegistry);

        }

        private void registerColumnElevenTablePainter(IConfigRegistry configRegistry) {
            //register the TableCellPainter for the food collection in the data model
            configRegistry.registerConfigAttribute(CellConfigAttributes.CELL_PAINTER, new TableCellPainter(),
                DisplayMode.NORMAL, COLUMN_ELEVEN_LABEL);

            //register the TableCellEditor for the food collection in the data model
            configRegistry.registerConfigAttribute(EditConfigAttributes.CELL_EDITOR, new TableCellEditor(),
                DisplayMode.NORMAL, COLUMN_ELEVEN_LABEL);
            // uncomment this to get an idea on how the TableCellEditor works
            configRegistry.registerConfigAttribute(EditConfigAttributes.CELL_EDITABLE_RULE,
                IEditableRule.ALWAYS_EDITABLE, DisplayMode.EDIT, COLUMN_ELEVEN_LABEL);
            //
            configRegistry.registerConfigAttribute(EditConfigAttributes.CELL_EDITOR, new TableCellEditor(),
                DisplayMode.NORMAL, COLUMN_ELEVEN_LABEL);

        }
}
Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1764103 is a reply to message #1764100] Wed, 24 May 2017 16:50 Go to previous messageGo to next message
Eclipse UserFriend
Well column 0 is showing the firstname and not a collection. You need to register the label for the correct column.

Our examples show this also.
Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1764319 is a reply to message #1764103] Sun, 28 May 2017 05:35 Go to previous messageGo to next message
Eclipse UserFriend
What a silly mistake from my side.
Thanks a lot!It works!
Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1764366 is a reply to message #1764319] Mon, 29 May 2017 04:55 Go to previous messageGo to next message
Eclipse UserFriend
Hello Dirk,
I have two question:
1.is it possible to have two different column providers for each column in the same table?
2.can I show two attributes of an object in the same cell (as it can be seen in the resulted_nattable, second column)

The problem that I have, is that the object that works as a provider for the first column has a list of objects that I want to use for the cell painter in the second column ,just as in the UML.
I need a second provider because I will also have to implement a ISelection provider for the both columns, enabling the user to modify the data in the both columns and keeping the back end model up to date.
I saw that the constructor of DefaultGridLayer does not provide a constructor for two column providers.

The wanted result can be found in the resulted_nattable.png

Thank you!
Have a nice day!

[Updated on: Mon, 29 May 2017 05:05] by Moderator

Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1764386 is a reply to message #1764366] Mon, 29 May 2017 06:17 Go to previous messageGo to next message
Eclipse UserFriend
Not sure what you mean. But you can implement your own IDataProvider and return whatever you want. Or implement a custom converter.
Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1764403 is a reply to message #1764386] Mon, 29 May 2017 08:09 Go to previous messageGo to next message
Eclipse UserFriend
I will try!Thank you for your prompt replay!
Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1765599 is a reply to message #1764386] Mon, 12 June 2017 13:07 Go to previous messageGo to next message
Eclipse UserFriend
Hello Dirk,
I am trying to add a context menu with delete and add row menus.
I tried to copy the code from _308_DataModificationExample into my workspace but I have some problems with DeleteRowCommandHandeler at doCommand() method.


Here is the errors I get:Quote:

"The method doCommand(ILayer, ExamplePart.InsertRowCommand) of type ExamplePart.InsertRowCommandHandler must override or implement a supertype method"




public class ExamplePart { 
public void createNatTable(Composite parent) {
        parent.setLayout(new GridLayout());

        // property names of the Person class
        String[] personPropertyNames = {
            "firstName",
            "lastName",
            "gender",
            "married",
            "birthday" };

        // mapping from property to label, needed for column header labels
        Map personPropertyToLabelMap = new HashMap();
        personPropertyToLabelMap.put("firstName", "Firstname");
        personPropertyToLabelMap.put("lastName", "Lastname");
        personPropertyToLabelMap.put("gender", "Gender");
        personPropertyToLabelMap.put("married", "Married");
        personPropertyToLabelMap.put("birthday", "Birthday");

        ListDataProvider bodyDataProvider = new ListDataProvider<>(
            PersonService.getPersons(10),
            new ReflectiveColumnPropertyAccessor(personPropertyNames));

        IDataProvider personColumnHeaderDataProvider =
            new DefaultColumnHeaderDataProvider(personPropertyNames, personPropertyToLabelMap);

        IDataProvider personRowHeaderDataProvider = new DefaultRowHeaderDataProvider(bodyDataProvider);

        // mapping from property to label, needed for column header labels
        Map addressPropertyToLabelMap = new HashMap();
        addressPropertyToLabelMap.put("street", "Street");
        addressPropertyToLabelMap.put("housenumber", "Housenumber");
        addressPropertyToLabelMap.put("postalCode", "Postal Code");
        addressPropertyToLabelMap.put("city", "City");

        Composite panel = new Composite(parent, SWT.NONE);
        panel.setLayout(new GridLayout());
        GridDataFactory.fillDefaults().grab(true, true).applyTo(panel);

        Composite gridPanel = new Composite(panel, SWT.NONE);
        gridPanel.setLayout(new GridLayout());
        GridDataFactory.fillDefaults().grab(true, true).applyTo(gridPanel);

        Composite buttonPanel = new Composite(panel, SWT.NONE);
        buttonPanel.setLayout(new GridLayout());
        GridDataFactory.fillDefaults().grab(true, true).applyTo(buttonPanel);

        ConfigRegistry configRegistry = new ConfigRegistry();

        // create the body layer stack
        DataLayer bodyDataLayer = new DataLayer(bodyDataProvider);
        bodyDataLayer.setConfigLabelAccumulator(new IConfigLabelAccumulator() {

            @Override
            public void accumulateConfigLabels(LabelStack configLabels, int columnPosition, int rowPosition) {
                switch (columnPosition) {
                    case 3:
                        configLabels.addLabel("MARRIED");
                        break;
                    case 4:
                        configLabels.addLabel("DATE");
                        break;
                }
            }
        });
        DefaultBodyLayerStack bodyLayerStack = new DefaultBodyLayerStack(bodyDataLayer);

        bodyDataLayer.registerCommandHandler(
            new DeleteRowCommandHandler(bodyDataProvider.getList()));
        //        bodyDataLayer.registerCommandHandler(
        //            new InsertRowCommandHandler(bodyDataProvider.getList()));

        // create the column header layer stack
        DataLayer columnHeaderDataLayer = new DataLayer(personColumnHeaderDataProvider);
        ILayer columnHeaderLayer = new ColumnHeaderLayer(
            columnHeaderDataLayer,
            bodyLayerStack.getViewportLayer(),
            bodyLayerStack.getSelectionLayer());
        DataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(personRowHeaderDataProvider);
        ILayer rowHeaderLayer = new RowHeaderLayer(
            rowHeaderDataLayer,
            bodyLayerStack.getViewportLayer(),
            bodyLayerStack.getSelectionLayer());

        // create the corner layer stack
        ILayer cornerLayer = new CornerLayer(new DataLayer(
            new DefaultCornerDataProvider(
                personColumnHeaderDataProvider,
                personRowHeaderDataProvider)),
            rowHeaderLayer,
            columnHeaderLayer);

        // create the grid layer composed with the prior created layer stacks
        GridLayer gridLayer = new GridLayer(
            bodyLayerStack,
            columnHeaderLayer,
            rowHeaderLayer,
            cornerLayer);

        final NatTable natTable = new NatTable(gridPanel, gridLayer, false);
        natTable.setConfigRegistry(configRegistry);
        natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
        natTable.addConfiguration(new HeaderMenuConfiguration(natTable));
        natTable.addConfiguration(new SingleClickSortConfiguration());

        natTable.addConfiguration(new AbstractRegistryConfiguration() {

            @Override
            public void configureRegistry(IConfigRegistry configRegistry) {
                configRegistry.registerConfigAttribute(
                    CellConfigAttributes.CELL_PAINTER,
                    new CheckBoxPainter(),
                    DisplayMode.NORMAL,
                    "MARRIED");
                configRegistry.registerConfigAttribute(
                    CellConfigAttributes.DISPLAY_CONVERTER,
                    new DefaultDateDisplayConverter("yyyy-MM-dd"),
                    DisplayMode.NORMAL,
                    "DATE");
            }
        });

        natTable.addConfiguration(new AbstractUiBindingConfiguration() {

            private final Menu bodyMenu = new PopupMenuBuilder(natTable)
                .withMenuItemProvider(new IMenuItemProvider() {

                    @Override
                    public void addMenuItem(NatTable natTable, Menu popupMenu) {
                        MenuItem deleteRow = new MenuItem(popupMenu, SWT.PUSH);
                        deleteRow.setText("Insert below");
                        deleteRow.setEnabled(true);

                        deleteRow.addSelectionListener(new SelectionAdapter() {

                            @Override
                            public void widgetSelected(SelectionEvent event) {
                                int rowPosition = MenuItemProviders.getNatEventData(event).getRowPosition();
                                //                                natTable.doCommand(new InsertRowCommand(bodyDataLayer, rowPosition,
                                //                                    PersonService.getPersons(1).get(0)));
                            }
                        });
                    }
                })
                .withMenuItemProvider(new IMenuItemProvider() {

                    @Override
                    public void addMenuItem(NatTable natTable, Menu popupMenu) {
                        MenuItem deleteRow = new MenuItem(popupMenu, SWT.PUSH);
                        deleteRow.setText("Delete");
                        deleteRow.setEnabled(true);

                        deleteRow.addSelectionListener(new SelectionAdapter() {

                            @Override
                            public void widgetSelected(SelectionEvent event) {
                                int rowPosition = MenuItemProviders.getNatEventData(event).getRowPosition();
                                natTable.doCommand(new DeleteRowCommand(natTable, rowPosition));
                            }
                        });
                    }
                })
                .build();

            @Override
            public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
                uiBindingRegistry.registerMouseDownBinding(
                    new MouseEventMatcher(
                        SWT.NONE,
                        GridRegion.BODY,
                        MouseEventMatcher.RIGHT_BUTTON),
                    new PopupMenuAction(this.bodyMenu) {

                        @Override
                        public void run(NatTable natTable, MouseEvent event) {
                            int columnPosition = natTable.getColumnPositionByX(event.x);
                            int rowPosition = natTable.getRowPositionByY(event.y);

                            if (!bodyLayerStack.getSelectionLayer().isRowPositionFullySelected(rowPosition)) {
                                natTable.doCommand(
                                    new SelectRowsCommand(
                                        natTable,
                                        columnPosition,
                                        rowPosition,
                                        false,
                                        false));
                            }

                            super.run(natTable, event);
                        }
                    });
            }

        });

        natTable.configure();
        GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);
    }

    class InsertRowCommand extends AbstractRowCommand {

        private final T object;

        public InsertRowCommand(ILayer layer, int rowPosition, T object) {
            super(layer, rowPosition);
            this.object = object;
        }

        protected InsertRowCommand(InsertRowCommand command) {
            super(command);
            this.object = command.object;
        }

        @Override
        public ILayerCommand cloneCommand() {
            return new InsertRowCommand(this);
        }

        public T getObject() {
            return this.object;
        }

    }

    /**
     * The command handler for inserting a row.
     *
     * @param
     */
    @SuppressWarnings ("rawtypes")
    class InsertRowCommandHandler implements ILayerCommandHandler {

        private List bodyData;

        public InsertRowCommandHandler(List bodyData) {
            this.bodyData = bodyData;
        }

        @Override
        public Class getCommandClass() {
            return InsertRowCommand.class;
        }

        @SuppressWarnings ("unchecked")
        @Override
        public boolean doCommand(ILayer targetLayer, InsertRowCommand command) {
            // convert the transported position to the target layer
            if (command.convertToTargetLayer(targetLayer)) {
                // remove the element
                this.bodyData.add(command.getRowPosition(), (T)command.getObject());
                // fire the event to refresh
                targetLayer.fireLayerEvent(new RowInsertEvent(targetLayer, command.getRowPosition()));
                return true;
            }
            return false;
        }

        @Override
        public boolean doCommand(ILayer targetLayer, ILayerCommand command) {
            // TODO Auto-generated method stub
            return false;

        }

    }

    /**
     * Command to delete a row.
     */
     class DeleteRowCommand extends AbstractRowCommand {

        public DeleteRowCommand(ILayer layer, int rowPosition) {
            super(layer, rowPosition);
        }

        protected DeleteRowCommand(DeleteRowCommand command) {
            super(command);
        }

        @Override
        public ILayerCommand cloneCommand() {
            return new DeleteRowCommand(this);
        }

    }

    /**
     * The command handler for deleting a row.
     *
     * @param
     */
    class DeleteRowCommandHandler implements ILayerCommandHandler {

        private List bodyData;

        public DeleteRowCommandHandler(List bodyData) {
            this.bodyData = bodyData;
        }

        @Override
        public Class getCommandClass() {
            return DeleteRowCommand.class;
        }

        @Override
        public boolean doCommand(ILayer targetLayer, DeleteRowCommand command) {
            // convert the transported position to the target layer
            if (command.convertToTargetLayer(targetLayer)) {
                // remove the element
                this.bodyData.remove(command.getRowPosition());
                // fire the event to refresh
                targetLayer.fireLayerEvent(new RowDeleteEvent(targetLayer, command.getRowPosition()));
                return true;
            }
            return false;
        }

        @Override
        public boolean doCommand(ILayer targetLayer, ILayerCommand command) {
            // TODO Auto-generated method stub
            return false;

        }

    }
}



If I tried to fix the problem , the menu appears in the context menu but does nothing.
  • Attachment: error.PNG
    (Size: 46.78KB, Downloaded 250 times)
Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1765605 is a reply to message #1765599] Mon, 12 June 2017 13:57 Go to previous messageGo to next message
Eclipse UserFriend
ILayerCommandHandler is a generic interface. So it should be

class DeleteRowCommandHandler implements ILayerCommandHandler<DeleteRowCommand>


I suppose the overloading methods is not working.
Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1765608 is a reply to message #1765605] Mon, 12 June 2017 14:41 Go to previous messageGo to next message
Eclipse UserFriend
Yes, that is the solution.Thank you!

But now I have another problem...the UI is not refreshing after a row delete.

If I try to delete twice the same row I get an error..so I suppose the delete is working but the UI is not refreshing.

Do you think it has something to do with the fact that the class is @Creatable and it`s used as a PartDescriptor in a fragment.e4xmi ??

From your answer on Stack Overflow ( https://stackoverflow.com/questions/31907288/delete-rows-from-nattable) I understood that the table should refresh automatically after RowDeleteEvent....
Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1765645 is a reply to message #1765608] Tue, 13 June 2017 01:34 Go to previous messageGo to next message
Eclipse UserFriend
Testing your example and fixing all the errors and warnings with regards to generics makes it work exactly as intended. The refresh is performed automatically.
Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1765646 is a reply to message #1765645] Tue, 13 June 2017 01:36 Go to previous messageGo to next message
Eclipse UserFriend
And BTW, don't hijack a forum post for multiple questions! this way others will not be able to find the answer if they have a similar question!
Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1765650 is a reply to message #1765645] Tue, 13 June 2017 02:46 Go to previous messageGo to next message
Eclipse UserFriend
I will have another look ! Thank you for your time!
Re: Create nattable with two column ,the second column has multiple dynamic rows inside. [message #1765651 is a reply to message #1765646] Tue, 13 June 2017 02:49 Go to previous message
Eclipse UserFriend
You are right!I haven`t thought of that!
If I will have other problem will create a separate question.
Have a nice day!
Previous Topic:"Interrupted Selection" creates Multiselection effect
Next Topic:Remove row numbers in Nattable
Goto Forum:
  


Current Time: Wed Jul 23 19:45:19 EDT 2025

Powered by FUDForum. Page generated in 0.05196 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top