Skip to content

Commit cbda3bc

Browse files
Christopher-Hermannfedejeanne
authored andcommitted
Highlighting problem when using the dark theme on Windows
eclipse-platform/eclipse.platform.swt#811 JFace viewer are using OS selection color to highlight the selected item. On some OS this is not accessible. With this change, the selection color can be changed via color preference in the settings of eclipse. The colors are used to draw selection color for tree and table viewers. For Windows, the selection color in the dark theme is overwritten to fix the bad default coloring Fixes eclipse-platform/eclipse.platform.swt#811 Fixes #1688
1 parent 934ccc6 commit cbda3bc

File tree

20 files changed

+624
-34
lines changed

20 files changed

+624
-34
lines changed

bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Export-Package:
1010
org.eclipse.jface.contentassist.images,
1111
org.eclipse.jface.internal.text;x-internal:=true,
1212
org.eclipse.jface.internal.text.codemining;x-internal:=true,
13+
org.eclipse.jface.internal.text.contentassist;x-internal:=true,
1314
org.eclipse.jface.internal.text.html;x-friends:="org.eclipse.ant.ui, org.eclipse.jdt.ui, org.eclipse.ltk.ui.refactoring, org.eclipse.pde.ui, org.eclipse.ui.editors, org.eclipse.xtext.ui",
1415
org.eclipse.jface.internal.text.link.contentassist;x-internal:=true,
1516
org.eclipse.jface.internal.text.revisions;x-internal:=true,

bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java

+78-6
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
import org.eclipse.swt.widgets.Table;
2626
import org.eclipse.swt.widgets.TableItem;
2727

28+
import org.eclipse.jface.resource.ColorRegistry;
29+
import org.eclipse.jface.resource.JFaceResources;
30+
2831

2932
/**
3033
* Adds owner draw support for tables.
@@ -42,6 +45,10 @@ public class TableOwnerDrawSupport implements Listener {
4245

4346
public static void install(Table table) {
4447
TableOwnerDrawSupport listener= new TableOwnerDrawSupport(table);
48+
installListener(table, listener);
49+
}
50+
51+
protected static void installListener(Table table, Listener listener) {
4552
table.addListener(SWT.Dispose, listener);
4653
table.addListener(SWT.MeasureItem, listener);
4754
table.addListener(SWT.EraseItem, listener);
@@ -70,7 +77,7 @@ private static StyleRange[] getStyledRanges(TableItem item, int column) {
7077
return (StyleRange[])item.getData(STYLED_RANGES_KEY + column);
7178
}
7279

73-
private TableOwnerDrawSupport(Table table) {
80+
protected TableOwnerDrawSupport(Table table) {
7481
int orientation= table.getStyle() & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
7582
fSharedLayout= new TextLayout(table.getDisplay());
7683
fSharedLayout.setOrientation(orientation);
@@ -147,7 +154,28 @@ private void performPaint(Event event) {
147154
Color oldForeground= gc.getForeground();
148155
Color oldBackground= gc.getBackground();
149156

150-
if (!isSelected) {
157+
if (isSelected) {
158+
Color background= item.getParent().isFocusControl()
159+
? getSelectedRowBackgroundColor()
160+
: getSelectedRowBackgroundColorNoFocus();
161+
Color foreground= item.getParent().isFocusControl()
162+
? getSelectedRowForegroundColor()
163+
: getSelectedRowForegroundColorNoFocus();
164+
165+
if (background == null) {
166+
background= item.getDisplay().getSystemColor(
167+
SWT.COLOR_LIST_SELECTION);
168+
}
169+
170+
if (foreground == null) {
171+
foreground= item.getDisplay().getSystemColor(
172+
SWT.COLOR_LIST_SELECTION_TEXT);
173+
}
174+
175+
gc.setBackground(background);
176+
gc.setForeground(foreground);
177+
gc.fillRectangle(0, event.y, item.getParent().getBounds().width, event.height);
178+
} else {
151179
Color foreground= item.getForeground(index);
152180
gc.setForeground(foreground);
153181

@@ -178,10 +206,54 @@ private void performPaint(Event event) {
178206
gc.drawFocus(focusBounds.x, focusBounds.y, focusBounds.width + fDeltaOfLastMeasure, focusBounds.height);
179207
}
180208

181-
if (!isSelected) {
182-
gc.setForeground(oldForeground);
183-
gc.setBackground(oldBackground);
184-
}
209+
gc.setForeground(oldForeground);
210+
gc.setBackground(oldBackground);
211+
}
212+
213+
/**
214+
* The color to use when rendering the background of the selected row when the control has the
215+
* input focus
216+
*
217+
* @return the color or <code>null</code> to use the default
218+
*/
219+
protected Color getSelectedRowBackgroundColor() {
220+
ColorRegistry colorRegistry= JFaceResources.getColorRegistry();
221+
return colorRegistry.get("org.eclipse.ui.workbench.SELECTED_CELL_BACKGROUND"); //$NON-NLS-1$
222+
}
223+
224+
/**
225+
* The color to use when rendering the foreground (=text) of the selected row when the control
226+
* has the input focus
227+
*
228+
* @return the color or <code>null</code> to use the default
229+
*/
230+
protected Color getSelectedRowForegroundColor() {
231+
ColorRegistry colorRegistry= JFaceResources.getColorRegistry();
232+
return colorRegistry.get("org.eclipse.ui.workbench.SELECTED_CELL_FOREGROUND"); //$NON-NLS-1$
233+
}
234+
235+
/**
236+
* The color to use when rendering the foreground (=text) of the selected row when the control
237+
* has <b>no</b> input focus
238+
*
239+
* @return the color or <code>null</code> to use the same used when control has focus
240+
* @since 3.4
241+
*/
242+
protected Color getSelectedRowForegroundColorNoFocus() {
243+
ColorRegistry colorRegistry= JFaceResources.getColorRegistry();
244+
return colorRegistry.get("org.eclipse.ui.workbench.SELECTED_CELL_FOREGROUND_NO_FOCUS"); //$NON-NLS-1$
245+
}
246+
247+
/**
248+
* The color to use when rendering the background of the selected row when the control has
249+
* <b>no</b> input focus
250+
*
251+
* @return the color or <code>null</code> to use the same used when control has focus
252+
* @since 3.4
253+
*/
254+
protected Color getSelectedRowBackgroundColorNoFocus() {
255+
ColorRegistry colorRegistry= JFaceResources.getColorRegistry();
256+
return colorRegistry.get("org.eclipse.ui.workbench.SELECTED_CELL_BACKGROUND_NO_FOCUS"); //$NON-NLS-1$
185257
}
186258

