Skip to content

Commit ccb3003

Browse files
committed
Style workspace selection dialog with default theme setting
When the user's preferred theme is dark, apply dark styling to the workspace selection dialog before the workbench and its ThemeEngine start up. This ensures the dialog matches the IDE theme even at first launch. Styling is applied in two passes: - A display-level SWT.Show listener as an early pass when the shell first appears. - In createContents() after all dialog controls are constructed, to catch dynamically created widgets not yet present at SWT.Show time. Color objects use the modern display-free Color(r, g, b) constructor rather than the deprecated Color(Display, r, g, b) form.
1 parent f22f75c commit ccb3003

7 files changed

Lines changed: 133 additions & 15 deletions

File tree

bundles/org.eclipse.e4.ui.css.swt.theme/META-INF/MANIFEST.MF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Bundle-Name: %pluginName
66
Bundle-Vendor: %providerName
77
Bundle-Localization: plugin
88
Bundle-RequiredExecutionEnvironment: JavaSE-21
9-
Require-Bundle: org.eclipse.swt;bundle-version="[3.133.0,4.0.0)",
9+
Require-Bundle: org.eclipse.swt;bundle-version="[3.134.0,4.0.0)",
1010
org.eclipse.e4.ui.css.swt;bundle-version="0.13.100",
1111
org.eclipse.e4.ui.css.core;bundle-version="0.12.200",
1212
org.eclipse.core.runtime;bundle-version="[3.29.0,4.0.0)"

bundles/org.eclipse.e4.ui.css.swt.theme/src/org/eclipse/e4/ui/css/swt/internal/theme/ThemeEngine.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,9 @@ public void setTheme(ITheme theme, boolean restore, boolean force) {
510510
ThemeEngineManager.logError(e.getMessage(), e);
511511
}
512512
}
513+
boolean isDark = theme.getId().contains("dark"); //$NON-NLS-1$
514+
display.setDarkThemePreferred(isDark);
515+
513516
sendThemeChangeEvent(restore);
514517

515518
for (CSSEngine engine : cssEngines) {

bundles/org.eclipse.ui.ide.application/META-INF/MANIFEST.MF

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.21.0,4.0.0)",
1818
org.eclipse.e4.core.di.extensions,
1919
org.eclipse.e4.core.services;bundle-version="2.4.0",
2020
org.eclipse.e4.core.contexts;bundle-version="[1.12.0,2.0.0)",
21+
org.eclipse.ui.forms,
2122
org.eclipse.urischeme;bundle-version="[1.3.0,2.0.0)",
2223
org.eclipse.e4.ui.di
2324
Export-Package: org.eclipse.ui.internal.ide.application;x-internal:=true,

bundles/org.eclipse.ui.ide.application/src/org/eclipse/ui/internal/ide/application/IDEApplication.java

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,15 @@
3636

