| Summary: | [GTK] Incorrect behaviour of tree rendering on GTK after removing paint listener | ||||||
|---|---|---|---|---|---|---|---|
| Product: | [Eclipse Project] Platform | Reporter: | Yuri Strot <yuri> | ||||
| Component: | SWT | Assignee: | Eric Williams <ericwill> | ||||
| Status: | VERIFIED FIXED | QA Contact: | Praveen <pinnamur> | ||||
| Severity: | normal | ||||||
| Priority: | P3 | CC: | alex.panchenko, cocoakevin, ericwill, gautier.desaintmartinlacaze, ipun, pinnamur | ||||
| Version: | 4.8 | Keywords: | triaged | ||||
| Target Milestone: | 4.12 M1 | ||||||
| Hardware: | PC | ||||||
| OS: | Linux | ||||||
| See Also: |
https://git.eclipse.org/r/137235 https://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=eef687cb0ba0e614571caf5af7dc4ad829aeed1b |
||||||
| Whiteboard: | RHT | ||||||
| Attachments: |
|
||||||
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. |
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(); } }