Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Win32] Table and Tree use light background, if disabled and EraseItem event is registered #1836

Open
tmssngr opened this issue Feb 15, 2025 · 2 comments

Comments

@tmssngr
Copy link
Contributor

tmssngr commented Feb 15, 2025

Describe the bug
For a dark theme the background color of a disabled Tree or Table is white.

To Reproduce
Run this snippet on Windows and toggle the "enabled" checkbox:

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

/**
 * @author Thomas Singer
 */
public class DarkControlTest {

	private static final Color DARK_GRAY = new Color(32, 32, 32);
	private static final Color LIGHT_GRAY = new Color(200, 200, 200);

	public static void main(String[] args) {
		final Display display = new Display();

		display.addListener(SWT.Skin, event -> {
			if (event.widget instanceof Control control) {
				control.setBackground(DARK_GRAY);
				control.setForeground(LIGHT_GRAY);
				if (control instanceof Table table) {
					table.setHeaderBackground(DARK_GRAY);
					table.setHeaderForeground(LIGHT_GRAY);
				}
				if (control instanceof Tree tree) {
					tree.setHeaderBackground(DARK_GRAY);
					tree.setHeaderForeground(LIGHT_GRAY);
				}
			}
		});

		final Shell shell = new Shell(display);
		shell.setLayout(new GridLayout(2, true));

		final Control table = createTable(shell);
		final Control tree = createTree(shell);

		final Button checkbox = new Button(shell, SWT.CHECK);
		checkbox.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
		checkbox.setText("enabled");
		checkbox.setSelection(true);
		checkbox.addListener(SWT.Selection, event -> {
			table.setEnabled(checkbox.getSelection());
			tree.setEnabled(checkbox.getSelection());
		});

		shell.setSize(400, 300);
		shell.open();

		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}

		display.dispose();
	}

	private static Table createTable(Composite parent) {
		final Table table = new Table(parent, SWT.BORDER);
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		table.setHeaderVisible(true);

		table.addListener(SWT.EraseItem, event -> {
			final Rectangle clientArea = table.getClientArea();
			event.gc.fillRectangle(clientArea.x, event.y, clientArea.width, event.height);

			event.detail &= ~(SWT.FOREGROUND | SWT.BACKGROUND | SWT.HOT | SWT.SELECTED);
		});
		table.addListener(SWT.PaintItem, event -> {
			event.gc.drawText(((Item)event.item).getText(), event.x, event.y);
		});


		final TableColumn column = new TableColumn(table, SWT.LEFT);
		column.setText("Column");
		column.setWidth(150);

		new TableItem(table, SWT.LEFT).setText("Item 1");
		new TableItem(table, SWT.LEFT).setText("Item 2");
		return table;
	}

	private static Tree createTree(Composite parent) {
		final Tree tree = new Tree(parent, SWT.BORDER);
		tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		tree.setHeaderVisible(true);

		tree.addListener(SWT.EraseItem, event -> {
			event.gc.setClipping((Rectangle)null);
			final Rectangle clientArea = tree.getClientArea();
			event.gc.fillRectangle(clientArea.x, event.y, clientArea.width, event.height);

			event.detail &= ~(SWT.FOREGROUND | SWT.BACKGROUND | SWT.HOT | SWT.SELECTED);
		});
		tree.addListener(SWT.PaintItem, event -> {
			event.gc.drawText(((Item)event.item).getText(), event.x, event.y);
		});

		new TreeItem(tree, SWT.LEFT).setText("Item 1");
		new TreeItem(tree, SWT.LEFT).setText("Item 2");
		return tree;
	}
}

Expected behavior
In both cases, enabled and disabled, the set background color should be used.

Screenshots
enabled:
Image

disabled:
Image

Environment:

  1. Select the platform(s) on which the behavior is seen:
    • All OS
    • Windows
    • Linux
    • macOS
@deepika-u
Copy link
Contributor

deepika-u commented Feb 24, 2025

Hi @tmssngr
I tried a slight modification in your program as below

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

/**
 * @author Thomas Singer
 */
public class DarkControlTest {

	private static final Color DARK_GRAY = new Color(32, 32, 32);
	private static final Color LIGHT_GRAY = new Color(200, 200, 200);