3737
import org.eclipse.core.runtime.IConfigurationElement;
3838
import org.eclipse.core.runtime.IExecutableExtension;
39+
import org.eclipse.core.runtime.IProduct;
3940
import org.eclipse.core.runtime.IStatus;
4041
import org.eclipse.core.runtime.OperationCanceledException;
4142
import org.eclipse.core.runtime.Platform;
4243
import org.eclipse.core.runtime.Status;
4344
import org.eclipse.core.runtime.jobs.Job;
4445
import org.eclipse.core.runtime.preferences.ConfigurationScope;
46+
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
47+
import org.eclipse.core.runtime.preferences.UserScope;
4548
import org.eclipse.equinox.app.IApplication;
4649
import org.eclipse.equinox.app.IApplicationContext;
4750
import org.eclipse.jface.dialogs.IDialogConstants;
@@ -52,14 +55,18 @@
5255
import org.eclipse.osgi.service.datalocation.Location;
5356
import org.eclipse.osgi.util.NLS;
5457
import org.eclipse.swt.SWT;
58+
import org.eclipse.swt.graphics.Color;
5559
import org.eclipse.swt.layout.FillLayout;
5660
import org.eclipse.swt.widgets.Composite;
5761
import org.eclipse.swt.widgets.Control;
5862
import org.eclipse.swt.widgets.Display;
5963
import org.eclipse.swt.widgets.Label;
64+
import org.eclipse.swt.widgets.Link;
65+
import org.eclipse.swt.widgets.Listener;
6066
import org.eclipse.swt.widgets.Shell;
6167
import org.eclipse.ui.IWorkbench;
6268
import org.eclipse.ui.PlatformUI;
69+
import org.eclipse.ui.forms.widgets.ExpandableComposite;
6370
import org.eclipse.ui.internal.Workbench;
6471
import org.eclipse.ui.internal.WorkbenchPlugin;
6572
import org.eclipse.ui.internal.WorkspaceLock;
@@ -94,6 +101,9 @@ public class IDEApplication implements IApplication, IExecutableExtension {
94101

95102
private static final String USER_NAME = "user.name"; //$NON-NLS-1$
96103

104+
private boolean isDark;
105+
private Listener darkThemeShowListener;
106+
97107
// Use the branding plug-in of the platform feature since this is most likely
98108
// to change on an update of the IDE.
99109
private static final String WORKSPACE_CHECK_REFERENCE_BUNDLE_NAME = "org.eclipse.platform"; //$NON-NLS-1$
@@ -145,6 +155,9 @@ public Object start(IApplicationContext appContext) throws Exception {
145155
Job.getJobManager().suspend();
146156

147157
Display display = createDisplay();
158+
159+
initializeDefaultTheme(display);
160+
148161
// processor must be created before we start event loop
149162
DelayedEventsProcessor processor = new DelayedEventsProcessor(display);
150163

@@ -167,6 +180,10 @@ public Object start(IApplicationContext appContext) throws Exception {
167180
return instanceLocationCheck;
168181
}
169182

183+
// Reset early dark theme styling before the workbench starts;
184+
// the ThemeEngine will apply the correct theme from here on.
185+
resetEarlyDarkTheme(display);
186+
170187
// create the workbench with this advisor and run it until it exits
171188
// N.B. createWorkbench remembers the advisor, and also registers
172189
// the workbench globally so that all UI plug-ins can find it using
@@ -587,6 +604,14 @@ protected Shell getParentShell() {
587604
return null;
588605
}
589606

607+
@Override
608+
protected Control createContents(Composite parent) {
609+
Control contents = super.createContents(parent);
610+
if (isDark) {
611+
applyDarkStyles(getShell());
612+
}
613+
return contents;
614+
}
590615
}.prompt(force);
591616
}
592617

@@ -852,6 +877,86 @@ protected static Version toMajorMinorVersion(Version version) {
852877
return new Version(version.getMajor(), version.getMinor(), 0);
853878
}
854879

