Change SWT tree node text foreground when highlighted
Asked Answered
S

2

6

I’m pretty new in SWT/JFace technology and I’ve found a problem that it’s driving me crazy. In an Eclipse RCP application I have a view where I’ve placed a SWT tree with a JFace TreeViewer which provides the labels and the icons by means of a label provider. By requirements of the customer the background colour of the tree is dark blue and the font colour is white. This combination of colours results in a bad visualization of a node’s text when the node is selected, the text does not fit the tree region and we place the mouse pointer over the node. Somehow a “native highlighting” appears. This can be shown in the following image.

enter image description here

On the other side, this problem does not happen when the node where we place the mouse over is not selected. The highlighting changes the colour of the font to make it more visible. This can be shown in the following image.

enter image description here

After doing some research I’ve found that by adding a listener for the SWT.EraseItem event I am able to modify the background’s colour of a selected node and then disable the selection. This allows me to define my own selection background style and also disable the SWT.SELECTED flag of the event.detail in order to force the OS to highlight as the node is not selected.

private final class EraseItemListener implements Listener {

    public void handleEvent(Event event) {
        // Only perform the node highlight when it is selected.
        if ((event.detail & SWT.SELECTED) == SWT.SELECTED) {
            // Modify background, emulate Windows highlighting.

            ...

            // Set Windows that we do not want to draw this item as a selection (we have already highlighted the item in our way).
            event.detail &= ~SWT.SELECTED;
        }
    }
}

This “solution” can be reasonable. The main drawbacks I see is that my selection style only fits for the Windows 7 default visual themes. For those “Windows classic” or “High contrast” I’ll get visualization problems. Moreover (and this is the most annoying issue), the fact of adding a listener for the SWT.EraseItem (even without code to handle the event) produces two new problems.

  1. This makes either SWT or JFace to draw the icon of the tree node in the wrong place as you can see in the following image.

    enter image description here

  2. The highlight of the tree’s root node is completely wrong. As you can see in the following image, the node seems to be highlighted in 2 different ways and the icon is repeated.

    enter image description here

My questions are basically two.

  1. Do you think there is an easier solution for the main problem? What I would like is to show a selected node (the one of the first image) in the same way as in the second image. I would like to change the foreground colour of the selected node to make it more visible.

  2. In case of using the SWT.EraseItem approach, is there any way of showing the icons in the correct location? Is this behaviour a known bug?

Thanks in advance.

Shod answered 22/1, 2014 at 9:9 Comment(1)
Very well written question! Unfortunately, I have no idea how to solve your question. Looking forward to some good answers here.Elsa
S
2

If you use a label provider based on StyledCellLabelProvider (perhaps one based on DelegatingStyledCellLabelProvider) you can specify COLORS_ON_SELECTION to retain normal colors on selection.

If that is not good enough (don't have Windows here to test) you can override the paint method - again you can try using event.detail &= ~SWT.SELECTED to suppress the normal selection handling or even handle the paint yourself.

Slovenia answered 22/1, 2014 at 10:4 Comment(1)
Thanks for the answer and sorry for the late response. The first testings I've done with your recommendation are not successful. The only improvement is that the icon seems to appear in the correct place, nevertheless the native highlighting of Windows 7 still appears (by leaving the white font) even when I disable the selection by event.detail &= ~SWT.SELECTED.Affectional
A
0

Just stumbled across this old post and realized it matches a bug that I opened recently on eclipse.

My workaround to have the text in the correct color was to paint over the text with a different color using a PaintListener (registered in the tree with SWT.PaintItem):

private static class TreePaintListener implements Listener {
    @Override
    public void handleEvent(Event event) {
        boolean isSelected = (event.detail & SWT.SELECTED) != 0;
        if (isSelected && event.item instanceof TreeItem) {         
            TreeItem treeItem = (TreeItem) event.item;
            Tree parent = treeItem.getParent();


            GC gc = event.gc;
            Color foreground = null/* Some Color */;
            gc.setForeground(foreground);

            Rectangle imageBounds = treeItem.getImageBounds(0);
            Rectangle textBounds = treeItem.getTextBounds(0);
            Point stringExtent = gc.stringExtent(treeItem.getText());

            int offsetX = imageBounds.width != 0 ? imageBounds.height - imageBounds.width : 0;
            int offsetY = (textBounds.height - stringExtent.y) / 2;

            int x = textBounds.x + offsetX;
            int y = textBounds.y + offsetY;

            if (gc.getClipping().contains(x, y)) {
                gc.drawString(treeItem.getText(), x, y);
            }
        }
    }
}

But it still misbehaves when there are multiple columns defined (only the first one is painted over), and depending on the operating system and DPI the calculations might be a bit off.

Aphid answered 31/5, 2019 at 8:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.