Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » NatTable » Cell Image Painter taking too long(Taking too long to paint cells with image renderer. Continually comes into cell accumulator over and over.)
Cell Image Painter taking too long [message #1444982] Tue, 14 October 2014 21:21 Go to next message
Eclipse UserFriend
I have NatTable that is using ColumnGroupHeaderLayer. For each Column Group there are 2 columns, one that paints image1 and the other paints image2. I have a CellOverrideLabelAccumulator that checks the cell and adds a label, either LABEL1 for image1 or LABEL2 for image2. Then 2 image renderers, one for each image. But it is extremely slow to display a simple grid that has 13 rows and 6 columns. I put a println() statement in the CellOverrideLabelAccumulator and it enters this method numerous times, repeated for the same cell 2 or 3 times. If I scroll the natTable, it seems to be in an endless loop through the cell accumulator. What is causing this? Any suggestions as to how to make it stop?
Thanks for your help in advance,
-francine

Here is the code:
    public static NatTable createObjectPrivilegeNatTable(
            Composite parent,
            Map<String, Image> imageMap,
            ObjectPrivilegesNTComposite objectPrivilegeComp,
            Map<String, Map<String, PrivilegeGrantedState>> globalPrivilegesStateMap,
            AsterGrantee displayGrantee,
            Map<String, List<Privilege>> privilegeMap,
            IStateMapCallback stateMapCallback) {

        final ColumnGroupModel columnGroupModel = new ColumnGroupModel();
        PrivilegeObjectDataProvider bodyDataProvider = new PrivilegeObjectDataProvider(
                objectPrivilegeComp, privilegeMap);
        DataLayer dataLayer = new DataLayer(bodyDataProvider);
        ColumnGroupBodyLayerStack bodyLayer = new ColumnGroupBodyLayerStack(
                dataLayer, columnGroupModel);

        // Column header
        ColumnObjectHeaderDataModel defaultColumnHeaderDataProvider = new ColumnObjectHeaderDataModel(
                privilegeMap, displayGrantee,
                objectPrivilegeComp.getTypeSelected());
        DefaultColumnHeaderDataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(
                defaultColumnHeaderDataProvider);
        ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(
                columnHeaderDataLayer, bodyLayer, bodyLayer.getSelectionLayer());
        ColumnGroupHeaderLayer columnGroupHeaderLayer = new ColumnGroupHeaderLayer(
                columnHeaderLayer, bodyLayer.getSelectionLayer(),
                columnGroupModel);

        addIndexesToObjectGroup(columnGroupHeaderLayer, privilegeMap,
                columnGroupModel, objectPrivilegeComp.getTypeSelected(),
                displayGrantee);

        // Row header
        RowHeaderDataModel rowHeaderDataProvider = new RowHeaderDataModel(
                new ArrayList<String>(privilegeMap.keySet()));
        DefaultRowHeaderDataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(
                rowHeaderDataProvider);
        ILayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer,
                bodyLayer, bodyLayer.getSelectionLayer());

        // Corner
        CornerObjectDataModel cornerDataProvider = new CornerObjectDataModel(
                defaultColumnHeaderDataProvider, rowHeaderDataProvider);
        DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);
        ILayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer,
                columnGroupHeaderLayer);

        // Grid
        GridLayer gridLayer = new GridLayer(bodyLayer, columnGroupHeaderLayer,
                rowHeaderLayer, cornerLayer);

        NatTable natTable = new NatTable(parent, SWT.DOUBLE_BUFFERED | SWT.H_SCROLL
                | SWT.V_SCROLL, gridLayer, false);

        // Register column chooser
        DisplayColumnChooserCommandHandler columnChooserCommandHandler = new DisplayColumnChooserCommandHandler(
                bodyLayer.getSelectionLayer(),
                bodyLayer.getColumnHideShowLayer(), columnHeaderLayer,
                columnHeaderDataLayer, columnGroupHeaderLayer, columnGroupModel);
        bodyLayer.registerCommandHandler(columnChooserCommandHandler);

        natTable.addConfiguration(new DefaultNatTableStyleConfiguration());

        Style style = new Style();
        style.setAttributeValue(CellStyleAttributes.VERTICAL_ALIGNMENT,
                VerticalAlignmentEnum.MIDDLE);
        style.setAttributeValue(CellStyleAttributes.HORIZONTAL_ALIGNMENT,
                HorizontalAlignmentEnum.CENTER);
        IConfigRegistry configRegistry = new ConfigRegistry();
        configRegistry.registerConfigAttribute(CellConfigAttributes.CELL_STYLE,
                style, DisplayMode.NORMAL);

        natTable.setConfigRegistry(configRegistry);
        natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
        registerObjectPrivilegeImageRenderers(dataLayer, gridLayer, natTable,
                imageMap, globalPrivilegesStateMap, objectPrivilegeComp);
        setUpInitialSizeCommand(natTable, dataLayer);
        addCustomStyling(natTable);
        setUpDefaultObjectActionHandlers(natTable, gridLayer, bodyLayer,
                dataLayer, globalPrivilegesStateMap, stateMapCallback,
                objectPrivilegeComp);

        natTable.configure();
        return natTable;


