Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    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 13:42 Go to next message
Andreea Sonda is currently offline Andreea SondaFriend
Messages: 11
Registered: May 2017
Junior Member
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 16:57 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2614
Registered: July 2012
Senior Member
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 17:22 Go to previous messageGo to next message
Andreea Sonda is currently offline Andreea SondaFriend
Messages: 11
Registered: May 2017
Junior Member
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 20:31 Go to previous messageGo to next message
Andreea Sonda is currently offline Andreea SondaFriend
Messages: 11
Registered: May 2017
Junior Member
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 20:50 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2614
Registered: July 2012
Senior Member
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 09:35 Go to previous messageGo to next message
Andreea Sonda is currently offline Andreea SondaFriend
Messages: 11
Registered: May 2017
Junior Member
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 08:55 Go to previous messageGo to next message
Andreea Sonda is currently offline Andreea SondaFriend
Messages: 11
Registered: May 2017
Junior Member
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 09:05]

Report message to a 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 10:17 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2614
Registered: July 2012
Senior Member
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 12:09 Go to previous messageGo to next message
Andreea Sonda is currently offline Andreea SondaFriend
Messages: 11
Registered: May 2017
Junior Member
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 17:07 Go to previous messageGo to next message
Andreea Sonda is currently offline Andreea SondaFriend
Messages: 11
Registered: May 2017
Junior Member
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 84 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 17:57 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2614
Registered: July 2012
Senior Member
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 18:41 Go to previous messageGo to next message
Andreea Sonda is currently offline Andreea SondaFriend
Messages: 11
Registered: May 2017
Junior Member
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 05:34 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2614
Registered: July 2012
Senior Member
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 05:36 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2614
Registered: July 2012
Senior Member
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 06:46 Go to previous messageGo to next message
Andreea Sonda is currently offline Andreea SondaFriend
Messages: 11
Registered: May 2017
Junior Member
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 06:49 Go to previous message
Andreea Sonda is currently offline Andreea SondaFriend
Messages: 11
Registered: May 2017
Junior Member
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: Tue Sep 18 22:05:35 GMT 2018

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

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

Back to the top