Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » NatTable » Some issues with layout and refresh after list data changed
Some issues with layout and refresh after list data changed [message #1707645] Tue, 08 September 2015 10:08 Go to next message
Mick Miralas is currently offline Mick MiralasFriend
Messages: 16
Registered: July 2015
Junior Member
Hello,

I have the following issues and kindly ask for help:

1.) The horizontalSpan is set to 4, but the columns don't fit to the whole space, as you can see in the attached picture "guiFilled.PNG".
2.) The verticalSpan changes its value automatically to -1 after I set it to 4. As you can see in the attached picture "guiDesign.PNG" I can influence the size by clicking and moving the frame, but during runtime, NatTable doesn't use the whole vertical space.
3.) As you can see in the attached picture "guiFilled.PNG" the row count numbers are shortened to 14..., i.e. the column does not grow.
4.) I have a private instance variable "underlyingLayer" of type FilterRowExampleGridLayer. After entering the search parameters and clicking on Search, within the event handler, I am using the following code in order to replace the old list data and providing the list with the new data:

underlyingLayer.getEventList().clear();
unerlyingLayer.getEventList().addAll(searchResultsList);


-Is this a good solution or can this be done more elegantly?
-Problem: NatTable doesn't refresh, i.e. I have to click within the area of NatTable to let it show the new data.

Thank you very much!

Regards,
Mick
Re: Some issues with layout and refresh after list data changed [message #1707657 is a reply to message #1707645] Tue, 08 September 2015 12:07 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2803
Registered: July 2012
Senior Member
Quote:
1.) The horizontalSpan is set to 4, but the columns don't fit to the whole space, as you can see in the attached picture "guiFilled.PNG".


How do you set the horizontalSpan? Are you using a SpanningDataLayer?

Quote:
2.) The verticalSpan changes its value automatically to -1 after I set it to 4. As you can see in the attached picture "guiDesign.PNG" I can influence the size by clicking and moving the frame, but during runtime, NatTable doesn't use the whole vertical space.


Again, how do you set the verticalSpan? I'm not sure if you use the framework for that. It looks like you are overriding some internal methods?

Quote:
3.) As you can see in the attached picture "guiFilled.PNG" the row count numbers are shortened to 14..., i.e. the column does not grow.


If you don't configure that it should do that, it won't do that. I assume you are using the DefaultRowHeaderDataLayer which sets a default width of 40 pixels. Either change the default width to something bigger or configure a TextPainter that is configured for automatic size calculation.

Quote:
-Is this a good solution or can this be done more elegantly?


That depends on your architecture. But yes, you typically operate on the EventList directly.

Quote:
-Problem: NatTable doesn't refresh, i.e. I have to click within the area of NatTable to let it show the new data.


Are you using the GlazedListsEventLayer in your composition? That layer is responsible for listening to list change events and propagate the refresh to NatTable.
Re: Some issues with layout and refresh after list data changed [message #1707752 is a reply to message #1707657] Wed, 09 September 2015 06:35 Go to previous messageGo to next message
Mick Miralas is currently offline Mick MiralasFriend
Messages: 16
Registered: July 2015
Junior Member
Quote:
How do you set the horizontalSpan? Are you using a SpanningDataLayer?

Again, how do you set the verticalSpan? I'm not sure if you use the framework for that. It looks like you are overriding some internal methods?


Actually, I have adapted the example classes, especially "FilterRowGridExample" and "FilterRowExampleGridLayer" which extends GridLayer. I think I should also mention the following three lines:

GridData gd_natTable = new GridData(SWT.FILL, SWT.FILL, false, false, 4, 1);
gd_natTable.heightHint = 323;
natTable.setLayoutData(gd_natTable);


Quote:
If you don't configure that it should do that, it won't do that. I assume you are using the DefaultRowHeaderDataLayer which sets a default width of 40 pixels. Either change the default width to something bigger or configure a TextPainter that is configured for automatic size calculation.


I've tried the first option, but it doesn't show a difference:

// Column header layer
IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);
DataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);
ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, bodyLayer, bodyLayer.getSelectionLayer());
columnHeaderDataLayer.setDefaultColumnWidth(100);


Quote:
Are you using the GlazedListsEventLayer in your composition? That layer is responsible for listening to list change events and propagate the refresh to NatTable.