187259
private void widgetDisposed() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 SAP SE.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* SAP SE - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.jface.internal.text.contentassist;
15+
16+
import org.eclipse.swt.custom.StyleRange;
17+
import org.eclipse.swt.graphics.Color;
18+
import org.eclipse.swt.widgets.Table;
19+
import org.eclipse.swt.widgets.TableItem;
20+
21+
import org.eclipse.jface.internal.text.TableOwnerDrawSupport;
22+
23+
/**
24+
* When a completion table (for example for code completion) is requested by the user, the user
25+
* needs to be able to continue typing in the linked text control. In such cases, the focus is not
26+
* on the completion table. To ensure the selected code completion proposal always displays in the
27+
* correct color, even if the completion table is not focused, the non-focused colors are overridden
28+
* with the focus colors.
29+
*/
30+
public class CompletionTableDrawSupport extends TableOwnerDrawSupport {
31+
32+
public static void install(Table table) {
33+
TableOwnerDrawSupport listener= new CompletionTableDrawSupport(table);
34+
installListener(table, listener);
35+
}
36+
37+
/**
38+
* Stores the styled ranges in the given table item. See {@link TableOwnerDrawSupport}
39+
*
40+
* @param item table item
41+
* @param column the column index
42+
* @param ranges the styled ranges or <code>null</code> to remove them
43+
*/
44+
public static void storeStyleRanges(TableItem item, int column, StyleRange[] ranges) {
45+
TableOwnerDrawSupport.storeStyleRanges(item, column, ranges);
46+
}
47+
48+
49+
private CompletionTableDrawSupport(Table table) {
50+
super(table);
51+
}
52+
53+
@Override
54+
protected Color getSelectedRowBackgroundColorNoFocus() {
55+
return super.getSelectedRowBackgroundColor();
56+
}
57+
58+
@Override
59+
protected Color getSelectedRowForegroundColorNoFocus() {
60+
return super.getSelectedRowForegroundColor();
61+
}
62+
63+
}

bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/link/contentassist/CompletionProposalPopup2.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
import org.eclipse.swt.widgets.Table;
4040
import org.eclipse.swt.widgets.TableItem;
4141

