Skip to main content

JXTreeTable highlighter problem

Please note these java.net forums are being decommissioned and use the new and improved forums at https://community.oracle.com/community/java.
1 reply [Last post]
luppy
Offline
Joined: 2008-05-01

I have a JXTreeTable which has a highlighter which alternates the colours of the row. I have a custom rendering component which has 2 labels one for an icon on the left of the cell and another label for text on the right of the cell.
The highlighting works ok until I add another highlighter which is where I want the logic to set the icons based on whether that row is highlighted or not. When I add this highlighter to a specific column that column seems to ignore the original colour highlighter.
Could anyone point out if I am doing something wrong or if it is a bug?
I have attached an example below (I can't seem to get it to format nicely so here's a link to a better formatted version www.oneandonlyluppy.pwp.blueyonder.co.uk/HighlighterIssueProblem.java
Thanks

import org.jdesktop.swingx.JXFrame;
import org.jdesktop.swingx.JXPanel;
import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.decorator.AbstractHighlighter;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.decorator.HighlightPredicate;
import org.jdesktop.swingx.renderer.CellContext;
import org.jdesktop.swingx.renderer.ComponentProvider;
import org.jdesktop.swingx.renderer.DefaultTableRenderer;
import org.jdesktop.swingx.renderer.JRendererLabel;
import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode;
import org.jdesktop.swingx.treetable.DefaultTreeTableModel;

import javax.swing.*;
import javax.swing.tree.TreePath;
import java.awt.*;

public class HighlighterIssueProblem extends JXFrame
{
    private final JXTreeTable table;

    public HighlighterIssueProblem()
    {
        MyRow root = new MyRow(false, "root");

        // Create some rows that alternate colour
        MyRow previous = root;
        for (int i = 0; i < 5; i++)
        {
            boolean highlighted = i % 2 == 0;
            String text = (highlighted) ? "Highlighted" : "Not-Highlighted";
            MyRow myRow = new MyRow(highlighted, text);
            previous.add(myRow);
            previous = myRow;
        }

        MyTreeTableModel model = new MyTreeTableModel();
        model.setRoot(root);

        // Color Highlighter
        MyHighlightPredicate highlightPredicate = new MyHighlightPredicate();
        ColorHighlighter colorHighlighter = new ColorHighlighter(highlightPredicate, Color.GREEN, null);

        table = new JXTreeTable(model);
        table.addHighlighter(new DynamicIconHighlighter());
        table.addHighlighter(colorHighlighter);

        // Render column 1 slightly differently
        table.getColumn(1).setCellRenderer(new DefaultTableRenderer(new DualLabelComponentProvider()));
        table.expandAll();

        setLayout(new BorderLayout());
        add(new JScrollPane(table), BorderLayout.CENTER);

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(600, 600);
        setVisible(true);
    }

    private MyRow getNodeForRow(int rowViewIndex)
    {
        TreePath path = table.getPathForRow(rowViewIndex);
        MyRow row = (MyRow) path.getLastPathComponent();
        return row;
    }

    /** Provide a custom component to the highlighter */
    private class DualLabelComponentProvider extends ComponentProvider<DualLabelComponent>
    {
        protected void format(CellContext context)
        {
            rendererComponent.setText(getValueAsString(context));
        }

        protected void configureState(CellContext context)
        {
        }

        protected DualLabelComponent createRendererComponent()
        {
            return new DualLabelComponent();
        }
    }

    /** A highter which would set the icon and text */
    private class DynamicIconHighlighter extends AbstractHighlighter
    {
        private final Icon infoIcon = UIManager.getIcon("OptionPane.informationIcon");
        private final Icon errorIcon = UIManager.getIcon("OptionPane.errorIcon");

        protected Component doHighlight(Component component, ComponentAdapter adapter)
        {
            if (component instanceof DualLabelComponent)
            {
                DualLabelComponent dualLabelComponent = (DualLabelComponent) component;

                MyRow myRow = getNodeForRow(adapter.row);
                boolean highlighted = myRow.isHighlighted();
                Icon icon = (highlighted) ? infoIcon : errorIcon;
                dualLabelComponent.setIcon(icon);
            }
            return component;
        }
    }

    private class DualLabelComponent extends JXPanel
    {
        private JRendererLabel leftLabel, rightLabel;

        private DualLabelComponent()
        {
            leftLabel = new JRendererLabel();
            leftLabel.setOpaque(false);
            rightLabel = new JRendererLabel();
            rightLabel.setOpaque(false);

            setLayout(new BorderLayout());
            add(leftLabel, BorderLayout.WEST);
            add(rightLabel, BorderLayout.EAST);
        }

        public void setIcon(Icon icon)
        {
            leftLabel.setIcon(icon);
        }

        public void setText(String text)
        {
            rightLabel.setText(text);
        }
    }

    private class MyHighlightPredicate implements HighlightPredicate
    {
        public boolean isHighlighted(Component renderer, ComponentAdapter adapter)
        {
            int rowIndex = adapter.row;
            MyRow row = getNodeForRow(rowIndex);
            boolean isHighlighted = row.isHighlighted();
            return isHighlighted;
        }
    }

    private class MyTreeTableModel extends DefaultTreeTableModel
    {
        @Override
        public int getColumnCount()
        {
            return 3;
        }

        @Override
        public Object getValueAt(Object node, int column)
        {
            MyRow myRow = (MyRow) node;
            return myRow.getText();
        }
    }

    private class MyRow extends DefaultMutableTreeTableNode
    {
        private boolean highlight;
        private String text;

        private MyRow(boolean highlight, String text)
        {
            this.highlight = highlight;
            this.text = text;
        }

        public boolean isHighlighted()
        {
            return highlight;
        }

        public String getText()
        {
            return text;
        }
    }

    public static void main(String[] args)
    {
        new HighlighterIssueProblem();
    }
}
 

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
luppy
Offline
Joined: 2008-05-01

Solved, the color highlighter was using the predicate to color the rows so rows 1, 3, 5 were not re-rendered.