Community
Participate
Working Groups
If I'd like to add custom paint listener to my tree and than remove it, sometimes all text disappear. Actually, the problem is text foreground == white after removing paint listener. Looks like the problem with Tree.drawForeground field: while custom rendering appear, Tree could cache this variable and then use invalid value when there are no custom painters (drawForeground value doesn't clear). Following example reproduce my problem. You need to select the last one item in the tree, check "Enable custom painter" and then uncheck it -- all text will be white: import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.TextLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; public class TreePainter implements Listener { private Tree tree; private TextLayout textLayout; TreePainter(Tree tree) { this.tree = tree; } public void setListeners(boolean add) { if (add) { tree.addListener(SWT.EraseItem, this); tree.addListener(SWT.PaintItem, this); } else { tree.removeListener(SWT.EraseItem, this); tree.removeListener(SWT.PaintItem, this); } redraw(); } @Override public void handleEvent(Event event) { switch (event.type) { case SWT.PaintItem: paint(event); break; case SWT.EraseItem: erase(event); break; } } private void erase(Event event) { event.detail &= ~(SWT.BACKGROUND | SWT.FOREGROUND | SWT.SELECTED | SWT.HOT); } private void paint(Event event) { TreeItem item = (TreeItem) event.item; GC gc = event.gc; // remember colors to restore the GC later Color oldForeground = gc.getForeground(); Color oldBackground = gc.getBackground(); int index = event.index; Color foreground = item.getForeground(index); if (foreground != null) { gc.setForeground(foreground); } Color background = item.getBackground(index); if (background != null) { gc.setBackground(background); } if ((event.detail & SWT.SELECTED) != 0) { gc.fillRectangle(item.getBounds(index)); } Image image = item.getImage(index); if (image != null) { Rectangle imageBounds = item.getImageBounds(index); if (imageBounds != null) { Rectangle bounds = image.getBounds(); // center the image in the given space int x = imageBounds.x + Math.max(0, (imageBounds.width - bounds.width) / 2); int y = imageBounds.y + Math.max(0, (imageBounds.height - bounds.height) / 2); gc.drawImage(image, x, y); } } Rectangle textBounds = item.getTextBounds(index); if (textBounds != null) { TextLayout layout = getTextLayout(); layout.setText(item.getText(index)); layout.setFont(item.getFont(index)); Rectangle layoutBounds = layout.getBounds(); int x = textBounds.x; int avg = (textBounds.height - layoutBounds.height) / 2; int y = textBounds.y + Math.max(0, avg); layout.draw(gc, x, y); } gc.setForeground(oldForeground); gc.setBackground(oldBackground); } public void redraw() { Rectangle rect = tree.getClientArea(); tree.redraw(rect.x, rect.y, rect.width, rect.height, true); } private TextLayout getTextLayout() { if (textLayout == null) { int orientation = tree.getStyle() & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT); textLayout = new TextLayout(tree.getDisplay()); textLayout.setOrientation(orientation); } else { textLayout.setText(""); } return textLayout; } public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setBounds(10, 10, 800, 600); shell.setLayout(new GridLayout()); final Tree tree = new Tree(shell, SWT.BORDER); tree.setLinesVisible(true); for (int i = 0; i < 5; i++) { TreeItem item = new TreeItem(tree, SWT.NONE); item.setText("item " + i); for (int j = 0; j < 5; j++) { TreeItem child = new TreeItem(item, SWT.NONE); child.setText("item " + i + "-" + j); } } tree.setLayoutData(new GridData(GridData.FILL_BOTH)); final TreePainter painer = new TreePainter(tree); final Button button = new Button(shell, SWT.CHECK); button.setText("Enable custom painter"); button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { painer.setListeners(button.getSelection()); } }); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } }
which GTK version you are using ? I am not able to reproduce the problem on Ubuntu 9.04 (using GTK 2.16) - the text appears correctly after enabling/disabling the custom painter.
Created attachment 155426 [details] Screenshot I can reproduce this on RHEL 5 (gtk 2.10). Attaching a screenshot.
I can reproduce this on GTK3.22, Fedora 25.
Bug has been triaged as it occurs from Erics tests, see https://wiki.eclipse.org/SWT/Devel/Triage for more information.
New Gerrit change created: https://git.eclipse.org/r/137235
Gerrit change https://git.eclipse.org/r/137235 was merged to [master]. Commit: http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=eef687cb0ba0e614571caf5af7dc4ad829aeed1b
(In reply to Eclipse Genie from comment #6) > Gerrit change https://git.eclipse.org/r/137235 was merged to [master]. > Commit: > http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/ > ?id=eef687cb0ba0e614571caf5af7dc4ad829aeed1b In master now.
Verified in I20190409-0600.
I'm observing a regression after this issue has been fixed. My env: RHEL7, GTK3, org.eclipse.swt_v3.123. In my example I want to provide RED foreground color for Tree and GREEN foreground color for child items. The example code is the same, but with small changes at the main method. Run the application, enable custom painter, disable custom painter. The foreground color for the all items become RED, not RED-GREEN as on start-up. With such issue we cannot provide TreeItem's custom foreground color on CommonViewer (CNF). public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setBounds(10, 10, 800, 600); shell.setLayout(new GridLayout()); final Tree tree = new Tree(shell, SWT.BORDER); tree.setLinesVisible(true); // new code tree.setForeground(display.getSystemColor(SWT.COLOR_RED)); for (int i = 0; i < 5; i++) { TreeItem item = new TreeItem(tree, SWT.NONE); item.setText("item " + i); for (int j = 0; j < 5; j++) { TreeItem child = new TreeItem(item, SWT.NONE); child.setText("item " + i + "-" + j); // new code child.setForeground(display.getSystemColor(SWT.COLOR_GREEN)); } } tree.setLayoutData(new GridData(GridData.FILL_BOTH)); final TreePainter painer = new TreePainter(tree); final Button button = new Button(shell, SWT.CHECK); button.setText("Enable custom painter"); button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { painer.setListeners(button.getSelection()); } }); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); }