42-
import org.eclipse.jface.internal.text.TableOwnerDrawSupport;
42+
import org.eclipse.jface.internal.text.contentassist.CompletionTableDrawSupport;
4343
import org.eclipse.jface.preference.JFacePreferences;
4444
import org.eclipse.jface.resource.ColorRegistry;
4545
import org.eclipse.jface.resource.JFaceColors;
@@ -269,7 +269,7 @@ private void createProposalSelector() {
269269

270270
fIsColoredLabelsSupportEnabled= fContentAssistant.isColoredLabelsSupportEnabled();
271271
if (fIsColoredLabelsSupportEnabled)
272-
TableOwnerDrawSupport.install(fProposalTable);
272+
CompletionTableDrawSupport.install(fProposalTable);
273273

274274
fProposalTable.setLocation(0, 0);
275275
if (fAdditionalInfoController != null)
@@ -572,7 +572,7 @@ private void setProposals(ICompletionProposal[] proposals) {
572572

573573
item.setText(displayString);
574574
if (fIsColoredLabelsSupportEnabled)
575-
TableOwnerDrawSupport.storeStyleRanges(item, 0, styleRanges);
575+
CompletionTableDrawSupport.storeStyleRanges(item, 0, styleRanges);
576576

577577
item.setData(p);
578578

bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
import org.eclipse.jface.bindings.keys.SWTKeySupport;
7979
import org.eclipse.jface.contentassist.IContentAssistSubjectControl;
8080
import org.eclipse.jface.internal.text.InformationControlReplacer;
81-
import org.eclipse.jface.internal.text.TableOwnerDrawSupport;
81+
import org.eclipse.jface.internal.text.contentassist.CompletionTableDrawSupport;
8282
import org.eclipse.jface.preference.JFacePreferences;
8383
import org.eclipse.jface.resource.JFaceColors;
8484
import org.eclipse.jface.resource.JFaceResources;
@@ -613,7 +613,7 @@ void createProposalSelector() {
613613

614614
fIsColoredLabelsSupportEnabled= fContentAssistant.isColoredLabelsSupportEnabled();
615615
if (fIsColoredLabelsSupportEnabled)
616-
TableOwnerDrawSupport.install(fProposalTable);
616+
CompletionTableDrawSupport.install(fProposalTable);
617617

618618
fProposalTable.setLocation(0, 0);
619619
if (fAdditionalInfoController != null)
@@ -904,7 +904,7 @@ private void handleSetData(Event event) {
904904

905905
item.setText(displayString);
906906
if (fIsColoredLabelsSupportEnabled)
907-
TableOwnerDrawSupport.storeStyleRanges(item, 0, styleRanges);
907+
CompletionTableDrawSupport.storeStyleRanges(item, 0, styleRanges);
908908

909909
item.setImage(image);
910910
item.setData(current);

bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/FocusCellOwnerDrawHighlighter.java

+10-5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import org.eclipse.core.runtime.Assert;
2020
import org.eclipse.jface.util.Util;
21+
import org.eclipse.jface.resource.ColorRegistry;
22+
import org.eclipse.jface.resource.JFaceResources;
2123
import org.eclipse.swt.SWT;
2224
import org.eclipse.swt.graphics.Color;
2325
import org.eclipse.swt.graphics.GC;
@@ -151,8 +153,8 @@ private void hookListener(final ColumnViewer viewer) {
151153
* @return the color or <code>null</code> to use the default
152154
*/
153155
protected Color getSelectedCellBackgroundColor(ViewerCell cell) {
154-
return removeNonFocusedSelectionInformation ? null
155-
: cell.getItem().getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
156+
ColorRegistry colorRegistry = JFaceResources.getColorRegistry();
157+
return colorRegistry.get("org.eclipse.ui.workbench.SELECTED_CELL_BACKGROUND"); //$NON-NLS-1$
156158
}
157159

158160
/**
@@ -164,7 +166,8 @@ protected Color getSelectedCellBackgroundColor(ViewerCell cell) {
164166
* @return the color or <code>null</code> to use the default
165167
*/
166168
protected Color getSelectedCellForegroundColor(ViewerCell cell) {
167-
return null;
169+
ColorRegistry colorRegistry = JFaceResources.getColorRegistry();
170+
return colorRegistry.get("org.eclipse.ui.workbench.SELECTED_CELL_FOREGROUND"); //$NON-NLS-1$
168171
}
169172

170173
/**
@@ -178,7 +181,8 @@ protected Color getSelectedCellForegroundColor(ViewerCell cell) {
178181
* @since 3.4
179182
*/
180183
protected Color getSelectedCellForegroundColorNoFocus(ViewerCell cell) {
181-
return null;
184+
ColorRegistry colorRegistry = JFaceResources.getColorRegistry();
185+
return colorRegistry.get("org.eclipse.ui.workbench.SELECTED_CELL_FOREGROUND_NO_FOCUS"); //$NON-NLS-1$
182186
}
183187

184188
/**
@@ -192,7 +196,8 @@ protected Color getSelectedCellForegroundColorNoFocus(ViewerCell cell) {
192196
* @since 3.4
193197
*/
194198
protected Color getSelectedCellBackgroundColorNoFocus(ViewerCell cell) {
195-
return null;
199+
ColorRegistry colorRegistry = JFaceResources.getColorRegistry();
200+
return colorRegistry.get("org.eclipse.ui.workbench.SELECTED_CELL_BACKGROUND_NO_FOCUS"); //$NON-NLS-1$
196201
}
197202

198203
/**

bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider.java

+18-15
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import java.util.HashSet;
1818
import java.util.Set;
1919

20+
import org.eclipse.jface.resource.ColorRegistry;
21+
import org.eclipse.jface.resource.JFaceResources;
2022
import org.eclipse.swt.SWT;
2123
import org.eclipse.swt.graphics.Color;
2224
import org.eclipse.swt.graphics.Rectangle;
@@ -166,20 +168,16 @@ public void update(ViewerCell cell) {
166168
}
167169

168170
/**
169-
* Handle the erase event. The default implementation colors the background
170-
* of selected areas with {@link SWT#COLOR_LIST_SELECTION} and foregrounds
171-
* with {@link SWT#COLOR_LIST_SELECTION_TEXT}. Note that this
172-
* implementation causes non-native behavior on some platforms. Subclasses
173-
* should override this method and <b>not</b> call the super
171+
* Handle the erase event. The default implementation colors the background of
172+
* selected areas with "org.eclipse.ui.workbench.SELECTED_CELL_BACKGROUND" and
173+
* foregrounds with "org.eclipse.ui.workbench.SELECTED_CELL_FOREGROUND". Note
174+
* that this implementation causes non-native behavior on some platforms.
175+
* Subclasses should override this method and <b>not</b> call the super
174176
* implementation.
175177
*
176-
* @param event
177-
* the erase event
178-
* @param element
179-
* the model object
178+
* @param event the erase event
179+
* @param element the model object
180180
* @see SWT#EraseItem
181-
* @see SWT#COLOR_LIST_SELECTION
182-
* @see SWT#COLOR_LIST_SELECTION_TEXT
183181
*/
184182
protected void erase(Event event, Object element) {
185183

@@ -189,11 +187,16 @@ protected void erase(Event event, Object element) {
189187
Color oldForeground = event.gc.getForeground();
190188
Color oldBackground = event.gc.getBackground();
191189

192-
event.gc.setBackground(event.item.getDisplay().getSystemColor(
193-
SWT.COLOR_LIST_SELECTION));
194-
event.gc.setForeground(event.item.getDisplay().getSystemColor(
195-
SWT.COLOR_LIST_SELECTION_TEXT));
190+
ColorRegistry colorRegistry = JFaceResources.getColorRegistry();
191+
if (event.widget instanceof Control control && control.isFocusControl()) {
192+
event.gc.setBackground(colorRegistry.get("org.eclipse.ui.workbench.SELECTED_CELL_BACKGROUND")); //$NON-NLS-1$
193+
event.gc.setForeground(colorRegistry.get("org.eclipse.ui.workbench.SELECTED_CELL_FOREGROUND")); //$NON-NLS-1$
194+
} else {
195+
event.gc.setBackground(colorRegistry.get("org.eclipse.ui.workbench.SELECTED_CELL_BACKGROUND_NO_FOCUS")); //$NON-NLS-1$
196+
event.gc.setForeground(colorRegistry.get("org.eclipse.ui.workbench.SELECTED_CELL_FOREGROUND_NO_FOCUS")); //$NON-NLS-1$
197+
}
196198
event.gc.fillRectangle(bounds);
199+
197200
/* restore the old GC colors */
198201
event.gc.setForeground(oldForeground);
199202
event.gc.setBackground(oldBackground);

bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/StyledCellLabelProvider.java

+1
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ protected void erase(Event event, Object element) {
263263
// info has been set by 'update': announce that we paint ourselves
264264
event.detail &= ~SWT.FOREGROUND;
265265
}
266+
super.erase(event, element);
266267
}
267268

268269
@Override

bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/TableViewer.java

+11
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package org.eclipse.jface.viewers;
2121

2222
import org.eclipse.core.runtime.Assert;
23+
import org.eclipse.jface.viewers.internal.ColumnViewerSelectionColorListener;
2324
import org.eclipse.jface.viewers.internal.ExpandableNode;
2425
import org.eclipse.pde.api.tools.annotations.NoExtend;
2526
import org.eclipse.swt.SWT;
@@ -119,6 +120,7 @@ public TableViewer(Composite parent, int style) {
119120
public TableViewer(Table table) {
120121
this.table = table;
121122
hookControl(table);
123+
overwriteSelectionColor();
122124
}
123125

124126
@Override
@@ -507,4 +509,13 @@ void handleExpandableNodeClicked(Widget w) {
507509
}
508510
}
509511

512+
/**
513+
* The color of the selected item is drawn by the OS. On some OS the color might
514+
* be not accessible. To fix this issue the background color for selected items
515+
* is drawn in a custom method.
516+
*/
517+
private void overwriteSelectionColor() {
518+
ColumnViewerSelectionColorListener.addListenerToViewer(this);
519+
}
520+
510521
}

0 commit comments

Comments
 (0)