Here is the registerObjectPrivilegeImageRenderers:
    public static void registerObjectPrivilegeImageRenderers(
            DataLayer bodyDataLayer,
            final GridLayer gridLayer,
            NatTable natTable,
            Map<String, Image> images,
            final Map<String, Map<String, PrivilegeGrantedState>> globalPrivilegesStateMap,
            final ObjectPrivilegesNTComposite objectPrivilegeNT) {

        final IDataProvider dataProvider = bodyDataLayer.getDataProvider();
        IRowDataProvider<Privilege> provider = new IRowDataProvider<Privilege>() {
            @Override
            public Object getDataValue(int columnIndex, int rowIndex) {

                Object value = dataProvider.getDataValue(columnIndex, rowIndex);
                if (value instanceof Privilege) {
                    return value;
                } else {
                    return null;
                }
            }

            @Override
            public void setDataValue(int columnIndex, int rowIndex,
                    Object newValue) {
                // do nothing!
            }

            @Override
            public int getColumnCount() {
                return dataProvider.getColumnCount();
            }

            @Override
            public int getRowCount() {
                return dataProvider.getRowCount();
            }

            @Override
            public Privilege getRowObject(int rowIndex) {
                return null;
            }

            @Override
            public int indexOfRowObject(Privilege rowObject) {
                 return -1;
            }
        };

        CellOverrideLabelAccumulator<Privilege> privilegeLabelAccumulator = new CellOverrideLabelAccumulator<Privilege>(
                provider) {
            public void accumulateConfigLabels(LabelStack configLabels,
                    int columnPosition, int rowPosition) {
                Object val = dataProvider.getDataValue(columnPosition,
                        rowPosition);
                System.out.println("enter accumulate: Col/Row = "
                        + columnPosition + "/" + rowPosition + " labels: " + configLabels.getLabels());
                if (val instanceof Privilege) {
                    Map<String, List<Privilege>> privilegeMap = objectPrivilegeNT
                            .getObjectMap(objectPrivilegeNT.getTypeSelected());
                    // determine which label to add
                    if (doImageOne()) {
                        configLabels.addLabel(WITH_IMAGE_CELL_LABEL);
                    } else {
                        configLabels.addLabel(IMAGE_CELL_LABEL);
                    }
                }
            }

        };
        bodyDataLayer.setConfigLabelAccumulator(privilegeLabelAccumulator);
        
        createObjectImageRenderer(gridLayer, natTable, images,
                globalPrivilegesStateMap, objectPrivilegeNT);
        createObjectImageWithRenderer(gridLayer, natTable, images,
                globalPrivilegesStateMap, objectPrivilegeNT);
    }


Here is the ImageRenderer. There is a similar one for createObjectImageWithRenderer:
    private static void createObjectImageRenderer(
            final GridLayer gridLayer,
            final NatTable natTable,
            final Map<String, Image> images,
            final Map<String, Map<String, PrivilegeGrantedState>> globalPrivilegesStateMap,
            final ObjectPrivilegesNTComposite objectPrivilegeNT) {
        ImagePainter imagePainter = new ImagePainter() {

            @Override
            protected Image getImage(ILayerCell cell,
                    IConfigRegistry configRegistry) {
                int row = cell.getRowPosition();
                int col = cell.getColumnPosition();

                System.out.println("getImage, Row/Col = " + row + "/" + col);
                
                Object obj = gridLayer.getDataValueByPosition(col, row);
                if (obj instanceof Privilege) {
                        return cellImage1;
                } else {
                    return null;
                }
            }

            @Override
            public int getPreferredWidth(ILayerCell cell, GC gc,
                    IConfigRegistry configRegistry) {
                Image image = getImage(cell, configRegistry);
                if (image != null) {
                    return Math.min(image.getBounds().width + BUFFER,
                            MAX_PREFERRED_IMAGE_WIDTH);
                } else {
                    return super.getPreferredWidth(cell, gc, configRegistry);
                }
            }

            @Override
            public int getPreferredHeight(ILayerCell cell, GC gc,
                    IConfigRegistry configRegistry) {
                Image image = getImage(cell, configRegistry);
                if (image != null) {
                    return Math.min(image.getBounds().height + BUFFER,
                            MAX_PREFERRED_IMAGE_HEIGHT);
                } else {
                    return super.getPreferredHeight(cell, gc, configRegistry);
                }
            }
        };

        IConfigRegistry configRegistry = natTable.getConfigRegistry();

        configRegistry.registerConfigAttribute(
                CellConfigAttributes.CELL_PAINTER, imagePainter,
                DisplayMode.NORMAL, IMAGE_CELL_LABEL);
        configRegistry.registerConfigAttribute(
                CellConfigAttributes.CELL_PAINTER, imagePainter,
                DisplayMode.SELECT, IMAGE_CELL_LABEL);

    }
         