	public static void main(String[] args) {
		final Display display = new Display();

		display.addListener(SWT.Skin, event -> {
			if (event.widget instanceof Control control) {
				control.setBackground(DARK_GRAY);
				control.setForeground(LIGHT_GRAY);
				if (control instanceof Table table) {
//					table.setHeaderBackground(DARK_GRAY);
//					table.setHeaderForeground(LIGHT_GRAY);
					System.out.println(table.getBackground().getRGB() + "Before : table.getBackground().getRGB()");
					table.setHeaderBackground(table.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
					table.setHeaderForeground(table.getDisplay().getSystemColor(SWT.COLOR_GRAY));
					table.setBackground(table.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
					table.setForeground(table.getDisplay().getSystemColor(SWT.COLOR_GRAY));
					System.out.println(table.getBackground().getRGB() + "After : table.getBackground().getRGB()");
				}
				if (control instanceof Tree tree) {
//					tree.setHeaderBackground(DARK_GRAY);
//					tree.setHeaderForeground(LIGHT_GRAY);
					System.out.println(tree.getBackground().getRGB()+ "Before : tree.getBackground().getRGB()");
					tree.setHeaderBackground(tree.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
					tree.setHeaderForeground(tree.getDisplay().getSystemColor(SWT.COLOR_GRAY));
					tree.setBackground(tree.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
					tree.setForeground(tree.getDisplay().getSystemColor(SWT.COLOR_GRAY));
					System.out.println(tree.getBackground().getRGB()+ "After : tree.getBackground().getRGB()");
				}
			}
		});

		final Shell shell = new Shell(display);
		shell.setLayout(new GridLayout(2, true));

		final Control table = createTable(shell);
		final Control tree = createTree(shell);
		System.out.println(table.getBackground().getRGB() + "Just Created : table.getBackground().getRGB()");
		System.out.println(tree.getBackground().getRGB()+ "Just Created : tree.getBackground().getRGB()");

		final Button checkbox = new Button(shell, SWT.CHECK);
		checkbox.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
		checkbox.setText("enabled");
		checkbox.setSelection(true);
		checkbox.addListener(SWT.Selection, event -> {
			table.setEnabled(checkbox.getSelection());
			tree.setEnabled(checkbox.getSelection());
		});

		shell.setSize(400, 300);
		shell.open();

		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}

		display.dispose();
	}

	private static Table createTable(Composite parent) {
		final Table table = new Table(parent, SWT.BORDER);
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		table.setHeaderVisible(true);

		table.addListener(SWT.EraseItem, event -> {
			final Rectangle clientArea = table.getClientArea();
			event.gc.fillRectangle(clientArea.x, event.y, clientArea.width, event.height);

			event.detail &= ~(SWT.FOREGROUND | SWT.BACKGROUND | SWT.HOT | SWT.SELECTED);
		});
		table.addListener(SWT.PaintItem, event -> {
			event.gc.drawText(((Item)event.item).getText(), event.x, event.y);
		});

		final TableColumn column = new TableColumn(table, SWT.LEFT);
		column.setText("Column");
		column.setWidth(150);

		new TableItem(table, SWT.LEFT).setText("Item 1");
		new TableItem(table, SWT.LEFT).setText("Item 2");
		return table;
	}

	private static Tree createTree(Composite parent) {
		final Tree tree = new Tree(parent, SWT.BORDER);
		tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		tree.setHeaderVisible(true);

		tree.addListener(SWT.EraseItem, event -> {
			event.gc.setClipping((Rectangle)null);
			final Rectangle clientArea = tree.getClientArea();
			event.gc.fillRectangle(clientArea.x, event.y, clientArea.width, event.height);

			event.detail &= ~(SWT.FOREGROUND | SWT.BACKGROUND | SWT.HOT | SWT.SELECTED);
		});
		tree.addListener(SWT.PaintItem, event -> {
			event.gc.drawText(((Item)event.item).getText(), event.x, event.y);
		});

		new TreeItem(tree, SWT.LEFT).setText("Item 1");
		new TreeItem(tree, SWT.LEFT).setText("Item 2");
		return tree;
	}
}

Slight modifications done in display.addListener(), not much. My observation here is as below
corresponds to RGB {255, 255, 255}Just Created : table.getBackground().getRGB() - white
corresponds to RGB {128, 128, 128}After : table.getBackground().getRGB() - light gray
corresponds to RGB {32, 32, 32}Before : table.getBackground().getRGB() - dark gray
corresponds to RGB {0, 0, 0}Before : table.getBackground().getRGB() - black

So from this atleast i feel when first created all the widgets get background(white) then when skin is applied respective theme gets applied. On top of it as you set with setBackground gets applied.

Can you try this and see what you want can be achieved or not?

fyi : I tried to map colors from ControlExample -> Tree/Table -> change background "change" custom color palatte.

Image

@tmssngr
Copy link
Contributor Author

tmssngr commented Feb 25, 2025

Sorry, I don't understand what you suggest. Your change only sets different gray colors, the problem remains.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants