Date: Thu, 26 Feb 2026 13:24:04 +0100
Subject: [PATCH 07/26] Make constructor private
---
.../jface/viewers/ColumnViewerSelectionColorListener.java | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
index 01c8012de8ee..ceac09ba4671 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
@@ -57,6 +57,13 @@ public class ColumnViewerSelectionColorListener implements Listener {
private static final String COLOR_SELECTION_BG_NO_FOCUS = "org.eclipse.jface.SELECTION_BACKGROUND_NO_FOCUS"; //$NON-NLS-1$
private static final String COLOR_SELECTION_FG_NO_FOCUS = "org.eclipse.jface.SELECTION_FOREGROUND_NO_FOCUS"; //$NON-NLS-1$
+ /**
+ * This class shouldn't be instantiated directly. Attach this listener to a
+ * viewer via {@link #addListenerToViewer(StructuredViewer)} instead.
+ */
+ private ColumnViewerSelectionColorListener() {
+ }
+
/**
* Registers the selection color listener on the given viewer.
*
From bc866ce15048667fd7bcb05895decb103088dbaa Mon Sep 17 00:00:00 2001
From: Christopher Hermann
Date: Wed, 12 Feb 2025 10:34:14 +0100
Subject: [PATCH 08/26] Draw completion proposals always as focused
When opening the completion proposals via the keyboard, the focus will
stay in the editor to be able to accept further user input. This is
causing the completion proposal to be drawn in non focus colors. This
colors can lead to UX problems, especially in dark theme.
With this fix, the completion proposals are always drawn in focused
colors.
Fixes #1688
---
.../internal/text/TableOwnerDrawSupport.java | 2 +-
.../CompletionProposalDrawSupport.java | 63 +++++++++++++++++++
.../CompletionProposalPopup2.java | 3 +-
.../CompletionProposalPopup.java | 3 +-
4 files changed, 68 insertions(+), 3 deletions(-)
create mode 100644 bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java
index a4b1ffd4257e..7e7ffe909c0d 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java
@@ -72,7 +72,7 @@ private static StyleRange[] getStyledRanges(TableItem item, int column) {
return (StyleRange[])item.getData(STYLED_RANGES_KEY + column);
}
- private TableOwnerDrawSupport(Table table) {
+ public TableOwnerDrawSupport(Table table) {
int orientation= table.getStyle() & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
fSharedLayout= new TextLayout(table.getDisplay());
fSharedLayout.setOrientation(orientation);
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java
new file mode 100644
index 000000000000..d6fd283cae72
--- /dev/null
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2025 SAP SE.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * SAP SE - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jface.internal.text.contentassist;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Table;
+
+import org.eclipse.jface.internal.text.TableOwnerDrawSupport;
+
+/**
+ * Provides custom drawing support for completion proposals. This class ensures that completion
+ * proposals are always rendered with a focused appearance.
+ *
+ *
+ * This drawing behavior addresses the particular situation where the code completion is triggered
+ * via keyboard shortcut, leaving the editor focused. In such cases, without this custom drawing
+ * support, the completion proposal would appear unfocused, leading to a suboptimal coloring.
+ *
+ */
+public class CompletionProposalDrawSupport implements Listener {
+
+ private final TableOwnerDrawSupport fTableOwnerDrawSupport;
+
+ private CompletionProposalDrawSupport(Table table) {
+ fTableOwnerDrawSupport= new TableOwnerDrawSupport(table);
+ }
+
+ public static void install(Table table) {
+ CompletionProposalDrawSupport listener= new CompletionProposalDrawSupport(table);
+ table.addListener(SWT.Dispose, listener);
+ table.addListener(SWT.MeasureItem, listener);
+ table.addListener(SWT.EraseItem, listener);
+ table.addListener(SWT.PaintItem, listener);
+ }
+
+ @Override
+ public void handleEvent(Event event) {
+ if (event.widget instanceof Control control && !control.isFocusControl() && (event.type == SWT.EraseItem || event.type == SWT.PaintItem) && event.gc != null) {
+ Color background= event.widget.getDisplay().getSystemColor(SWT.COLOR_TITLE_BACKGROUND);
+ Color foreground= event.widget.getDisplay().getSystemColor(SWT.COLOR_WHITE);
+ event.gc.setBackground(background);
+ event.gc.setForeground(foreground);
+ }
+
+ fTableOwnerDrawSupport.handleEvent(event);
+ }
+
+}
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/link/contentassist/CompletionProposalPopup2.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/link/contentassist/CompletionProposalPopup2.java
index d4450c2eacce..35306f2d4303 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/link/contentassist/CompletionProposalPopup2.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/link/contentassist/CompletionProposalPopup2.java
@@ -40,6 +40,7 @@
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.jface.internal.text.TableOwnerDrawSupport;
+import org.eclipse.jface.internal.text.contentassist.CompletionProposalDrawSupport;
import org.eclipse.jface.preference.JFacePreferences;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.JFaceColors;
@@ -274,7 +275,7 @@ private void createProposalSelector() {
fIsColoredLabelsSupportEnabled= fContentAssistant.isColoredLabelsSupportEnabled();
if (fIsColoredLabelsSupportEnabled) {
- TableOwnerDrawSupport.install(fProposalTable);
+ CompletionProposalDrawSupport.install(fProposalTable);
}
fProposalTable.setLocation(0, 0);
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java
index 3333fe01085e..661228369bd9 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java
@@ -79,6 +79,7 @@
import org.eclipse.jface.contentassist.IContentAssistSubjectControl;
import org.eclipse.jface.internal.text.InformationControlReplacer;
import org.eclipse.jface.internal.text.TableOwnerDrawSupport;
+import org.eclipse.jface.internal.text.contentassist.CompletionProposalDrawSupport;
import org.eclipse.jface.preference.JFacePreferences;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.jface.resource.JFaceResources;
@@ -628,7 +629,7 @@ void createProposalSelector() {
fIsColoredLabelsSupportEnabled= fContentAssistant.isColoredLabelsSupportEnabled();
if (fIsColoredLabelsSupportEnabled) {
- TableOwnerDrawSupport.install(fProposalTable);
+ CompletionProposalDrawSupport.install(fProposalTable);
}
fProposalTable.setLocation(0, 0);
From 095c9869f9b037f1b4e91df90cdc78bd87163699 Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 09:31:17 +0100
Subject: [PATCH 09/26] Undo some changes in TableOwnerDrawSupport
They will be handled via the CompletionProposalDrawSupport
---
.../jface/internal/text/TableOwnerDrawSupport.java | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java
index 7e7ffe909c0d..343f17864e81 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java
@@ -25,8 +25,6 @@
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
-import org.eclipse.jface.viewers.ColumnViewerSelectionColorListener;
-
/**
* Adds owner draw support for tables.
@@ -85,7 +83,7 @@ public void handleEvent(Event event) {
measureItem(event);
break;
case SWT.EraseItem:
- event.detail&= ~SWT.FOREGROUND;
+ event.detail &= ~SWT.FOREGROUND;
break;
case SWT.PaintItem:
performPaint(event);
@@ -149,9 +147,7 @@ private void performPaint(Event event) {
Color oldForeground= gc.getForeground();
Color oldBackground= gc.getBackground();
- if (isSelected) {
- ColumnViewerSelectionColorListener.drawSelection(event);
- } else {
+ if (!isSelected) {
Color foreground= item.getForeground(index);
gc.setForeground(foreground);
From ada2dc8ea302973b09efc06bae134747d525aee2 Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 14:47:39 +0100
Subject: [PATCH 10/26] Move stuff around
---
.../CompletionProposalDrawSupport.java | 36 ++-
.../ColumnViewerSelectionColorListener.java | 224 +++++++++++-------
2 files changed, 166 insertions(+), 94 deletions(-)
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java
index d6fd283cae72..de11a5792cd3 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java
@@ -18,9 +18,11 @@
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Scrollable;
import org.eclipse.swt.widgets.Table;
import org.eclipse.jface.internal.text.TableOwnerDrawSupport;
+import org.eclipse.jface.viewers.ColumnViewerSelectionColorListener;
/**
* Provides custom drawing support for completion proposals. This class ensures that completion
@@ -50,14 +52,36 @@ public static void install(Table table) {
@Override
public void handleEvent(Event event) {
- if (event.widget instanceof Control control && !control.isFocusControl() && (event.type == SWT.EraseItem || event.type == SWT.PaintItem) && event.gc != null) {
- Color background= event.widget.getDisplay().getSystemColor(SWT.COLOR_TITLE_BACKGROUND);
- Color foreground= event.widget.getDisplay().getSystemColor(SWT.COLOR_WHITE);
- event.gc.setBackground(background);
- event.gc.setForeground(foreground);
+
+ if (event.widget instanceof Control && event.gc != null) {
+
+ boolean isSelected= (event.detail & SWT.SELECTED) != 0;
+
+ if (event.type == SWT.EraseItem && isSelected) {
+
+ final Color backgroundColor= ColumnViewerSelectionColorListener.getBackgroundColor(isSelected, event.display);
+ event.gc.setBackground(backgroundColor);
+
+ final int width= (event.widget instanceof Scrollable s) ? s.getClientArea().width : event.width;
+ event.gc.fillRectangle(0, event.y, width, event.height);
+
+ // Prevent native selection drawing
+ // Do NOT clear SWT.BACKGROUND here unless you really want to suppress SWT
+ // background painting.
+ // (You *can* clear SWT.BACKGROUND if you see it overwriting your fill on a
+ // platform,
+ // but try without first.)
+ event.detail&= ~SWT.SELECTED;
+
+ } else if (event.type == SWT.PaintItem) {
+
+ final Color foregroundColor= ColumnViewerSelectionColorListener.getForegroundColor(isSelected, event.display);
+ event.gc.setForeground(foregroundColor);
+
+// event.detail&= ~SWT.FOREGROUND;
+ }
}
fTableOwnerDrawSupport.handleEvent(event);
}
-
}
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
index ceac09ba4671..693cf21fac89 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
@@ -19,11 +19,13 @@
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Scrollable;
@@ -49,6 +51,23 @@
*/
public class ColumnViewerSelectionColorListener implements Listener {
+ /**
+ * Contains the values of the color definitions from the
+ * plugin.xml.
+ *
+ * @implNote If some value doesn't match the exact name (String) inside the
+ * plugin.xml or if some string from the xml is not
+ * present here then
+ * {@link ColumnViewerSelectionColorFactory#getSystemColorForId(ColorId)}
+ * will not return what you expect.
+ * @since 3.5
+ *
+ */
+// private static enum ColorId {
+// SELECTED_CELL_BACKGROUND, SELECTED_CELL_FOREGROUND, SELECTED_CELL_BACKGROUND_NO_FOCUS,
+// SELECTED_CELL_FOREGROUND_NO_FOCUS
+// }
+
private static final String LISTENER_KEY = "org.eclipse.jface.viewers.selection_color_listener"; //$NON-NLS-1$
private static final String OWNER_DRAW_LISTENER_KEY = "owner_draw_label_provider_listener"; //$NON-NLS-1$
@@ -64,47 +83,10 @@ public class ColumnViewerSelectionColorListener implements Listener {
private ColumnViewerSelectionColorListener() {
}
- /**
- * Registers the selection color listener on the given viewer.
- *
- * This method is idempotent - calling it multiple times on the same viewer has
- * no additional effect.
- *
- *
- * @param viewer the viewer to which the listener should be added
- */
- public static void addListenerToViewer(StructuredViewer viewer) {
- Control control = viewer.getControl();
- if (control.isDisposed() || isListenerRegistered(control)) {
- return; // Already registered or disposed
- }
-
- ColumnViewerSelectionColorListener listener = new ColumnViewerSelectionColorListener();
- control.setData(LISTENER_KEY, listener);
- control.addListener(SWT.EraseItem, listener);
- }
-
private static boolean isListenerRegistered(Control control) {
return control.getData(LISTENER_KEY) != null;
}
- @Override
- public void handleEvent(Event event) {
- if ((event.detail & SWT.SELECTED) == 0) {
- return; // Not selected
- }
-
- if (event.widget instanceof Control control && !control.isEnabled()) {
- return; // Disabled control
- }
-
- if (hasAdditionalEraseItemListeners(event)) {
- return; // Let other listeners handle selection
- }
-
- drawSelection(event);
- }
-
/**
* Checks if additional EraseItem listeners were registered after this listener
* that are NOT the OwnerDrawListener. This allows user code to override the
@@ -128,69 +110,39 @@ private boolean hasAdditionalEraseItemListeners(Event event) {
.anyMatch(l -> l != ownerDrawListener);
}
- /**
- * Draws custom selection coloring for the given event.
- *
- * This method provides consistent selection rendering across different viewers
- * and owner draw implementations. It handles both focused and unfocused
- * selection states using themed colors from the ColorRegistry with appropriate
- * fallbacks.
- *
- *
- * @param event the erase event containing the widget, GC, and coordinates
- * @since 3.32
- */
- public static void drawSelection(Event event) {
- Control control = (Control) event.widget;
- GC gc = event.gc;
-
- final Color backgroundColor = getSelectionColor(
- control.isFocusControl() ? COLOR_SELECTION_BG_FOCUS : COLOR_SELECTION_BG_NO_FOCUS, event.display);
- final Color foregroundColor = getSelectionColor(
- control.isFocusControl() ? COLOR_SELECTION_FG_FOCUS : COLOR_SELECTION_FG_NO_FOCUS, event.display);
-
- gc.setBackground(backgroundColor);
- gc.setForeground(foregroundColor);
-
- int width = event.width;
- if (event.widget instanceof Scrollable scrollable) {
- width = scrollable.getClientArea().width;
- }
-
- gc.fillRectangle(15, event.y, width, event.height);
-
- // Remove SELECTED and BACKGROUND flags to prevent native drawing from
- // overwriting our custom colors
- event.detail &= ~(SWT.SELECTED | SWT.BACKGROUND);
-
- // GTK paints over the image so we need to redraw explicitly
- if (!(event.item instanceof TableItem item))
- return;
-
- int index = event.index;
- Image image = item.getImage(index);
-
- if (image == null)
- return;
+ public static Color getForegroundColor(boolean focused, Device device) {
+ return getSelectionColor(focused ? COLOR_SELECTION_FG_FOCUS : COLOR_SELECTION_FG_NO_FOCUS, device);
+ }
- Rectangle imageBounds = item.getImageBounds(index);
- Rectangle bounds = image.getBounds();
- 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);
+ public static Color getBackgroundColor(boolean focused, Device device) {
+ return getSelectionColor(focused ? COLOR_SELECTION_BG_FOCUS : COLOR_SELECTION_BG_NO_FOCUS, device);
}
- private static Color getSelectionColor(String key, org.eclipse.swt.graphics.Device device) {
+ public static Color getSelectionColor(String key, Device device) {
ColorRegistry registry = JFaceResources.getColorRegistry();
if (!registry.hasValueFor(key)) {
+
RGB systemColor = device.getSystemColor(idToColor(key)).getRGB();
+// RGB systemColor2 = getSystemColorForId(device, key);
+//
+// if (!systemColor.equals(systemColor2))
+// throw new RuntimeException("Something's fishy"); //$NON-NLS-1$
+
registry.put(key, systemColor);
}
return registry.get(key);
}
+ public static RGB getSystemColorForId(String id) {
+ return getSystemColorForId(Display.getDefault(), id);
+ }
+
+ private static RGB getSystemColorForId(Device device, String id) {
+ return device.getSystemColor(idToColor(id)).getRGB();
+ }
+
private static int idToColor(String id) {
return switch (id) {
case COLOR_SELECTION_BG_FOCUS -> SWT.COLOR_TITLE_BACKGROUND;
@@ -201,4 +153,100 @@ private static int idToColor(String id) {
};
}
-}
+ public static void addListenerToViewer(StructuredViewer viewer) {
+ Control control = viewer.getControl();
+ if (control.isDisposed() || isListenerRegistered(control)) {
+ return;
+ }
+
+ ColumnViewerSelectionColorListener listener = new ColumnViewerSelectionColorListener();
+ control.setData(LISTENER_KEY, listener);
+
+ // We need both phases
+ control.addListener(SWT.EraseItem, listener);
+ control.addListener(SWT.PaintItem, listener);
+ }
+
+ @Override
+ public void handleEvent(Event event) {
+ if (event.type == SWT.EraseItem) {
+ handleEraseItem(event);
+ } else if (event.type == SWT.PaintItem) {
+ handlePaintItem(event);
+ }
+ }
+
+ private void handleEraseItem(Event event) {
+ if ((event.detail & SWT.SELECTED) == 0)
+ return;
+ if (event.widget instanceof Control c && !c.isEnabled())
+ return;
+
+ // Your "other listeners" logic still applies, but note:
+ // TableOwnerDrawSupport is a different listener and will still run.
+ if (hasAdditionalEraseItemListeners(event))
+ return;
+
+ Control control = (Control) event.widget;
+ GC gc = event.gc;
+
+ Color bg = getBackgroundColor(control.isFocusControl(), event.display);
+ Color fg = getForegroundColor(control.isFocusControl(), event.display);
+
+ gc.setBackground(bg);
+ gc.setForeground(fg);
+
+ // (A) full-row
+ int rowWidth = (event.widget instanceof Scrollable s) ? s.getClientArea().width : event.width;
+ gc.fillRectangle(0, event.y, rowWidth, event.height);
+
+ // Prevent native selection drawing
+ // Do NOT clear SWT.BACKGROUND here unless you really want to suppress SWT
+ // background painting.
+ // (You *can* clear SWT.BACKGROUND if you see it overwriting your fill on a
+ // platform,
+ // but try without first.)
+ event.detail &= ~SWT.SELECTED;
+
+ }
+
+ public static void handlePaintItem(Event event) {
+ // We must not rely on event.detail & SWT.SELECTED because we cleared it above.
+ // Instead compute selection state from the widget.
+ if (!(event.widget instanceof org.eclipse.swt.widgets.Table table))
+ return;
+ if (!(event.item instanceof TableItem item))
+ return;
+
+ boolean isSelected = table.isSelected(table.indexOf(item));
+ if (!isSelected)
+ return; // only adjust painting for selected rows, otherwise leave default owner draw
+
+ GC gc = event.gc;
+
+ // Set the foreground color for selected text/icon painting, if needed
+ Color fg = getSelectionColor(table.isFocusControl() ? COLOR_SELECTION_FG_FOCUS : COLOR_SELECTION_FG_NO_FOCUS,
+ event.display);
+ gc.setForeground(fg);
+
+ // Paint the image explicitly (like TableOwnerDrawSupport does)
+ int column = event.index;
+ Image image = item.getImage(column);
+ if (image != null) {
+ Rectangle imageBounds = item.getImageBounds(column);
+ Rectangle src = image.getBounds();
+
+ int x = imageBounds.x + Math.max(0, (imageBounds.width - src.width) / 2);
+ int y = imageBounds.y + Math.max(0, (imageBounds.height - src.height) / 2);
+
+ gc.drawImage(image, x, y);
+ }
+
+ // Text painting:
+ // If TableOwnerDrawSupport is installed, it will paint the text itself.
+ // If you find text color is wrong on selected rows, you have two choices:
+ // 1) Adjust TableOwnerDrawSupport to respect gc foreground, or
+ // 2) Paint the text yourself here (requires computing text bounds and applying
+ // styles).
+ }
+}
\ No newline at end of file
From b921c1a39e51ead8ad699fcd29424b9dc01f5169 Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 19:33:23 +0100
Subject: [PATCH 11/26] Use the id the match the colors in the color factory
No need for parameters
---
.../CompletionProposalDrawSupport.java | 4 +-
.../ColumnViewerSelectionColorListener.java | 43 +++++--------------
.../ColumnViewerSelectionColorFactory.java | 20 ++-------
bundles/org.eclipse.ui/plugin.xml | 16 -------
4 files changed, 16 insertions(+), 67 deletions(-)
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java
index de11a5792cd3..dc8a9ba575d8 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java
@@ -59,7 +59,7 @@ public void handleEvent(Event event) {
if (event.type == SWT.EraseItem && isSelected) {
- final Color backgroundColor= ColumnViewerSelectionColorListener.getBackgroundColor(isSelected, event.display);
+ final Color backgroundColor= ColumnViewerSelectionColorListener.getBackgroundColor(event.display, isSelected);
event.gc.setBackground(backgroundColor);
final int width= (event.widget instanceof Scrollable s) ? s.getClientArea().width : event.width;
@@ -75,7 +75,7 @@ public void handleEvent(Event event) {
} else if (event.type == SWT.PaintItem) {
- final Color foregroundColor= ColumnViewerSelectionColorListener.getForegroundColor(isSelected, event.display);
+ final Color foregroundColor= ColumnViewerSelectionColorListener.getForegroundColor(event.display, isSelected);
event.gc.setForeground(foregroundColor);
// event.detail&= ~SWT.FOREGROUND;
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
index 693cf21fac89..1790df0de6fc 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
@@ -51,23 +51,6 @@
*/
public class ColumnViewerSelectionColorListener implements Listener {
- /**
- * Contains the values of the color definitions from the
- * plugin.xml.
- *
- * @implNote If some value doesn't match the exact name (String) inside the
- * plugin.xml or if some string from the xml is not
- * present here then
- * {@link ColumnViewerSelectionColorFactory#getSystemColorForId(ColorId)}
- * will not return what you expect.
- * @since 3.5
- *
- */
-// private static enum ColorId {
-// SELECTED_CELL_BACKGROUND, SELECTED_CELL_FOREGROUND, SELECTED_CELL_BACKGROUND_NO_FOCUS,
-// SELECTED_CELL_FOREGROUND_NO_FOCUS
-// }
-
private static final String LISTENER_KEY = "org.eclipse.jface.viewers.selection_color_listener"; //$NON-NLS-1$
private static final String OWNER_DRAW_LISTENER_KEY = "owner_draw_label_provider_listener"; //$NON-NLS-1$
@@ -110,25 +93,19 @@ private boolean hasAdditionalEraseItemListeners(Event event) {
.anyMatch(l -> l != ownerDrawListener);
}
- public static Color getForegroundColor(boolean focused, Device device) {
- return getSelectionColor(focused ? COLOR_SELECTION_FG_FOCUS : COLOR_SELECTION_FG_NO_FOCUS, device);
+ public static Color getForegroundColor(Device device, boolean focused) {
+ return getSelectionColor(device, focused ? COLOR_SELECTION_FG_FOCUS : COLOR_SELECTION_FG_NO_FOCUS);
}
- public static Color getBackgroundColor(boolean focused, Device device) {
- return getSelectionColor(focused ? COLOR_SELECTION_BG_FOCUS : COLOR_SELECTION_BG_NO_FOCUS, device);
+ public static Color getBackgroundColor(Device device, boolean focused) {
+ return getSelectionColor(device, focused ? COLOR_SELECTION_BG_FOCUS : COLOR_SELECTION_BG_NO_FOCUS);
}
- public static Color getSelectionColor(String key, Device device) {
+ private static Color getSelectionColor(Device device, String key) {
ColorRegistry registry = JFaceResources.getColorRegistry();
if (!registry.hasValueFor(key)) {
-
RGB systemColor = device.getSystemColor(idToColor(key)).getRGB();
-// RGB systemColor2 = getSystemColorForId(device, key);
-//
-// if (!systemColor.equals(systemColor2))
-// throw new RuntimeException("Something's fishy"); //$NON-NLS-1$
-
registry.put(key, systemColor);
}
@@ -190,8 +167,8 @@ private void handleEraseItem(Event event) {
Control control = (Control) event.widget;
GC gc = event.gc;
- Color bg = getBackgroundColor(control.isFocusControl(), event.display);
- Color fg = getForegroundColor(control.isFocusControl(), event.display);
+ Color bg = getBackgroundColor(event.display, control.isFocusControl());
+ Color fg = getForegroundColor(event.display, control.isFocusControl());
gc.setBackground(bg);
gc.setForeground(fg);
@@ -210,7 +187,7 @@ private void handleEraseItem(Event event) {
}
- public static void handlePaintItem(Event event) {
+ private void handlePaintItem(Event event) {
// We must not rely on event.detail & SWT.SELECTED because we cleared it above.
// Instead compute selection state from the widget.
if (!(event.widget instanceof org.eclipse.swt.widgets.Table table))
@@ -225,8 +202,8 @@ public static void handlePaintItem(Event event) {
GC gc = event.gc;
// Set the foreground color for selected text/icon painting, if needed
- Color fg = getSelectionColor(table.isFocusControl() ? COLOR_SELECTION_FG_FOCUS : COLOR_SELECTION_FG_NO_FOCUS,
- event.display);
+ Color fg = getSelectionColor(event.display,
+ table.isFocusControl() ? COLOR_SELECTION_FG_FOCUS : COLOR_SELECTION_FG_NO_FOCUS);
gc.setForeground(fg);
// Paint the image explicitly (like TableOwnerDrawSupport does)
diff --git a/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/themes/ColumnViewerSelectionColorFactory.java b/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/themes/ColumnViewerSelectionColorFactory.java
index 5b9875d0172f..f987cf7eafab 100644
--- a/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/themes/ColumnViewerSelectionColorFactory.java
+++ b/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/themes/ColumnViewerSelectionColorFactory.java
@@ -13,12 +13,10 @@
*******************************************************************************/
package org.eclipse.ui.internal.themes;
-import java.util.Hashtable;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExecutableExtension;
-import org.eclipse.swt.SWT;
+import org.eclipse.jface.viewers.ColumnViewerSelectionColorListener;
import org.eclipse.swt.graphics.RGB;
-import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.themes.IColorFactory;
/**
@@ -39,23 +37,13 @@ public class ColumnViewerSelectionColorFactory implements IColorFactory, IExecut
@Override
public RGB createColor() {
- return Display.getDefault().getSystemColor(idToColor(color)).getRGB();
- }
-
- private int idToColor(String id) {
- return switch (id) {
- case "SELECTED_CELL_BACKGROUND" -> SWT.COLOR_TITLE_BACKGROUND; //$NON-NLS-1$
- case "SELECTED_CELL_FOREGROUND" -> SWT.COLOR_WHITE; //$NON-NLS-1$
- case "SELECTED_CELL_BACKGROUND_NO_FOCUS" -> SWT.COLOR_TITLE_INACTIVE_BACKGROUND; //$NON-NLS-1$
- case "SELECTED_CELL_FOREGROUND_NO_FOCUS" -> SWT.COLOR_TITLE_INACTIVE_FOREGROUND; //$NON-NLS-1$
- default -> SWT.COLOR_BLACK;
- };
+ return ColumnViewerSelectionColorListener.getSystemColorForId(color);
}
@Override
public void setInitializationData(IConfigurationElement config, String propertyName, Object data) {
- if (data instanceof Hashtable table) {
- this.color = (String) table.get("color"); //$NON-NLS-1$
+ if ("colorDefinition".equals(config.getName())) { //$NON-NLS-1$
+ this.color = config.getAttribute("id"); //$NON-NLS-1$
}
}
}
diff --git a/bundles/org.eclipse.ui/plugin.xml b/bundles/org.eclipse.ui/plugin.xml
index ccddfd5116ed..6911af10c291 100644
--- a/bundles/org.eclipse.ui/plugin.xml
+++ b/bundles/org.eclipse.ui/plugin.xml
@@ -1749,10 +1749,6 @@
-
-
%Color.viewerSelectionBackgroundFocusedDesc
@@ -1765,10 +1761,6 @@
-
-
%Color.viewerSelectionForegroundFocusedDesc
@@ -1781,10 +1773,6 @@
-
-
%Color.viewerSelectionBackgroundNoFocusDesc
@@ -1797,10 +1785,6 @@
-
-
%Color.viewerSelectionForegroundNoFocusDesc
From 1ca6ba68736b10f8dfd0474313cac0f58ae6c1c2 Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 19:58:13 +0100
Subject: [PATCH 12/26] Adapt some comments and remove FQN (use import)
---
.../CompletionProposalDrawSupport.java | 15 +++++++--------
.../ColumnViewerSelectionColorListener.java | 13 ++++---------
2 files changed, 11 insertions(+), 17 deletions(-)
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java
index dc8a9ba575d8..91bc9f500df0 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java
@@ -36,6 +36,9 @@
*/
public class CompletionProposalDrawSupport implements Listener {
+ /**
+ * Delegate
+ */
private final TableOwnerDrawSupport fTableOwnerDrawSupport;
private CompletionProposalDrawSupport(Table table) {
@@ -44,6 +47,10 @@ private CompletionProposalDrawSupport(Table table) {
public static void install(Table table) {
CompletionProposalDrawSupport listener= new CompletionProposalDrawSupport(table);
+
+ // Since this listener delegates to TableOwnerDrawSupport right after doing
+ // its own stuff, we need to make sure to listen for all kind of events so
+ // that the delegation happens even after a No-Op.
table.addListener(SWT.Dispose, listener);
table.addListener(SWT.MeasureItem, listener);
table.addListener(SWT.EraseItem, listener);
@@ -66,19 +73,11 @@ public void handleEvent(Event event) {
event.gc.fillRectangle(0, event.y, width, event.height);
// Prevent native selection drawing
- // Do NOT clear SWT.BACKGROUND here unless you really want to suppress SWT
- // background painting.
- // (You *can* clear SWT.BACKGROUND if you see it overwriting your fill on a
- // platform,
- // but try without first.)
event.detail&= ~SWT.SELECTED;
} else if (event.type == SWT.PaintItem) {
-
final Color foregroundColor= ColumnViewerSelectionColorListener.getForegroundColor(event.display, isSelected);
event.gc.setForeground(foregroundColor);
-
-// event.detail&= ~SWT.FOREGROUND;
}
}
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
index 1790df0de6fc..3bc7cbc8019e 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
@@ -29,6 +29,7 @@
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Scrollable;
+import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
/**
@@ -159,8 +160,8 @@ private void handleEraseItem(Event event) {
if (event.widget instanceof Control c && !c.isEnabled())
return;
- // Your "other listeners" logic still applies, but note:
- // TableOwnerDrawSupport is a different listener and will still run.
+ // No need to process if there are more processors (other than
+ // TableOwnerDrawSupport) after this one.
if (hasAdditionalEraseItemListeners(event))
return;
@@ -173,16 +174,10 @@ private void handleEraseItem(Event event) {
gc.setBackground(bg);
gc.setForeground(fg);
- // (A) full-row
int rowWidth = (event.widget instanceof Scrollable s) ? s.getClientArea().width : event.width;
gc.fillRectangle(0, event.y, rowWidth, event.height);
// Prevent native selection drawing
- // Do NOT clear SWT.BACKGROUND here unless you really want to suppress SWT
- // background painting.
- // (You *can* clear SWT.BACKGROUND if you see it overwriting your fill on a
- // platform,
- // but try without first.)
event.detail &= ~SWT.SELECTED;
}
@@ -190,7 +185,7 @@ private void handleEraseItem(Event event) {
private void handlePaintItem(Event event) {
// We must not rely on event.detail & SWT.SELECTED because we cleared it above.
// Instead compute selection state from the widget.
- if (!(event.widget instanceof org.eclipse.swt.widgets.Table table))
+ if (!(event.widget instanceof Table table))
return;
if (!(event.item instanceof TableItem item))
return;
From b2683738e910c46936ab927962a56c7c02a7824a Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 20:00:08 +0100
Subject: [PATCH 13/26] Rename method to "install" to match similar methods in
other listeners
---
.../jface/viewers/ColumnViewerSelectionColorListener.java | 4 ++--
.../src/org/eclipse/jface/viewers/StructuredViewer.java | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
index 3bc7cbc8019e..56019a6afe1e 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
@@ -62,7 +62,7 @@ public class ColumnViewerSelectionColorListener implements Listener {
/**
* This class shouldn't be instantiated directly. Attach this listener to a
- * viewer via {@link #addListenerToViewer(StructuredViewer)} instead.
+ * viewer via {@link #install(StructuredViewer)} instead.
*/
private ColumnViewerSelectionColorListener() {
}
@@ -131,7 +131,7 @@ private static int idToColor(String id) {
};
}
- public static void addListenerToViewer(StructuredViewer viewer) {
+ public static void install(StructuredViewer viewer) {
Control control = viewer.getControl();
if (control.isDisposed() || isListenerRegistered(control)) {
return;
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/StructuredViewer.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/StructuredViewer.java
index 08dc398839e3..2f4774bfd3f6 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/StructuredViewer.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/StructuredViewer.java
@@ -1210,7 +1210,7 @@ public void widgetDefaultSelected(SelectionEvent e) {
});
handler.addPostSelectionListener(widgetSelectedAdapter(this::handlePostSelect));
handler.addOpenListener(StructuredViewer.this::handleOpen);
- ColumnViewerSelectionColorListener.addListenerToViewer(this);
+ ColumnViewerSelectionColorListener.install(this);
}
/**
From 81f9cd0878d7f79c2340a580aea06e8dfcdde739 Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 20:01:20 +0100
Subject: [PATCH 14/26] Move method up
---
.../ColumnViewerSelectionColorListener.java | 28 +++++++++----------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
index 56019a6afe1e..4bb5fc1aba68 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
@@ -67,6 +67,20 @@ public class ColumnViewerSelectionColorListener implements Listener {
private ColumnViewerSelectionColorListener() {
}
+ public static void install(StructuredViewer viewer) {
+ Control control = viewer.getControl();
+ if (control.isDisposed() || isListenerRegistered(control)) {
+ return;
+ }
+
+ ColumnViewerSelectionColorListener listener = new ColumnViewerSelectionColorListener();
+ control.setData(LISTENER_KEY, listener);
+
+ // We need both phases
+ control.addListener(SWT.EraseItem, listener);
+ control.addListener(SWT.PaintItem, listener);
+ }
+
private static boolean isListenerRegistered(Control control) {
return control.getData(LISTENER_KEY) != null;
}
@@ -131,20 +145,6 @@ private static int idToColor(String id) {
};
}
- public static void install(StructuredViewer viewer) {
- Control control = viewer.getControl();
- if (control.isDisposed() || isListenerRegistered(control)) {
- return;
- }
-
- ColumnViewerSelectionColorListener listener = new ColumnViewerSelectionColorListener();
- control.setData(LISTENER_KEY, listener);
-
- // We need both phases
- control.addListener(SWT.EraseItem, listener);
- control.addListener(SWT.PaintItem, listener);
- }
-
@Override
public void handleEvent(Event event) {
if (event.type == SWT.EraseItem) {
From 0838f15858e9e45d781cc838eddec877a46030f0 Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 20:02:46 +0100
Subject: [PATCH 15/26] Extract private method
---
.../jface/viewers/ColumnViewerSelectionColorListener.java | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
index 4bb5fc1aba68..c5b249cffb33 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
@@ -74,7 +74,7 @@ public static void install(StructuredViewer viewer) {
}
ColumnViewerSelectionColorListener listener = new ColumnViewerSelectionColorListener();
- control.setData(LISTENER_KEY, listener);
+ registerListener(control, listener);
// We need both phases
control.addListener(SWT.EraseItem, listener);
@@ -85,6 +85,10 @@ private static boolean isListenerRegistered(Control control) {
return control.getData(LISTENER_KEY) != null;
}
+ private static void registerListener(Control control, ColumnViewerSelectionColorListener listener) {
+ control.setData(LISTENER_KEY, listener);
+ }
+
/**
* Checks if additional EraseItem listeners were registered after this listener
* that are NOT the OwnerDrawListener. This allows user code to override the
From 172eb01c7758daa9b9a662ba12d00d0d0a52d6fc Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 20:29:01 +0100
Subject: [PATCH 16/26] Use private method in
ColumnViewerSelectionColorListener
In order to avoid code duplication.
Also add small JavaDoc
---
.../jface/viewers/ColumnViewerSelectionColorListener.java | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
index c5b249cffb33..40adac1cbf94 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
@@ -120,11 +120,15 @@ public static Color getBackgroundColor(Device device, boolean focused) {
return getSelectionColor(device, focused ? COLOR_SELECTION_BG_FOCUS : COLOR_SELECTION_BG_NO_FOCUS);
}
+ /**
+ * @return either a color set via preferences or the system color for the given
+ * key.
+ */
private static Color getSelectionColor(Device device, String key) {
ColorRegistry registry = JFaceResources.getColorRegistry();
if (!registry.hasValueFor(key)) {
- RGB systemColor = device.getSystemColor(idToColor(key)).getRGB();
+ RGB systemColor = getSystemColorForId(device, key);
registry.put(key, systemColor);
}
From 28563b5969ff70be238b88092423e39f3339407f Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 20:34:23 +0100
Subject: [PATCH 17/26] Move CompletionDrawSupport to parent package.
This way I can reduce the visibility of the constructor in
TableOwnerDrawSupport to default and avoid exposing more (internal) API
surface than strictly necessary.
---
.../{contentassist => }/CompletionProposalDrawSupport.java | 3 +--
.../org/eclipse/jface/internal/text/TableOwnerDrawSupport.java | 2 +-
.../text/link/contentassist/CompletionProposalPopup2.java | 2 +-
.../jface/text/contentassist/CompletionProposalPopup.java | 2 +-
4 files changed, 4 insertions(+), 5 deletions(-)
rename bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/{contentassist => }/CompletionProposalDrawSupport.java (96%)
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/CompletionProposalDrawSupport.java
similarity index 96%
rename from bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java
rename to bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/CompletionProposalDrawSupport.java
index 91bc9f500df0..d6c4fb9a939e 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/contentassist/CompletionProposalDrawSupport.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/CompletionProposalDrawSupport.java
@@ -11,7 +11,7 @@
* Contributors:
* SAP SE - initial API and implementation
*******************************************************************************/
-package org.eclipse.jface.internal.text.contentassist;
+package org.eclipse.jface.internal.text;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
@@ -21,7 +21,6 @@
import org.eclipse.swt.widgets.Scrollable;
import org.eclipse.swt.widgets.Table;
-import org.eclipse.jface.internal.text.TableOwnerDrawSupport;
import org.eclipse.jface.viewers.ColumnViewerSelectionColorListener;
/**
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java
index 343f17864e81..166a6c7d7a46 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java
@@ -70,7 +70,7 @@ private static StyleRange[] getStyledRanges(TableItem item, int column) {
return (StyleRange[])item.getData(STYLED_RANGES_KEY + column);
}
- public TableOwnerDrawSupport(Table table) {
+ TableOwnerDrawSupport(Table table) {
int orientation= table.getStyle() & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
fSharedLayout= new TextLayout(table.getDisplay());
fSharedLayout.setOrientation(orientation);
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/link/contentassist/CompletionProposalPopup2.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/link/contentassist/CompletionProposalPopup2.java
index 35306f2d4303..6316dcd60514 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/link/contentassist/CompletionProposalPopup2.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/link/contentassist/CompletionProposalPopup2.java
@@ -39,8 +39,8 @@
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.jface.internal.text.CompletionProposalDrawSupport;
import org.eclipse.jface.internal.text.TableOwnerDrawSupport;
-import org.eclipse.jface.internal.text.contentassist.CompletionProposalDrawSupport;
import org.eclipse.jface.preference.JFacePreferences;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.JFaceColors;
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java
index 661228369bd9..af29dcbba625 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java
@@ -77,9 +77,9 @@
import org.eclipse.jface.bindings.keys.KeySequence;
import org.eclipse.jface.bindings.keys.SWTKeySupport;
import org.eclipse.jface.contentassist.IContentAssistSubjectControl;
+import org.eclipse.jface.internal.text.CompletionProposalDrawSupport;
import org.eclipse.jface.internal.text.InformationControlReplacer;
import org.eclipse.jface.internal.text.TableOwnerDrawSupport;
-import org.eclipse.jface.internal.text.contentassist.CompletionProposalDrawSupport;
import org.eclipse.jface.preference.JFacePreferences;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.jface.resource.JFaceResources;
From 521271e7f783b1cafb1a3a9f3bcc2a77b65555aa Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 20:38:42 +0100
Subject: [PATCH 18/26] Remove the install method from TableOwnerDrawSupport
The method is not used anymore and the listener has been replaced by
CompletionProposalDrawSupport, which adds its own functionality and then
delegates to TableOwnerDrawSupport.
---
.../jface/internal/text/TableOwnerDrawSupport.java | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java
index 166a6c7d7a46..219d080a3909 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/TableOwnerDrawSupport.java
@@ -27,7 +27,9 @@
/**
- * Adds owner draw support for tables.
+ * Adds owner draw support for tables.
+ *
+ * It has been replaced by {@link CompletionProposalDrawSupport} in 2026-06.
*
* @since 3.4
*/
@@ -40,14 +42,6 @@ public class TableOwnerDrawSupport implements Listener {
private int fDeltaOfLastMeasure;
- public static void install(Table table) {
- TableOwnerDrawSupport listener= new TableOwnerDrawSupport(table);
- table.addListener(SWT.Dispose, listener);
- table.addListener(SWT.MeasureItem, listener);
- table.addListener(SWT.EraseItem, listener);
- table.addListener(SWT.PaintItem, listener);
- }
-
/**
* Stores the styled ranges in the given table item.
*
From ef799cc1c75899a5ce9bff0837de94eb265d3711 Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 20:49:50 +0100
Subject: [PATCH 19/26] Rename public methods in
ColumnViewerSelectionColorListener
And also add JavaDocs to them instead of documenting the private method.
---
.../text/CompletionProposalDrawSupport.java | 4 +--
.../ColumnViewerSelectionColorListener.java | 30 ++++++++++++++-----
2 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/CompletionProposalDrawSupport.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/CompletionProposalDrawSupport.java
index d6c4fb9a939e..3ac82ef07dd9 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/CompletionProposalDrawSupport.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/CompletionProposalDrawSupport.java
@@ -65,7 +65,7 @@ public void handleEvent(Event event) {
if (event.type == SWT.EraseItem && isSelected) {
- final Color backgroundColor= ColumnViewerSelectionColorListener.getBackgroundColor(event.display, isSelected);
+ final Color backgroundColor= ColumnViewerSelectionColorListener.getSelectionBackgroundColor(event.display, isSelected);
event.gc.setBackground(backgroundColor);
final int width= (event.widget instanceof Scrollable s) ? s.getClientArea().width : event.width;
@@ -75,7 +75,7 @@ public void handleEvent(Event event) {
event.detail&= ~SWT.SELECTED;
} else if (event.type == SWT.PaintItem) {
- final Color foregroundColor= ColumnViewerSelectionColorListener.getForegroundColor(event.display, isSelected);
+ final Color foregroundColor= ColumnViewerSelectionColorListener.getSelectionForegroundColor(event.display, isSelected);
event.gc.setForeground(foregroundColor);
}
}
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
index 40adac1cbf94..2f3e9980a922 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
@@ -112,18 +112,32 @@ private boolean hasAdditionalEraseItemListeners(Event event) {
.anyMatch(l -> l != ownerDrawListener);
}
- public static Color getForegroundColor(Device device, boolean focused) {
+ /**
+ * Gets the foreground color for a selected cell or item in a viewer.
+ *
+ * @param device The device to get the system color from (in case there is no
+ * color set in the preferences)
+ * @param focused Whether or not the control that contains the cell or item is
+ * currently focused.
+ * @return either a color set via preferences or the default system color.
+ */
+ public static Color getSelectionForegroundColor(Device device, boolean focused) {
return getSelectionColor(device, focused ? COLOR_SELECTION_FG_FOCUS : COLOR_SELECTION_FG_NO_FOCUS);
}
- public static Color getBackgroundColor(Device device, boolean focused) {
+ /**
+ * Gets the background color for a selected cell or item in a viewer.
+ *
+ * @param device The device to get the system color from (in case there is no
+ * color set in the preferences)
+ * @param focused Whether or not the control that contains the cell or item is
+ * currently focused.
+ * @return either a color set via preferences or the default system color.
+ */
+ public static Color getSelectionBackgroundColor(Device device, boolean focused) {
return getSelectionColor(device, focused ? COLOR_SELECTION_BG_FOCUS : COLOR_SELECTION_BG_NO_FOCUS);
}
- /**
- * @return either a color set via preferences or the system color for the given
- * key.
- */
private static Color getSelectionColor(Device device, String key) {
ColorRegistry registry = JFaceResources.getColorRegistry();
@@ -176,8 +190,8 @@ private void handleEraseItem(Event event) {
Control control = (Control) event.widget;
GC gc = event.gc;
- Color bg = getBackgroundColor(event.display, control.isFocusControl());
- Color fg = getForegroundColor(event.display, control.isFocusControl());
+ Color bg = getSelectionBackgroundColor(event.display, control.isFocusControl());
+ Color fg = getSelectionForegroundColor(event.display, control.isFocusControl());
gc.setBackground(bg);
gc.setForeground(fg);
From 632a2018a26ce43ec29a654e4af0dd9b706000fb Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 21:05:39 +0100
Subject: [PATCH 20/26] Make constant in OwnerDrawLabelProvider more visible
and use it
Use it in ColumnViewerSelectionColorListener instead of duplicating it.
---
.../jface/viewers/ColumnViewerSelectionColorListener.java | 3 +--
.../src/org/eclipse/jface/viewers/OwnerDrawLabelProvider.java | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
index 2f3e9980a922..010c50900cbb 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
@@ -53,7 +53,6 @@
public class ColumnViewerSelectionColorListener implements Listener {
private static final String LISTENER_KEY = "org.eclipse.jface.viewers.selection_color_listener"; //$NON-NLS-1$
- private static final String OWNER_DRAW_LISTENER_KEY = "owner_draw_label_provider_listener"; //$NON-NLS-1$
private static final String COLOR_SELECTION_BG_FOCUS = "org.eclipse.jface.SELECTION_BACKGROUND_FOCUSED"; //$NON-NLS-1$
private static final String COLOR_SELECTION_FG_FOCUS = "org.eclipse.jface.SELECTION_FOREGROUND_FOCUSED"; //$NON-NLS-1$
@@ -106,7 +105,7 @@ private boolean hasAdditionalEraseItemListeners(Event event) {
}
Listener[] listeners = control.getListeners(SWT.EraseItem);
- Object ownerDrawListener = control.getData(OWNER_DRAW_LISTENER_KEY);
+ Object ownerDrawListener = control.getData(OwnerDrawLabelProvider.OWNER_DRAW_LABEL_PROVIDER_LISTENER);
return Arrays.stream(listeners).dropWhile(l -> l != this) // ignore listeners before "this"
.dropWhile(l -> l == this) // also ignore "this"
.anyMatch(l -> l != ownerDrawListener);
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider.java
index e240ab7393df..5a7eebbcb091 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider.java
@@ -68,7 +68,7 @@ public void handleEvent(Event event) {
}
}
- private static final String OWNER_DRAW_LABEL_PROVIDER_LISTENER = "owner_draw_label_provider_listener"; //$NON-NLS-1$
+ static final String OWNER_DRAW_LABEL_PROVIDER_LISTENER = "owner_draw_label_provider_listener"; //$NON-NLS-1$
/**
* Set up the owner draw callbacks for the viewer.
From 0ec8982f9324a972623d9e6f773c83d6fe93cd2b Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 21:13:50 +0100
Subject: [PATCH 21/26] Rename private method in
ColumnViewerSelectionColorListener
---
.../jface/viewers/ColumnViewerSelectionColorListener.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
index 010c50900cbb..f7b07fa93d1d 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
@@ -153,10 +153,10 @@ public static RGB getSystemColorForId(String id) {
}
private static RGB getSystemColorForId(Device device, String id) {
- return device.getSystemColor(idToColor(id)).getRGB();
+ return device.getSystemColor(idToDefaultSWTSystemColor(id)).getRGB();
}
- private static int idToColor(String id) {
+ private static int idToDefaultSWTSystemColor(String id) {
return switch (id) {
case COLOR_SELECTION_BG_FOCUS -> SWT.COLOR_TITLE_BACKGROUND;
case COLOR_SELECTION_FG_FOCUS -> SWT.COLOR_WHITE;
From d409d11bd3326d563ee164dc5b27f49777ed568d Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 21:17:07 +0100
Subject: [PATCH 22/26] Use method getSelectionForegroundColor to avoid code
duplication
---
.../jface/viewers/ColumnViewerSelectionColorListener.java | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
index f7b07fa93d1d..b9bb5db41a03 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
@@ -218,8 +218,7 @@ private void handlePaintItem(Event event) {
GC gc = event.gc;
// Set the foreground color for selected text/icon painting, if needed
- Color fg = getSelectionColor(event.display,
- table.isFocusControl() ? COLOR_SELECTION_FG_FOCUS : COLOR_SELECTION_FG_NO_FOCUS);
+ Color fg = getSelectionForegroundColor(event.display, table.isFocusControl());
gc.setForeground(fg);
// Paint the image explicitly (like TableOwnerDrawSupport does)
From 10907785c15c978766c11cee1cf3efa158471881 Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 21:21:56 +0100
Subject: [PATCH 23/26] Do not set the foreground color in handleEraseItem.
Erasing only needs to prepare the background so the foreground color has
nothing to do with it. It is during the painting phase that the text
(and also the icons) are drawn so setting the foreground color needs to
be done only in the method handlePaintItem.
---
.../jface/viewers/ColumnViewerSelectionColorListener.java | 3 ---
1 file changed, 3 deletions(-)
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
index b9bb5db41a03..24e531705354 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
@@ -190,17 +190,14 @@ private void handleEraseItem(Event event) {
GC gc = event.gc;
Color bg = getSelectionBackgroundColor(event.display, control.isFocusControl());
- Color fg = getSelectionForegroundColor(event.display, control.isFocusControl());
gc.setBackground(bg);
- gc.setForeground(fg);
int rowWidth = (event.widget instanceof Scrollable s) ? s.getClientArea().width : event.width;
gc.fillRectangle(0, event.y, rowWidth, event.height);
// Prevent native selection drawing
event.detail &= ~SWT.SELECTED;
-
}
private void handlePaintItem(Event event) {
From 27357b4cdfab1657e2a2555d9ed40d5becbe4ce2 Mon Sep 17 00:00:00 2001
From: Eclipse Platform Bot
Date: Fri, 27 Feb 2026 20:32:13 +0000
Subject: [PATCH 24/26] Version bump(s) for 4.40 stream
---
bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF | 2 +-
bundles/org.eclipse.jface/META-INF/MANIFEST.MF | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF b/bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF
index 585219082466..74f698f50f07 100644
--- a/bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jface.text
-Bundle-Version: 3.30.0.qualifier
+Bundle-Version: 3.30.100.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package:
diff --git a/bundles/org.eclipse.jface/META-INF/MANIFEST.MF b/bundles/org.eclipse.jface/META-INF/MANIFEST.MF
index 0a2620fd7113..a28edbfee326 100644
--- a/bundles/org.eclipse.jface/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.jface/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jface;singleton:=true
-Bundle-Version: 3.39.0.qualifier
+Bundle-Version: 3.39.100.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package: org.eclipse.jface,
From da2d6fda6a0496ed795689c48493a984165a3971 Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 22:07:54 +0100
Subject: [PATCH 25/26] Bump minor version of org.eclipse.jface
---
bundles/org.eclipse.jface/META-INF/MANIFEST.MF | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bundles/org.eclipse.jface/META-INF/MANIFEST.MF b/bundles/org.eclipse.jface/META-INF/MANIFEST.MF
index a28edbfee326..a627f5c17061 100644
--- a/bundles/org.eclipse.jface/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.jface/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jface;singleton:=true
-Bundle-Version: 3.39.100.qualifier
+Bundle-Version: 3.40.0.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package: org.eclipse.jface,
From 8763def0ae0125b923f50bd41d52eac48a0f5f18 Mon Sep 17 00:00:00 2001
From: Federico Jeanne
Date: Fri, 27 Feb 2026 22:20:22 +0100
Subject: [PATCH 26/26] Bump version in @since
---
.../jface/viewers/ColumnViewerSelectionColorListener.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
index 24e531705354..19acd0fc8cc8 100644
--- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
+++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewerSelectionColorListener.java
@@ -48,7 +48,7 @@
* @see org.eclipse.jface.viewers.OwnerDrawLabelProvider
* @see org.eclipse.jface.viewers.StyledCellLabelProvider
* @see org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter
- * @since 3.39
+ * @since 3.40
*/
public class ColumnViewerSelectionColorListener implements Listener {