Re: Cell Image Painter taking too long [message #1445221 is a reply to message #1444982] Wed, 15 October 2014 06:18 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2902
Registered: July 2012
Senior Member
Hi Francine,

there are several things you are doing wrong that might cause the issue. Maybe you should start reading the spare documentation first.

https://www.eclipse.org/nattable/documentation.php?page=styling
https://www.eclipse.org/nattable/documentation.php?page=articles

I know that it is not much, but I'm working on that.

So let's start:
natTable.addConfiguration(new DefaultNatTableStyleConfiguration());

Style style = new Style();
style.setAttributeValue(CellStyleAttributes.VERTICAL_ALIGNMENT, VerticalAlignmentEnum.MIDDLE);
style.setAttributeValue(CellStyleAttributes.HORIZONTAL_ALIGNMENT, HorizontalAlignmentEnum.CENTER);
IConfigRegistry configRegistry = new ConfigRegistry();
configRegistry.registerConfigAttribute(CellConfigAttributes.CELL_STYLE, style, DisplayMode.NORMAL);

natTable.setConfigRegistry(configRegistry);


If you want to register a custom styling you should go on creating a new AbstractRegistryConfiguration or extend DefaultNatTableStyleConfiguration. Writing directly in the ConfigRegistry should be avoided if you don't know what you are doing.

You are registering a CellOverrideLabelAccumulator to the bodyDataLayer, but you are saying that you want to show images in the column header based on the lables that accumulator adds. But how should those labels get into the column header if they are applied to the body? That is also why the accumulator is called numerous times, for each cell in the body. But that shouldn't be an issue in general as this is the way it works in several compositions.

And what is the reason for overriding the ImagePainter with custom code? And also, why are you doing a check for the data in the ImagePainter to determine the image to show? You already registered labels, so you should create another ImagePainter and attach it to the label instead of doing your own logic again in the ImagePainter. ImagePainter has a constructor that takes the image as parameter or you can register a style that points to an image if only the image changes and you always want to show an image. That is personal flavour.

So in short:
- register your labels to the column header data layer and not the body if you want to style the column header
- create an AbstractConfigRegistry and register your styles (alignment and different image painters for your labels)
- delete createObjectImageRenderer() as it makes no sense

Greez,
Dirk
Re: Cell Image Painter taking too long [message #1445800 is a reply to message #1445221] Thu, 16 October 2014 00:13 Go to previous messageGo to next message
Eclipse UserFriend
Thanks for your response. The image is changed depending on the cell data. That is why I passed the bodyDataLayer into the registerObjectPrivilegeImageRenderers. I want to show images in the cells, not the column labels. I set the configLabelAccumulator to the bodyDataLayer.
bodyDataLayer.setConfigLabelAccumulator(privilegeLabelAccumulator);


I am not sure where it determines to" show images in the column header based on the labels that accumulator adds"?
Re: Cell Image Painter taking too long [message #1445976 is a reply to message #1445800] Thu, 16 October 2014 07:02 Go to previous message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2902
Registered: July 2012
Senior Member
You started your question with

Quote:
I have NatTable that is using ColumnGroupHeaderLayer. For each Column Group there are 2 columns, one that paints image1 and the other paints image2


so I assumed you are talking about the column header.

Quote:
The image is changed depending on the cell data. That is why I passed the bodyDataLayer into the registerObjectPrivilegeImageRenderers.


In such cases you should register labels for the content of the cell. But it looks like you are doing that already, since in both cases, label accumulator and image painter, you do an instanceof check.
Then register a style that contains the image to render. This way you achieve separation of styling and content via labels. Only the accumulator should know about data, not the painter. The painter should only render the data passed.

The painter
Previous Topic:Export Natable Grid to Excel.
Next Topic:Exception during dispose in GlazedListsEventLayer
Goto Forum:
  


Current Time: Fri Apr 26 05:24:47 GMT 2024

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

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

Back to the top