No. In relation to the example classes: How/Where do I have to set that?
Re: Some issues with layout and refresh after list data changed [message #1707753 is a reply to message #1707752] Wed, 09 September 2015 06:52 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2803
Registered: July 2012
Senior Member
Regarding the spanning, yes it would have been useful to tell me that you are talking about SWT layouts and not NatTable spanning.

NatTable is using the whole space correctly according to the SWT layout. But your column widths are configured statically. By default every column has 100 pixels width, and that won't change simply by configuring the SWT layout. If you want some different behavior you need to specify what you expect. For example, you could tell the last column to use percentage sizing, so that column would increase/decrease according to the available space. You can also tell all columns to use percentage sizing, so all columns are calculated according to the available width. This can be done via DataLayer#setColumnPercentageSizing()

Regarding the row header width, it won't change anything if you configure the column header column widths! It needs to be the ROW header.

Regarding the examples, there are a lot. And maybe it is better to switch to the Tutorial examples I created for a better understanding of the different features, than to look at the classic examples. So maybe Tutorial Examples -> GlazedLists -> Filter -> GlazedListsFilterExample (_6031_GlazedListsFilterExample in case you have checked out the sources) gives you a better understanding.
Re: Some issues with layout and refresh after list data changed [message #1707765 is a reply to message #1707753] Wed, 09 September 2015 09:04 Go to previous messageGo to next message
Mick Miralas is currently offline Mick MiralasFriend
Messages: 16
Registered: July 2015
Junior Member
Sorry for the misunderstandings. I'm just fighting a little bit with the details, since this technology is quite new to me...

The horizontal spanning works just perfectly fine now. But how do I handle the vertical spanning (the problem is that org.eclipse.swt.layout.GridData doesn't accept other values than 1 for verticalSpan)?

Quote:
Regarding the examples, there are a lot. And maybe it is better to switch to the Tutorial examples I created for a better understanding of the different features, than to look at the classic examples. So maybe Tutorial Examples -> GlazedLists -> Filter -> GlazedListsFilterExample (_6031_GlazedListsFilterExample in case you have checked out the sources) gives you a better understanding.


I've looked into this example. So the important code should be the following:

// layer for event handling of GlazedLists and PropertyChanges
GlazedListsEventLayer<T> glazedListsEventLayer = new GlazedListsEventLayer<T>(bodyDataLayer, this.filterList);
this.selectionLayer = new SelectionLayer(glazedListsEventLayer);
ViewportLayer viewportLayer = new ViewportLayer(getSelectionLayer());

setUnderlyingLayer(viewportLayer);


I understand the constructor part of GlazedListsEventLayer, but I fail to understand how to employ it in my adapted class "FilterRowExampleGridLayer". Could you have a look into it and give me some hints, please?

Thank you!
Re: Some issues with layout and refresh after list data changed [message #1707771 is a reply to message #1707765] Wed, 09 September 2015 09:40 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2803
Registered: July 2012
Senior Member
I still don't understand what you are trying to achieve. Is it about the height of the table? Maybe you have another control that takes the other space?

Regarding the composition, have a look at my getting started tutorial: http://www.vogella.com/tutorials/NatTable/article.html

You need to add the GlazedListsEventLayer on top of the DataLayer of your body layer stack. The FilterRowExampleGridLayer has a DefaultBodyLayerStack which doesn't contain the GlazedListsEventLayer. So basically you need to exchange that with a custom implementation as shown in the other examples.
Re: Some issues with layout and refresh after list data changed [message #1707790 is a reply to message #1707771] Wed, 09 September 2015 11:42 Go to previous messageGo to next message
Mick Miralas is currently offline Mick MiralasFriend
Messages: 16
Registered: July 2015
Junior Member
Quote:
I still don't understand what you are trying to achieve. Is it about the height of the table? Maybe you have another control that takes the other space?


Maybe I see things totally wrong. If you look into the attached file, there is an arrow that shows to a point I can move in order to change the size of the frame. Instead of moving the frame, I would like to set a value for vertical spanning, e.g. 8, such that vertical spanning goes over 8 rows. The problem is that after setting this value, it automatically jumps to 1.

Quote:
You need to add the GlazedListsEventLayer on top of the DataLayer of your body layer stack. The FilterRowExampleGridLayer has a DefaultBodyLayerStack which doesn't contain the GlazedListsEventLayer. So basically you need to exchange that with a custom implementation as shown in the other examples.


Which BodyLayerStack should I use instead of the default one?

[Updated on: Wed, 09 September 2015 11:43]

Report message to a moderator

Re: Some issues with layout and refresh after list data changed [message #1707792 is a reply to message #1707790] Wed, 09 September 2015 11:58 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2803
Registered: July 2012
Senior Member
Quote:
Maybe I see things totally wrong. If you look into the attached file, there is an arrow that shows to a point I can move in order to change the size of the frame. Instead of moving the frame, I would like to set a value for vertical spanning, e.g. 8, such that vertical spanning goes over 8 rows. The problem is that after setting this value, it automatically jumps to 1.


I don't know what you are showing me. Is this WindowBuilder? I never use this.

Quote:
Which BodyLayerStack should I use instead of the default one?


You should create your own.
Re: Some issues with layout and refresh after list data changed [message #1707874 is a reply to message #1707792] Thu, 10 September 2015 07:28 Go to previous messageGo to next message
Mick Miralas is currently offline Mick MiralasFriend
Messages: 16
Registered: July 2015
Junior Member
Quote:
I don't know what you are showing me. Is this WindowBuilder? I never use this.


Yes, it's WindowsBuilder. What are you using?

Quote:
You should create your own.


Now it works. Yesterday, I didn't see the code "class BodyLayerStack<T> extends AbstractLayerTransform". But what is the purpose of the ViewportLayer and is its usage compulsory when writing an own BodyLayerStack?

I have another question concerning "SortableGridExample": I've added the line "this.nattable.addConfiguration(new SingleClickSortConfiguration());" to my code in order to support multi column sorting, but sorting doesn't work at all. What am I missing?
Re: Some issues with layout and refresh after list data changed [message #1707882 is a reply to message #1707874] Thu, 10 September 2015 07:56 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2803
Registered: July 2012
Senior Member
Quote:
Yes, it's WindowsBuilder. What are you using?


I build my UIs programmatically to avoid such issues. I really don't have a clue what your layout issue could be.

Quote:
But what is the purpose of the ViewportLayer and is its usage compulsory when writing an own BodyLayerStack?


The ViewportLayer is necessary to support handling of large datasets and scrolling.

Quote:
I've added the line "this.nattable.addConfiguration(new SingleClickSortConfiguration());" to my code in order to support multi column sorting, but sorting doesn't work at all. What am I missing?


Is there a SortHeaderLayer in your column header layer stack? Do you have a SortedList somewhere? I think the examples should point out to everything.
Re: Some issues with layout and refresh after list data changed [message #1707906 is a reply to message #1707882] Thu, 10 September 2015 11:39 Go to previous messageGo to next message
Mick Miralas is currently offline Mick MiralasFriend
Messages: 16
Registered: July 2015
Junior Member
Quote:
I build my UIs programmatically to avoid such issues. I really don't have a clue what your layout issue could be.


OK, then I think it's the best if you could tell me how you set the vertical spanning in a org.eclipse.swt.layout.GridLayout, please?

Quote:
Is there a SortHeaderLayer in your column header layer stack? Do you have a SortedList somewhere? I think the examples should point out to everything.


No and no. I am trying to understand which ingredients I need for multi column sorting by understanding the example "SortableGridExample", but even after some hours I don't see what is really necessary. So the line "this.nattable.addConfiguration(new SingleClickSortConfiguration());" should be one ingredient. Which are the other ones and how do I need to employ them?

EDIT:
Concerning my second question. Now I found this useful sentence "@see GlazedListsGridLayer to see the required stack setup." I'll check it first, so you don't need to answer to the second question.

[Updated on: Thu, 10 September 2015 12:01]

Report message to a moderator

Re: Some issues with layout and refresh after list data changed [message #1707908 is a reply to message #1707906] Thu, 10 September 2015 12:24 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2803
Registered: July 2012
Senior Member
Quote:
OK, then I think it's the best if you could tell me how you set the vertical spanning in a org.eclipse.swt.layout.GridLayout, please?


I use the GridDataFactory. Maybe you should investigate some time in understanding SWT layouts.

http://www.eclipse.org/articles/article.php?file=Article-Understanding-Layouts/index.html
http://www.eclipse.org/articles/Article-Understanding-Layouts/Understanding-Layouts.htm
http://www.vogella.com/tutorials/SWT/article.html#layout
http://eclipsesource.com/blogs/2013/07/25/efficiently-dealing-with-swt-gridlayout-and-griddata/
http://www.vogella.com/tutorials/SWT/article.html#swtlayout_gridatafactory

Not sure what to post more. There are plenty of examples and explanations in the web.
Re: Some issues with layout and refresh after list data changed [message #1708145 is a reply to message #1707908] Mon, 14 September 2015 08:46 Go to previous messageGo to next message
Mick Miralas is currently offline Mick MiralasFriend
Messages: 16
Registered: July 2015
Junior Member
Unfortunately, I don't know how to successfully finish the implementation of sorting, since I am faced with more and more issues. My problem now is that GlazedlistsColumnHeader constructor receives a DefaultBodyLayerStack, but I have implemented a custom BodyLayerStack. Any help would be much appreciated (maybe it's simple, but I am in the end phase of the thesis and therefore probably blind):

/*******************************************************************************
* Copyright (c) 2012, 2013 Original authors and others.
* 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:
*     Original authors and others - initial API and implementation

******************************************************************************/

package anwendungsservertest.view;

import java.util.ArrayList;
import java.util.Map;

import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
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.extension.glazedlists.GlazedListsEventLayer;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsSortModel;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.filterrow.DefaultGlazedListsFilterStrategy;
import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowHeaderComposite;
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.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.layer.AbstractLayerTransform;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.layer.cell.ColumnOverrideLabelAccumulator;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer;
import org.eclipse.nebula.widgets.nattable.util.IClientAreaProvider;
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;

import anwendungsservertest.serverklassen.Part2;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.FilterList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.SortedList;
import ca.odell.glazedlists.TransformedList;

/**
* Factory for assembling GridLayer and the child layers - with support for
* GlazedLists and sorting
*
* @see {@linkplain http://publicobject.com/glazedlists/}
*/

public class GlazedListsGridLayer<T> extends GridLayer {

	private ListDataProvider<T> bodyDataProvider;
    private EventList eventList;
    private TransformedList rowObjectsGlazedList;
    private GlazedListsColumnHeaderLayerStack<T> columnHeaderLayerStack;

    private DataLayer bodyDataLayer;
	private BodyLayerStack bodyLayerStack;
	private ColumnOverrideLabelAccumulator bodyLabelAccumulator;

    public GlazedListsGridLayer(IConfigRegistry configRegistry) {

        super(true);

        // Underlying data source
        this.eventList = GlazedLists.eventList(new ArrayList<T>());
        FilterList filterList = new FilterList(this.eventList);
        this.rowObjectsGlazedList = GlazedLists.threadSafeList(filterList);
        String[] propertyNames = {"prtno", "nomcl", "inidt", "prtky", "testts", "remark", "testdf", "testti"};
        Map<String, String> propertyToLabelMap = RowDataListFixture.getPropertyToLabelMap();

        // Body layer
        IColumnPropertyAccessor<T> columnPropertyAccessor = new ReflectiveColumnPropertyAccessor<T>(propertyNames);
        this.bodyDataProvider = new ListDataProvider<T>(filterList, columnPropertyAccessor);
        this.bodyDataLayer = new DataLayer(this.bodyDataProvider);
        bodyDataLayer.setColumnPercentageSizing(true);
        // layer for event handling of GlazedLists and PropertyChanges
        GlazedListsEventLayer<T> glazedListsEventLayer = new GlazedListsEventLayer<T>(this.bodyDataLayer, filterList);
        this.bodyLayerStack = new BodyLayerStack(glazedListsEventLayer);
        this.bodyLabelAccumulator = new ColumnOverrideLabelAccumulator(bodyDataLayer);
        bodyDataLayer.setConfigLabelAccumulator(bodyLabelAccumulator);

        /*bodyLabelAccumulator.registerColumnOverrides(RowDataListFixture.getColumnIndexOfProperty(RowDataListFixture.PRICING_TYPE_PROP_NAME),

                        "PRICING_TYPE_PROP_NAME");*/

        // Body - with list event listener
        // NOTE: Remember to use the SortedList constructor with 'null' for the Comparator
        SortedList<T> sortedList = new SortedList<T>(rowObjectsGlazedList, null);
        this.bodyDataProvider = new ListDataProvider<T>(sortedList, columnPropertyAccessor);
        this.bodyDataLayer = new DataLayer(this.bodyDataProvider);
        
        // Column header layer
        IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);
        DataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);
        ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, bodyLayerStack, bodyLayerStack.getSelectionLayer());
        SortHeaderLayer<T> sortHeaderLayer = new SortHeaderLayer<T>(columnHeaderLayer, new GlazedListsSortModel<T>(sortedList, columnPropertyAccessor,
                        configRegistry, columnHeaderDataLayer), false);

        this.columnHeaderLayerStack = new GlazedListsColumnHeaderLayerStack<T>(columnHeaderDataProvider, sortedList, columnPropertyAccessor,
                configRegistry, this.bodyLayerStack);

        // Note: The column header layer is wrapped in a filter row composite.
        // This plugs in the filter row functionality
        FilterRowHeaderComposite<T> filterRowHeaderLayer = new FilterRowHeaderComposite<T>(
                        new DefaultGlazedListsFilterStrategy<T>(filterList, columnPropertyAccessor, configRegistry),
                        sortHeaderLayer, columnHeaderDataProvider, configRegistry);

        // Row header
        DefaultRowHeaderDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(this.bodyDataProvider);
        DefaultRowHeaderDataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
        RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, this.bodyLayerStack, this.bodyLayerStack.getSelectionLayer());
		
        // Corner
        DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(this.columnHeaderLayerStack.getDataProvider(), rowHeaderDataProvider);
        DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);
        CornerLayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer, this.columnHeaderLayerStack);

        // Grid
        setBodyLayer(this.bodyLayerStack);
        setColumnHeaderLayer(this.columnHeaderLayerStack);
        setRowHeaderLayer(rowHeaderLayer);
        setCornerLayer(cornerLayer);
    }

    public ColumnOverrideLabelAccumulator getColumnLabelAccumulator() {
                        return bodyLabelAccumulator;
    }

    @Override
    public void setClientAreaProvider(IClientAreaProvider clientAreaProvider) {
        super.setClientAreaProvider(clientAreaProvider);
    }

    public DataLayer getBodyDataLayer() {
        return this.bodyDataLayer;
    }

    public ListDataProvider<T> getBodyDataProvider() {
        return this.bodyDataProvider;
    }

    public GlazedListsColumnHeaderLayerStack<T> getColumnHeaderLayerStack() {
        return this.columnHeaderLayerStack;
    }

    public BodyLayerStack getBodyLayerStack() {
        return this.bodyLayerStack;
    }

    public EventList getEventList(){
        eturn eventList;
    }

    /**
     * Always encapsulate the body layer stack in an AbstractLayerTransform to
     * ensure that the index transformations are performed in later commands.
     *
     * @param <T>
     */
    class BodyLayerStack<T> extends AbstractLayerTransform {
        private final SelectionLayer selectionLayer;

        public BodyLayerStack(GlazedListsEventLayer<T> glazedListsEventLayer) {
            this.selectionLayer = new SelectionLayer(glazedListsEventLayer);
            ViewportLayer viewportLayer = new ViewportLayer(getSelectionLayer());
            setUnderlyingLayer(viewportLayer);
        }

        public SelectionLayer getSelectionLayer() {
            return this.selectionLayer;
        }
    }
}
Re: Some issues with layout and refresh after list data changed [message #1708146 is a reply to message #1708145] Mon, 14 September 2015 09:06 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2803
Registered: July 2012
Senior Member
I think I told you before not to use the Classic examples, as they are mostly hard to understand. Especially because the guys who implemented them created new classes in different packages that are not highly visible.

In short, why are you using the GlazedListsColumnHeaderLayerStack? It is a class implemented for such a classic example and it is not published as part of the installable NatTable parts. So using it will make things more difficult when it comes to things like automated builds and deployment.

In the Tutorial section of the examples you should find better examples. You simply need to create a custom column header layer stack that combines everything. And if you want to stick with the GlazedListsColumnHeaderLayerStack, copy it into your project and modify it to fit your needs.

You should also be careful with the layer stack creation. AFAIKS you are creating a body layer stack twice, which will lead to reference issues later on.
Re: Some issues with layout and refresh after list data changed [message #1708152 is a reply to message #1708146] Mon, 14 September 2015 09:52 Go to previous messageGo to next message
Mick Miralas is currently offline Mick MiralasFriend
Messages: 16
Registered: July 2015
Junior Member
Quote:
And if you want to stick with the GlazedListsColumnHeaderLayerStack, copy it into your project and modify it to fit your needs.


Due to time pressure I sticked with the GlazedListsColumnHeaderLayerStack and modified it.

Quote:
You should also be careful with the layer stack creation. AFAIKS you are creating a body layer stack twice, which will lead to reference issues later on.


At which place does this happen?


My new code is the following one, but I get errors (please see attached file):

/*******************************************************************************
 * Copyright (c) 2012, 2013 Original authors and others.
 * 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:
 *     Original authors and others - initial API and implementation
 ******************************************************************************/
package anwendungsservertest.view;

import java.util.ArrayList;
import java.util.Map;

import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
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.extension.glazedlists.GlazedListsEventLayer;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.filterrow.DefaultGlazedListsFilterStrategy;
import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowHeaderComposite;
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.DefaultRowHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
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.layer.AbstractLayerTransform;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.layer.cell.ColumnOverrideLabelAccumulator;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.util.IClientAreaProvider;
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;

import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.FilterList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.SortedList;
import ca.odell.glazedlists.TransformedList;

/**
 * Factory for assembling GridLayer and the child layers - with support for
 * GlazedLists and sorting
 *
 * @see {@linkplain http://publicobject.com/glazedlists/}
 */
public class GlazedListsGridLayer<T> extends GridLayer {
	
	private ListDataProvider<T> bodyDataProvider;
    private EventList eventList;
    private TransformedList rowObjectsGlazedList;

    private GlazedListsColumnHeaderLayerStack<T> columnHeaderLayerStack;
	private DataLayer bodyDataLayer;
	private BodyLayerStack bodyLayerStack;
	private ColumnOverrideLabelAccumulator bodyLabelAccumulator;
	private IDataProvider columnHeaderDataProvider;

    public GlazedListsGridLayer(IConfigRegistry configRegistry) {

        super(true);

        // Underlying data source
        this.eventList = GlazedLists.eventList(new ArrayList<T>());
        FilterList filterList = new FilterList(this.eventList);
        this.rowObjectsGlazedList = GlazedLists.threadSafeList(filterList);
        String[] propertyNames = {"prtno", "nomcl", "inidt", "prtky", "testts", "remark", "testdf", "testti"};
        Map<String, String> propertyToLabelMap = RowDataListFixture.getPropertyToLabelMap();
        
        // Body layer
        IColumnPropertyAccessor<T> columnPropertyAccessor = new ReflectiveColumnPropertyAccessor<T>(propertyNames);
        this.bodyDataProvider = new ListDataProvider<T>(filterList, columnPropertyAccessor);
        this.bodyDataLayer = new DataLayer(this.bodyDataProvider);
        bodyDataLayer.setColumnPercentageSizing(true);
        // layer for event handling of GlazedLists and PropertyChanges
        GlazedListsEventLayer<T> glazedListsEventLayer = new GlazedListsEventLayer<T>(this.bodyDataLayer, filterList);
        this.bodyLayerStack = new BodyLayerStack(glazedListsEventLayer);
        this.bodyLabelAccumulator = new ColumnOverrideLabelAccumulator(bodyDataLayer);
        bodyDataLayer.setConfigLabelAccumulator(bodyLabelAccumulator);

        /*bodyLabelAccumulator.registerColumnOverrides(RowDataListFixture.getColumnIndexOfProperty(RowDataListFixture.PRICING_TYPE_PROP_NAME),
                        "PRICING_TYPE_PROP_NAME");*/

        // Body - with list event listener
        // NOTE: Remember to use the SortedList constructor with 'null' for the Comparator
        SortedList<T> sortedList = new SortedList<T>(rowObjectsGlazedList, null);
        this.bodyDataProvider = new ListDataProvider<T>(sortedList, columnPropertyAccessor);
        this.bodyDataLayer = new DataLayer(this.bodyDataProvider);
                
        // Column header layer
        this.columnHeaderLayerStack = new GlazedListsColumnHeaderLayerStack<T>(columnHeaderDataProvider, sortedList, columnPropertyAccessor,
                configRegistry, this.bodyLayerStack);
        this.columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);
        // Note: The column header layer is wrapped in a filter row composite.
        // This plugs in the filter row functionality
        FilterRowHeaderComposite<T> filterRowHeaderLayer = new FilterRowHeaderComposite<T>(
        		new DefaultGlazedListsFilterStrategy<T>(filterList, columnPropertyAccessor, configRegistry),
        		this.columnHeaderLayerStack.getColumnHeaderLayer(), columnHeaderDataProvider, configRegistry);
        
        // Row header
        DefaultRowHeaderDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(this.bodyDataProvider);
        DefaultRowHeaderDataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
        RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, this.bodyLayerStack, this.bodyLayerStack.getSelectionLayer());

        // Corner
        DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(this.columnHeaderLayerStack.getDataProvider(), rowHeaderDataProvider);
        DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);
        CornerLayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer, this.columnHeaderLayerStack);

        // Grid
        setBodyLayer(this.bodyLayerStack);
        setColumnHeaderLayer(this.columnHeaderLayerStack);
        setRowHeaderLayer(rowHeaderLayer);
        setCornerLayer(cornerLayer);
    }

    public ColumnOverrideLabelAccumulator getColumnLabelAccumulator() {
		return bodyLabelAccumulator;
    }

    @Override
    public void setClientAreaProvider(IClientAreaProvider clientAreaProvider) {
        super.setClientAreaProvider(clientAreaProvider);
    }

    public DataLayer getBodyDataLayer() {
        return this.bodyDataLayer;
    }

    public ListDataProvider<T> getBodyDataProvider() {
        return this.bodyDataProvider;
    }

    public GlazedListsColumnHeaderLayerStack<T> getColumnHeaderLayerStack() {
        return this.columnHeaderLayerStack;
    }

    public BodyLayerStack getBodyLayerStack() {
        return this.bodyLayerStack;
    }
    
    public EventList getEventList(){
		return eventList;
    }
    
    /**
     * Always encapsulate the body layer stack in an AbstractLayerTransform to
     * ensure that the index transformations are performed in later commands.
     *
     * @param <T>
     */
    class BodyLayerStack<T> extends AbstractLayerTransform {
    	private final SelectionLayer selectionLayer;
    	
        public BodyLayerStack(GlazedListsEventLayer<T> glazedListsEventLayer) {
            this.selectionLayer = new SelectionLayer(glazedListsEventLayer);
            ViewportLayer viewportLayer = new ViewportLayer(getSelectionLayer());

            setUnderlyingLayer(viewportLayer);
        }
        
        public SelectionLayer getSelectionLayer() {
            return this.selectionLayer;
        }
    }
}
Re: Some issues with layout and refresh after list data changed [message #1708159 is a reply to message #1708152] Mon, 14 September 2015 10:03 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2803
Registered: July 2012
Senior Member
Change

// Underlying data source
this.eventList = GlazedLists.eventList(new ArrayList<T>());
FilterList filterList = new FilterList(this.eventList);
this.rowObjectsGlazedList = GlazedLists.threadSafeList(filterList);
String[] propertyNames = {"prtno", "nomcl", "inidt", "prtky", "testts", "remark", "testdf", "testti"};
Map<String, String> propertyToLabelMap = RowDataListFixture.getPropertyToLabelMap();
        
// Body layer
IColumnPropertyAccessor<T> columnPropertyAccessor = new ReflectiveColumnPropertyAccessor<T>(propertyNames);
this.bodyDataProvider = new ListDataProvider<T>(filterList, columnPropertyAccessor);
this.bodyDataLayer = new DataLayer(this.bodyDataProvider);
bodyDataLayer.setColumnPercentageSizing(true);
// layer for event handling of GlazedLists and PropertyChanges
GlazedListsEventLayer<T> glazedListsEventLayer = new GlazedListsEventLayer<T>(this.bodyDataLayer, filterList);
this.bodyLayerStack = new BodyLayerStack(glazedListsEventLayer);
this.bodyLabelAccumulator = new ColumnOverrideLabelAccumulator(bodyDataLayer);
bodyDataLayer.setConfigLabelAccumulator(bodyLabelAccumulator);

/*bodyLabelAccumulator.registerColumnOverrides(RowDataListFixture.getColumnIndexOfProperty(RowDataListFixture.PRICING_TYPE_PROP_NAME),
                "PRICING_TYPE_PROP_NAME");*/

// Body - with list event listener
// NOTE: Remember to use the SortedList constructor with 'null' for the Comparator
SortedList<T> sortedList = new SortedList<T>(rowObjectsGlazedList, null);
this.bodyDataProvider = new ListDataProvider<T>(sortedList, columnPropertyAccessor);
this.bodyDataLayer = new DataLayer(this.bodyDataProvider);


To a correct stack like:

// Underlying data source
this.eventList = GlazedLists.eventList(new ArrayList<T>());
this.rowObjectsGlazedList = GlazedLists.threadSafeList(eventList );

// NOTE: Remember to use the SortedList constructor with 'null' for the Comparator
SortedList<T> sortedList = new SortedList<T>(rowObjectsGlazedList, null);
FilterList filterList = new FilterList(sortedList);

String[] propertyNames = {"prtno", "nomcl", "inidt", "prtky", "testts", "remark", "testdf", "testti"};
Map<String, String> propertyToLabelMap = RowDataListFixture.getPropertyToLabelMap();
        
// Body layer
IColumnPropertyAccessor<T> columnPropertyAccessor = new ReflectiveColumnPropertyAccessor<T>(propertyNames);
this.bodyDataProvider = new ListDataProvider<T>(filterList, columnPropertyAccessor);
this.bodyDataLayer = new DataLayer(this.bodyDataProvider);
bodyDataLayer.setColumnPercentageSizing(true);
// layer for event handling of GlazedLists and PropertyChanges
GlazedListsEventLayer<T> glazedListsEventLayer = new GlazedListsEventLayer<T>(this.bodyDataLayer, filterList);
this.bodyLayerStack = new BodyLayerStack(glazedListsEventLayer);

this.bodyLabelAccumulator = new ColumnOverrideLabelAccumulator(bodyDataLayer);
bodyDataLayer.setConfigLabelAccumulator(bodyLabelAccumulator);


and create the bodyDataLayer and the bodyDataProvider only once.

Maybe you should try to understand things instead of copy & paste code together from multiple sources you don't understand.

BTW, this is the same way it is shown in the integration examples of the Tutorials section. So if you would have copied the correct sources and not the examples I told you to not look at, you would not have these issues.
Re: Some issues with layout and refresh after list data changed [message #1708169 is a reply to message #1708159] Mon, 14 September 2015 10:51 Go to previous messageGo to next message
Mick Miralas is currently offline Mick MiralasFriend
Messages: 16
Registered: July 2015
Junior Member
Quote:
BTW, this is the same way it is shown in the integration examples of the Tutorials section. So if you would have copied the correct sources and not the examples I told you to not look at, you would not have these issues.


Mea culpa. I underestimated the complexity.

Thank you for your help and sorry to be the bringer of bad news, but after chaning my code accoridng to you last post, I still get errors (please see file attached). The new code is as follows:

/*******************************************************************************
 * Copyright (c) 2012, 2013 Original authors and others.
 * 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:
 *     Original authors and others - initial API and implementation
 ******************************************************************************/
package anwendungsservertest.view;

import java.util.ArrayList;
import java.util.Map;

import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
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.extension.glazedlists.GlazedListsEventLayer;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.filterrow.DefaultGlazedListsFilterStrategy;
import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowHeaderComposite;
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.DefaultRowHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
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.layer.AbstractLayerTransform;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.layer.cell.ColumnOverrideLabelAccumulator;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.util.IClientAreaProvider;
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;

import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.FilterList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.SortedList;
import ca.odell.glazedlists.TransformedList;

/**
 * Factory for assembling GridLayer and the child layers - with support for
 * GlazedLists and sorting
 *
 * @see {@linkplain http://publicobject.com/glazedlists/}
 */
public class GlazedListsGridLayer<T> extends GridLayer {
	
	private ListDataProvider<T> bodyDataProvider;
    private EventList eventList;
    private TransformedList rowObjectsGlazedList;

    private GlazedListsColumnHeaderLayerStack<T> columnHeaderLayerStack;
	private DataLayer bodyDataLayer;
	private BodyLayerStack bodyLayerStack;
	private ColumnOverrideLabelAccumulator bodyLabelAccumulator;
	private IDataProvider columnHeaderDataProvider;

    public GlazedListsGridLayer(IConfigRegistry configRegistry) {

        super(true);

        // Underlying data source
        this.eventList = GlazedLists.eventList(new ArrayList<T>());
        this.rowObjectsGlazedList = GlazedLists.threadSafeList(eventList);
        
        // NOTE: Remember to use the SortedList constructor with 'null' for the Comparator
        SortedList<T> sortedList = new SortedList<T>(rowObjectsGlazedList, null);
        FilterList filterList = new FilterList(sortedList);
        
        String[] propertyNames = {"prtno", "nomcl", "inidt", "prtky", "testts", "remark", "testdf", "testti"};
        Map<String, String> propertyToLabelMap = RowDataListFixture.getPropertyToLabelMap();
        
        // Body layer
        IColumnPropertyAccessor<T> columnPropertyAccessor = new ReflectiveColumnPropertyAccessor<T>(propertyNames);
        this.bodyDataProvider = new ListDataProvider<T>(filterList, columnPropertyAccessor);
        this.bodyDataLayer = new DataLayer(this.bodyDataProvider);
        bodyDataLayer.setColumnPercentageSizing(true);
        // layer for event handling of GlazedLists and PropertyChanges
        GlazedListsEventLayer<T> glazedListsEventLayer = new GlazedListsEventLayer<T>(this.bodyDataLayer, filterList);
        this.bodyLayerStack = new BodyLayerStack(glazedListsEventLayer);
        
        this.bodyLabelAccumulator = new ColumnOverrideLabelAccumulator(bodyDataLayer);
        bodyDataLayer.setConfigLabelAccumulator(bodyLabelAccumulator);

        /*bodyLabelAccumulator.registerColumnOverrides(RowDataListFixture.getColumnIndexOfProperty(RowDataListFixture.PRICING_TYPE_PROP_NAME),
                        "PRICING_TYPE_PROP_NAME");*/

        // Column header layer
        this.columnHeaderLayerStack = new GlazedListsColumnHeaderLayerStack<T>(columnHeaderDataProvider, sortedList, columnPropertyAccessor,
                configRegistry, this.bodyLayerStack);
        this.columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);
        // Note: The column header layer is wrapped in a filter row composite.
        // This plugs in the filter row functionality
        FilterRowHeaderComposite<T> filterRowHeaderLayer = new FilterRowHeaderComposite<T>(
        		new DefaultGlazedListsFilterStrategy<T>(filterList, columnPropertyAccessor, configRegistry),
        		this.columnHeaderLayerStack.getColumnHeaderLayer(), columnHeaderDataProvider, configRegistry);
        
        // Row header
        DefaultRowHeaderDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(this.bodyDataProvider);
        DefaultRowHeaderDataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
        RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, this.bodyLayerStack, this.bodyLayerStack.getSelectionLayer());

        // Corner
        DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(this.columnHeaderLayerStack.getDataProvider(), rowHeaderDataProvider);
        DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);
        CornerLayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer, this.columnHeaderLayerStack);

        // Grid
        setBodyLayer(this.bodyLayerStack);
        setColumnHeaderLayer(this.columnHeaderLayerStack);
        setRowHeaderLayer(rowHeaderLayer);
        setCornerLayer(cornerLayer);
    }

    public ColumnOverrideLabelAccumulator getColumnLabelAccumulator() {
		return bodyLabelAccumulator;
    }

    @Override
    public void setClientAreaProvider(IClientAreaProvider clientAreaProvider) {
        super.setClientAreaProvider(clientAreaProvider);
    }

    public DataLayer getBodyDataLayer() {
        return this.bodyDataLayer;
    }

    public ListDataProvider<T> getBodyDataProvider() {
        return this.bodyDataProvider;
    }

    public GlazedListsColumnHeaderLayerStack<T> getColumnHeaderLayerStack() {
        return this.columnHeaderLayerStack;
    }

    public BodyLayerStack getBodyLayerStack() {
        return this.bodyLayerStack;
    }
    
    public EventList getEventList(){
		return eventList;
    }
    
    /**
     * Always encapsulate the body layer stack in an AbstractLayerTransform to
     * ensure that the index transformations are performed in later commands.
     *
     * @param <T>
     */
    class BodyLayerStack<T> extends AbstractLayerTransform {
    	private final SelectionLayer selectionLayer;
    	
        public BodyLayerStack(GlazedListsEventLayer<T> glazedListsEventLayer) {
            this.selectionLayer = new SelectionLayer(glazedListsEventLayer);
            ViewportLayer viewportLayer = new ViewportLayer(getSelectionLayer());

            setUnderlyingLayer(viewportLayer);
        }
        
        public SelectionLayer getSelectionLayer() {
            return this.selectionLayer;
        }
    }
}
Re: Some issues with layout and refresh after list data changed [message #1708181 is a reply to message #1708169] Mon, 14 September 2015 12:11 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2803
Registered: July 2012
Senior Member
It is a NullPointerException. And it looks like it is because of your copy & paste operations. And you expect me to solve your problems that exist because you simply copied stuff without understanding. It is really annoying!

String[] propertyNames = {"prtno", "nomcl", "inidt", "prtky", "testts", "remark", "testdf", "testti"};
Map<String, String> propertyToLabelMap = RowDataListFixture.getPropertyToLabelMap();


Why do you use the RowDataListFixture from our examples or test data? I assume you didn't wrote your own and therefore it returns the wrong values.

And what is this?
this.columnHeaderLayerStack = new GlazedListsColumnHeaderLayerStack<T>(columnHeaderDataProvider, sortedList, columnPropertyAccessor, configRegistry, this.bodyLayerStack);
this.columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);