880+
protected void initializeDefaultTheme(Display display) {
881+
IEclipsePreferences themeNode = UserScope.INSTANCE.getNode("org.eclipse.e4.ui.css.swt.theme"); //$NON-NLS-1$
882+
String productOrAppId = getProductOrApplicationId();
883+
String defaultThemeId = null;
884+
if (productOrAppId != null) {
885+
defaultThemeId = themeNode.node(productOrAppId).get("themeid", null); //$NON-NLS-1$
886+
}
887+
if (defaultThemeId == null) {
888+
defaultThemeId = themeNode.get("themeid", null); //$NON-NLS-1$
889+
}
890+
isDark = defaultThemeId != null && defaultThemeId.contains("dark"); //$NON-NLS-1$
891+
if (isDark) {
892+
display.setDarkThemePreferred(true);
893+
darkThemeShowListener = event -> {
894+
if (event.widget instanceof Shell shell) {
895+
applyDarkStyles(shell);
896+
}
897+
};
898+
display.addListener(SWT.Show, darkThemeShowListener);
899+
}
900+
}
901+
902+
/**
903+
* Removes the early dark theme styling applied for the workspace selection
904+
* dialog. Must be called before the workbench starts so the ThemeEngine can
905+
* manage the theme without interference.
906+
*/
907+
protected void resetEarlyDarkTheme(Display display) {
908+
if (darkThemeShowListener != null) {
909+
display.removeListener(SWT.Show, darkThemeShowListener);
910+
darkThemeShowListener = null;
911+
}
912+
if (isDark) {
913+
display.setDarkThemePreferred(false);
914+
}
915+
}
916+
917+
/**
918+
* Returns the product ID if a product is configured, otherwise falls back to
919+
* the application ID from the system property. Returns {@code null} if neither
920+
* is available.
921+
*/
922+
private static String getProductOrApplicationId() {
923+
IProduct product = Platform.getProduct();
924+
if (product != null) {
925+
return product.getId();
926+
}
927+
return System.getProperty("eclipse.application"); //$NON-NLS-1$
928+
}
929+
930+
private void applyDarkStyles(Shell shell) {
931+
Color bg = new Color(72, 72, 76); // #48484c
932+
Color fg = new Color(238, 238, 238); // #eeeeee
933+
Color linkColor = new Color(111, 197, 238); // #6FC5EE
934+
shell.setBackground(bg);
935+
shell.setForeground(fg);
936+
applyStylesRecursive(shell, bg, fg, linkColor);
937+
}
938+
939+
private void applyStylesRecursive(Control control, Color bg, Color fg, Color linkColor) {
940+
control.setBackground(bg);
941+
if (control instanceof Link link) {
942+
link.setLinkForeground(linkColor);
943+
} else {
944+
control.setForeground(fg);
945+
946+
}
947+
948+
if (control instanceof ExpandableComposite expandable) {
949+
expandable.setTitleBarForeground(fg);
950+
expandable.setToggleColor(fg);
951+
expandable.setActiveToggleColor(fg);
952+
}
953+
if (control instanceof Composite composite) {
954+
for (Control child : composite.getChildren()) {
955+
applyStylesRecursive(child, bg, fg, linkColor);
956+
}
957+
}
958+
}
959+
855960
@Override
856961
public void stop() {
857962
final IWorkbench workbench = PlatformUI.getWorkbench();

bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/ChooseWorkspaceDialog.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.eclipse.jface.dialogs.IDialogConstants;
4040
import org.eclipse.jface.dialogs.IDialogSettings;
4141
import org.eclipse.jface.dialogs.TitleAreaDialog;
42+
import org.eclipse.jface.resource.JFaceColors;
4243
import org.eclipse.jface.util.Geometry;
4344
import org.eclipse.jface.window.Window;
4445
import org.eclipse.osgi.util.NLS;
@@ -319,6 +320,10 @@ private void createRecentWorkspacesComposite(final Composite composite) {
319320
recentWorkspacesForm.getBody().setLayout(new GridLayout());
320321
ExpandableComposite recentWorkspacesExpandable = toolkit.createExpandableComposite(recentWorkspacesForm.getBody(),
321322
ExpandableComposite.TWISTIE);
323+
recentWorkspacesExpandable.setTitleBarForeground(composite.getForeground());
324+
recentWorkspacesExpandable.setForeground(composite.getForeground());
325+
recentWorkspacesExpandable.setToggleColor(composite.getForeground());
326+
recentWorkspacesExpandable.setActiveToggleColor(composite.getForeground());
322327
recentWorkspacesForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
323328
recentWorkspacesExpandable.setBackground(composite.getBackground());
324329
recentWorkspacesExpandable.setText(IDEWorkbenchMessages.ChooseWorkspaceDialog_recentWorkspaces);
@@ -352,6 +357,7 @@ public void expansionStateChanged(ExpansionEvent e) {
352357
final String recentWorkspace = uniqueWorkspaceEntry.getValue();
353358

354359
Link link = new Link(panel, SWT.WRAP);
360+
link.setForeground(JFaceColors.getHyperlinkText(composite.getDisplay()));
355361
link.setLayoutData(new RowData(SWT.DEFAULT, SWT.DEFAULT));
356362
link.setText("<a>" + uniqueWorkspaceEntry.getKey() + "</a>"); //$NON-NLS-1$ //$NON-NLS-2$
357363
link.setToolTipText(recentWorkspace);

bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/ChooseWorkspaceWithSettingsDialog.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ private void createSettingsControls(Composite workArea) {
128128

129129
copySettingsExpandable.setText(IDEWorkbenchMessages.ChooseWorkspaceWithSettingsDialog_SettingsGroupName);
130130
copySettingsExpandable.setBackground(workArea.getBackground());
131+
copySettingsExpandable.setTitleBarForeground(workArea.getForeground());
132+
copySettingsExpandable.setToggleColor(workArea.getForeground());
133+
copySettingsExpandable.setActiveToggleColor(workArea.getForeground());
131134
copySettingsExpandable.setLayout(new GridLayout());
132135
copySettingsExpandable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
133136
copySettingsExpandable.addExpansionListener(new IExpansionListener() {

tests/org.eclipse.ui.tests.forms/forms/org/eclipse/ui/tests/forms/util/FlatLookTest.java

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public void testFormHeadingFlatLook() {
6060
FormHeading head = (FormHeading) form.getHead();
6161
head.setSize(100, 50);
6262

63-
Color color = new Color(display, 255, 0, 0);
63+
Color color = new Color(255, 0, 0);
6464
Color[] identicalColors = new Color[] { color, color };
6565
int[] percents = new int[] { 100 };
6666

@@ -74,7 +74,7 @@ public void testFormHeadingFlatLook() {
7474
});
7575

7676
// Verify with distinct colors as well to ensure both paths work
77-
Color color2 = new Color(display, 0, 0, 255);
77+
Color color2 = new Color(0, 0, 255);
7878
Color[] distinctColors = new Color[] { color, color2 };
7979
head.setTextBackground(distinctColors, percents, true);
8080

@@ -90,7 +90,7 @@ public void testFlatLookUsesSolidBackground() {
9090
FormHeading head = (FormHeading) form.getHead();
9191
head.setSize(100, 50);
9292

93-
Color color = new Color(display, 200, 100, 50);
93+
Color color = new Color(200, 100, 50);
9494
head.setTextBackground(new Color[] { color, color }, new int[] { 100 }, true);
9595

9696
// Flat look: identical colors should use solid background, no gradient
@@ -107,8 +107,8 @@ public void testGradientLookUsesBackgroundImage() {
107107
FormHeading head = (FormHeading) form.getHead();
108108
head.setSize(100, 50);
109109

110-
Color color1 = new Color(display, 255, 0, 0);
111-
Color color2 = new Color(display, 0, 0, 255);
110+
Color color1 = new Color(255, 0, 0);
111+
Color color2 = new Color(0, 0, 255);
112112
head.setTextBackground(new Color[] { color1, color2 }, new int[] { 100 }, true);
113113

114114
// Gradient look: distinct colors should generate a background image
@@ -123,13 +123,13 @@ public void testSwitchFromGradientToFlat() {
123123
head.setSize(100, 50);
124124

125125
// First set a real gradient
126-
Color color1 = new Color(display, 255, 0, 0);
127-
Color color2 = new Color(display, 0, 0, 255);
126+
Color color1 = new Color(255, 0, 0);
127+
Color color2 = new Color(0, 0, 255);
128128
head.setTextBackground(new Color[] { color1, color2 }, new int[] { 100 }, true);
129129
assertNotNull(head.getBackgroundImage());
130130

131131
// Switch to flat look — gradient image should be cleaned up
132-
Color flat = new Color(display, 128, 128, 128);
132+
Color flat = new Color(128, 128, 128);
133133
head.setTextBackground(new Color[] { flat, flat }, new int[] { 100 }, true);
134134
assertNull(head.getBackgroundImage(),
135135
"Gradient image should be removed when switching to flat look");
@@ -142,7 +142,7 @@ public void testSingleColorArrayIsFlatLook() {
142142
FormHeading head = (FormHeading) form.getHead();
143143
head.setSize(100, 50);
144144

145-
Color color = new Color(display, 42, 42, 42);
145+
Color color = new Color(42, 42, 42);
146146
head.setTextBackground(new Color[] { color }, new int[] { 100 }, true);
147147

148148
assertNull(head.getBackgroundImage(),
@@ -156,7 +156,7 @@ public void testFlatLookRendersWithoutErrors() {
156156
FormHeading head = (FormHeading) form.getHead();
157157
head.setSize(100, 50);
158158

159-
Color color = new Color(display, 200, 200, 200);
159+
Color color = new Color(200, 200, 200);
160160
head.setTextBackground(new Color[] { color, color }, new int[] { 100 }, true);
161161

162162
assertDoesNotThrow(() -> {
@@ -171,8 +171,8 @@ public void testResetToNullClearsGradient() {
171171
FormHeading head = (FormHeading) form.getHead();
172172
head.setSize(100, 50);
173173

174-
Color color1 = new Color(display, 255, 0, 0);
175-
Color color2 = new Color(display, 0, 0, 255);
174+
Color color1 = new Color(255, 0, 0);
175+
Color color2 = new Color(0, 0, 255);
176176
head.setTextBackground(new Color[] { color1, color2 }, new int[] { 100 }, true);
177177
assertNotNull(head.getBackgroundImage());
178178

@@ -185,7 +185,7 @@ public void testResetToNullClearsGradient() {
185185
@Test
186186
public void testSectionFlatLook() {
187187
Section section = new Section(shell, Section.TITLE_BAR);
188-
Color bg = new Color(display, 240, 240, 240);
188+
Color bg = new Color(240, 240, 240);
189189
section.setTitleBarBackground(bg);
190190
section.setTitleBarBorderColor(bg);
191191

@@ -200,7 +200,7 @@ public void testSectionFlatLook() {
200200
@Test
201201
public void testFormImagesFlatGradient() throws Exception {
202202
FormImages instance = FormImages.getInstance();
203-
Color color = new Color(display, 100, 100, 100);
203+
Color color = new Color(100, 100, 100);
204204

205205
// test simple gradient with identical colors
206206
org.eclipse.swt.graphics.Image img1 = instance.getGradient(color, color, 10, 10, 0, display);

0 commit comments

Comments
 (0)