You are creating the column header layer stack with a not initialized columnHeaderDataProvider and expect everything works fine when you create it afterwards? A reference to null will never update to another reference if you specify the reference afterwards.

But a debugger would have told you the same!
Re: Some issues with layout and refresh after list data changed [message #1708287 is a reply to message #1708181] Tue, 15 September 2015 07:52 Go to previous messageGo to next message
Mick Miralas is currently offline Mick MiralasFriend
Messages: 16
Registered: July 2015
Junior Member
Hello Dirk,

finally I've managed it and now it works.
I totally understand your anger and I apologize most sincerely for the inconveniences. Beside a big thank you I just wanted to say that usually I solve problems by myself. At the moment there is a lot of pressure because of the dead line (the whole thesis was too complex for six months) and I now often don't see the forest for the trees.

So again: Sorry and thank you!

Regards,
Mick
Re: Some issues with layout and refresh after list data changed [message #1708394 is a reply to message #1708287] Wed, 16 September 2015 08:52 Go to previous messageGo to next message
Mick Miralas is currently offline Mick MiralasFriend
Messages: 16
Registered: July 2015
Junior Member
Hello Dirk,

unfortunately I need your help again.
While documenting the NatTable prototype, I noticed that when I want to filter the data and therefore click into the correspondent area (please see file attached), I can not type anything into it and clicking elsewhere in the table is no more possible.
Do you have any idea what's the reason for this?

/*******************************************************************************
* Copyright (c) 2012, 2013 Original authors and others.
* 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:
*     Original authors and others - initial API and implementation

******************************************************************************/

package anwendungsservertest.view;

import java.util.ArrayList;
import java.util.Map;

import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
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.extension.glazedlists.GlazedListsEventLayer;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.filterrow.DefaultGlazedListsFilterStrategy;
import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowHeaderComposite;
import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
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.DefaultRowHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
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.layer.AbstractLayerTransform;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.layer.cell.ColumnOverrideLabelAccumulator;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.util.IClientAreaProvider;
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;

import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.FilterList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.SortedList;
import ca.odell.glazedlists.TransformedList;

/**
* Factory for assembling GridLayer and the child layers - with support for
* GlazedLists and sorting
*
* @see {@linkplain http://publicobject.com/glazedlists/}
*/

public class GlazedListsGridLayer<T> extends GridLayer {

	private ListDataProvider<T> bodyDataProvider;
	private EventList eventList;
	private TransformedList rowObjectsGlazedList;

	private GlazedListsColumnHeaderLayerStack<T> columnHeaderLayerStack;
	private DataLayer bodyDataLayer;
	private BodyLayerStack bodyLayerStack;
	private ColumnOverrideLabelAccumulator bodyLabelAccumulator;
	private IDataProvider columnHeaderDataProvider;

	public GlazedListsGridLayer(IConfigRegistry configRegistry) {

		super(true);

		// Underlying data source
		this.eventList = GlazedLists.eventList(new ArrayList<T>());
		this.rowObjectsGlazedList = GlazedLists.threadSafeList(eventList);

		// NOTE: Remember to use the SortedList constructor with 'null' for the Comparator
		SortedList<T> sortedList = new SortedList<T>(rowObjectsGlazedList, null);
		FilterList filterList = new FilterList(sortedList);

		String[] propertyNames = {"prtno", "nomcl", "inidt", "prtky", "testts", "remark", "testdf", "testti"};
		Map<String, String> propertyToLabelMap = RowDataListFixture.getPropertyToLabelMap();

		// Body layer
		IColumnPropertyAccessor<T> columnPropertyAccessor = new ReflectiveColumnPropertyAccessor<T>(propertyNames);
		this.bodyDataProvider = new ListDataProvider<T>(filterList, columnPropertyAccessor);
		this.bodyDataLayer = new DataLayer(this.bodyDataProvider);
		bodyDataLayer.setColumnPercentageSizing(true);

		// layer for event handling of GlazedLists and PropertyChanges
		GlazedListsEventLayer<T> glazedListsEventLayer = new GlazedListsEventLayer<T>(this.bodyDataLayer, filterList);
		this.bodyLayerStack = new BodyLayerStack(glazedListsEventLayer); 
		this.bodyLabelAccumulator = new ColumnOverrideLabelAccumulator(bodyDataLayer);
		bodyDataLayer.setConfigLabelAccumulator(bodyLabelAccumulator);

		/*bodyLabelAccumulator.registerColumnOverrides(RowDataListFixture.getColumnIndexOfProperty(RowDataListFixture.PRICING_TYPE_PROP_NAME),

                        "PRICING_TYPE_PROP_NAME");*/

		// Column header layer
		this.columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);
		this.columnHeaderLayerStack = new GlazedListsColumnHeaderLayerStack<T>(columnHeaderDataProvider, sortedList, columnPropertyAccessor,
                configRegistry, this.bodyLayerStack);

		// Note: The column header layer is wrapped in a filter row composite.
		// This plugs in the filter row functionality
		FilterRowHeaderComposite<T> filterRowHeaderLayer = new FilterRowHeaderComposite<T>(
			new DefaultGlazedListsFilterStrategy<T>(filterList, columnPropertyAccessor, configRegistry), 
			this.columnHeaderLayerStack.getColumnHeaderLayer(), columnHeaderDataProvider, configRegistry);

		filterRowHeaderLayer.setChildLayer(GridRegion.COLUMN_HEADER, this.columnHeaderLayerStack, 0, 0);

		// Row header
		DefaultRowHeaderDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(this.bodyDataProvider);
		DefaultRowHeaderDataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
		RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, this.bodyLayerStack, this.bodyLayerStack.getSelectionLayer());

		// Corner
		DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(this.columnHeaderLayerStack.getDataProvider(), rowHeaderDataProvider);
		DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);
		CornerLayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer, this.columnHeaderLayerStack);

		// Grid
		setBodyLayer(this.bodyLayerStack);
		setColumnHeaderLayer(filterRowHeaderLayer);
		setRowHeaderLayer(rowHeaderLayer);
		setCornerLayer(cornerLayer);
	}

	public ColumnOverrideLabelAccumulator getColumnLabelAccumulator() {
		return bodyLabelAccumulator;
	}

	@Override
	public void setClientAreaProvider(IClientAreaProvider clientAreaProvider) {
		super.setClientAreaProvider(clientAreaProvider);
	}

	public DataLayer getBodyDataLayer() {
		return this.bodyDataLayer;
	}

	public ListDataProvider<T> getBodyDataProvider() {
		return this.bodyDataProvider;
	}

	public GlazedListsColumnHeaderLayerStack<T> getColumnHeaderLayerStack() {
		return this.columnHeaderLayerStack;
	}

	public BodyLayerStack getBodyLayerStack() {
		return this.bodyLayerStack;
	}

	public EventList getEventList(){
		return eventList;
	}

    /**
     * Always encapsulate the body layer stack in an AbstractLayerTransform to
     * ensure that the index transformations are performed in later commands.
     *
     * @param <T>
     */
	class BodyLayerStack<T> extends AbstractLayerTransform {
		private final SelectionLayer selectionLayer;

		public BodyLayerStack(GlazedListsEventLayer<T> glazedListsEventLayer) {
			this.selectionLayer = new SelectionLayer(glazedListsEventLayer);
			ViewportLayer viewportLayer = new ViewportLayer(getSelectionLayer());
		setUnderlyingLayer(viewportLayer);
		}

		public SelectionLayer getSelectionLayer() {
			return this.selectionLayer;
		}
	}
}
  • Attachment: freeze.PNG
    (Size: 43.82KB, Downloaded 141 times)
Re: Some issues with layout and refresh after list data changed [message #1708406 is a reply to message #1708394] Wed, 16 September 2015 10:35 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2803
Registered: July 2012
Senior Member
I assume there is some exception raised. What kind of exception and what is causing it I can't tell. Maybe some issue with the filter row configuration.
Re: Some issues with layout and refresh after list data changed [message #1708620 is a reply to message #1708406] Fri, 18 September 2015 07:41 Go to previous messageGo to next message
Mick Miralas is currently offline Mick MiralasFriend
Messages: 16
Registered: July 2015
Junior Member
Unfortunately, there is no error message shown. Only the following message appears, when I try to click outside the focused filter cell:

Quote:

log4j:WARN No appenders could be found for logger (org.eclipse.nebula.widgets.nattable.edit.command.UpdateDataCommandHandler).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.


Concerning filter row configuration:

public static class FilterRowCustomConfiguration extends AbstractRegistryConfiguration {
	// final DefaultDoubleDisplayConverter doubleDisplayConverter = new DefaultDoubleDisplayConverter();
	@Override
	public void configureRegistry(IConfigRegistry configRegistry) {
		// override the default filter row configuration for painter
		configRegistry.registerConfigAttribute(CELL_PAINTER, new FilterRowPainter(new FilterIconPainter(GUIHelper.getImage("filter"))), NORMAL, FILTER_ROW);
	}
}

Re: Some issues with layout and refresh after list data changed [message #1708624 is a reply to message #1708620] Fri, 18 September 2015 08:11 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2803
Registered: July 2012
Senior Member
First, you don't have a proper logging configuration. Second, there is an issue with committing the filter value, but without an error message I can't help.

Debug in org.eclipse.nebula.widgets.nattable.edit.command.UpdateDataCommandHandler to see what error occurs.
Re: Some issues with layout and refresh after list data changed [message #1708630 is a reply to message #1708624] Fri, 18 September 2015 08:42 Go to previous messageGo to next message
Mick Miralas is currently offline Mick MiralasFriend
Messages: 16
Registered: July 2015
Junior Member
Please see attached file.
The same error occours even when I type something into the filter cell.
  • Attachment: error.txt
    (Size: 22.70KB, Downloaded 110 times)
Re: Some issues with layout and refresh after list data changed [message #1708636 is a reply to message #1708630] Fri, 18 September 2015 09:04 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2803
Registered: July 2012
Senior Member
It says you are trying to set a value to the column header data provider, which is not supported. So there is something wrong with your composition as the FilterRowDataProvider should be used by the UpdateDataCommand.. But I don't see what easily and I don't have the time

Why did you add this line of code. I don't see this in any of our examples.

filterRowHeaderLayer.setChildLayer(GridRegion.COLUMN_HEADER, this.columnHeaderLayerStack, 0, 0);

Re: Some issues with layout and refresh after list data changed [message #1708650 is a reply to message #1708636] Fri, 18 September 2015 12:00 Go to previous message
Mick Miralas is currently offline Mick MiralasFriend
Messages: 16
Registered: July 2015
Junior Member
Now it (really) works!
I had a look into FullFeaturedColumnHeaderLayerStack.java and got the necessary "inspiration". Honestly, I don't know what exactly was responsible for the issues, but i moved the instantiation of filterRowHeaderComposite to my adapted class GlazedListsColumnHeaderLayerStack, plus changed the argument of setUnderlyingLayer to filterRowHeaderLayer and now it works.

So thanks again for the great and quick support. Now I solely have to finish the documentation of the NatTable prototype. The result of my work is a recommendation for RCP, since there is a lot of open source stuff for it. If you look at C#/WPF, the native possibilities are limited and you have to pay a lot of money, for example if you want a more sophisticated table widget. Additionally, RCP can be seen as platform independent and it should be fit for the future. Whereas a .NET solution based on WPF leads to a dependence on Windows (yes, there are some projects out there that focus on transformation of C#/WPF to HTML5/JavaScript) and Microsoft could stop the support of WPF in a few years.
Previous Topic:Clear All records in nattable and reload others
Next Topic:Dynamic Filter in NatTable
Goto Forum:
  


Current Time: Sat Feb 27 10:30:16 GMT 2021

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

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

Back to the top