Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-21
Require-Bundle: org.eclipse.swt;bundle-version="[3.133.0,4.0.0)",
Require-Bundle: org.eclipse.swt;bundle-version="[3.134.0,4.0.0)",
org.eclipse.e4.ui.css.swt;bundle-version="0.13.100",
org.eclipse.e4.ui.css.core;bundle-version="0.12.200",
org.eclipse.core.runtime;bundle-version="[3.29.0,4.0.0)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,9 @@ public void setTheme(ITheme theme, boolean restore, boolean force) {
ThemeEngineManager.logError(e.getMessage(), e);
}
}
boolean isDark = theme.getId().contains("dark"); //$NON-NLS-1$
display.setDarkThemePreferred(isDark);

sendThemeChangeEvent(restore);

for (CSSEngine engine : cssEngines) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.21.0,4.0.0)",
org.eclipse.e4.core.di.extensions,
org.eclipse.e4.core.services;bundle-version="2.4.0",
org.eclipse.e4.core.contexts;bundle-version="[1.12.0,2.0.0)",
org.eclipse.ui.forms,
org.eclipse.urischeme;bundle-version="[1.3.0,2.0.0)",
org.eclipse.e4.ui.di
Export-Package: org.eclipse.ui.internal.ide.application;x-internal:=true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,15 @@

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExecutableExtension;
import org.eclipse.core.runtime.IProduct;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.ConfigurationScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.UserScope;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.jface.dialogs.IDialogConstants;
Expand All @@ -52,14 +55,18 @@
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.internal.Workbench;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.WorkspaceLock;
Expand Down Expand Up @@ -94,6 +101,9 @@ public class IDEApplication implements IApplication, IExecutableExtension {

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

private boolean isDark;
private Listener darkThemeShowListener;

// Use the branding plug-in of the platform feature since this is most likely
// to change on an update of the IDE.
private static final String WORKSPACE_CHECK_REFERENCE_BUNDLE_NAME = "org.eclipse.platform"; //$NON-NLS-1$
Expand Down Expand Up @@ -145,6 +155,9 @@ public Object start(IApplicationContext appContext) throws Exception {
Job.getJobManager().suspend();

Display display = createDisplay();

Comment thread
vogella marked this conversation as resolved.
initializeDefaultTheme(display);

// processor must be created before we start event loop
DelayedEventsProcessor processor = new DelayedEventsProcessor(display);

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

// Reset early dark theme styling before the workbench starts;
// the ThemeEngine will apply the correct theme from here on.
resetEarlyDarkTheme(display);

// create the workbench with this advisor and run it until it exits
// N.B. createWorkbench remembers the advisor, and also registers
// the workbench globally so that all UI plug-ins can find it using
Expand Down Expand Up @@ -587,6 +604,14 @@ protected Shell getParentShell() {
return null;
}

@Override
protected Control createContents(Composite parent) {
Control contents = super.createContents(parent);
if (isDark) {
applyDarkStyles(getShell());
}
return contents;
}
Comment thread
vogella marked this conversation as resolved.
}.prompt(force);
}

Expand Down Expand Up @@ -852,6 +877,85 @@ protected static Version toMajorMinorVersion(Version version) {
return new Version(version.getMajor(), version.getMinor(), 0);
}

protected void initializeDefaultTheme(Display display) {
IEclipsePreferences themeNode = UserScope.INSTANCE.getNode("org.eclipse.e4.ui.css.swt.theme"); //$NON-NLS-1$
String productOrAppId = getProductOrApplicationId();
String defaultThemeId;
if (productOrAppId != null) {
defaultThemeId = themeNode.node(productOrAppId).get("themeid", null); //$NON-NLS-1$
} else {
defaultThemeId = themeNode.get("themeid", null); //$NON-NLS-1$
}
isDark = defaultThemeId != null && defaultThemeId.contains("dark"); //$NON-NLS-1$
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defaultThemeId.contains("dark") seem to match only default theme id.
If product defines theme "com.my.product.themeid", there is not necessarily "dark" in the id but the theme can be "dark".

Ideally this could be extracted to a protected boolean isDarkTheme(String themeId)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is currently the way the theme engine detects a dark theme. We can make this more flexible here but the rest of theming engine will just look for the "dark" string so that would make this not aligned with the rest of the theming.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is currently the way the theme engine detects a dark theme

OMG

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The theming code is a pleasure to look at. Tons of unused abstraction in lots of places and lots of hard coded values in others.

if (isDark) {
display.setDarkThemePreferred(true);
darkThemeShowListener = event -> {
if (event.widget instanceof Shell shell) {
applyDarkStyles(shell);
}
};
display.addListener(SWT.Show, darkThemeShowListener);
}
}

/**
* Removes the early dark theme styling applied for the workspace selection
* dialog. Must be called before the workbench starts so the ThemeEngine can
* manage the theme without interference.
*/
protected void resetEarlyDarkTheme(Display display) {
if (darkThemeShowListener != null) {
display.removeListener(SWT.Show, darkThemeShowListener);
darkThemeShowListener = null;
}
if (isDark) {
display.setDarkThemePreferred(false);
}
}

/**
* Returns the product ID if a product is configured, otherwise falls back to
* the application ID from the system property. Returns {@code null} if neither
* is available.
*/
private static String getProductOrApplicationId() {
IProduct product = Platform.getProduct();
if (product != null) {
return product.getId();
}
return System.getProperty("eclipse.application"); //$NON-NLS-1$
}

private void applyDarkStyles(Shell shell) {
Color bg = new Color(72, 72, 76); // #48484c
Color fg = new Color(238, 238, 238); // #eeeeee
Color linkColor = new Color(111, 197, 238); // #6FC5EE
shell.setBackground(bg);
shell.setForeground(fg);
applyStylesRecursive(shell, bg, fg, linkColor);
}

private void applyStylesRecursive(Control control, Color bg, Color fg, Color linkColor) {
control.setBackground(bg);
if (control instanceof Link link) {
link.setLinkForeground(linkColor);
} else {
control.setForeground(fg);

Comment thread
vogella marked this conversation as resolved.
}

if (control instanceof ExpandableComposite expandable) {
expandable.setTitleBarForeground(fg);
expandable.setToggleColor(fg);
expandable.setActiveToggleColor(fg);
}
if (control instanceof Composite composite) {
for (Control child : composite.getChildren()) {
applyStylesRecursive(child, bg, fg, linkColor);
}
}
}

@Override
public void stop() {
final IWorkbench workbench = PlatformUI.getWorkbench();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.jface.util.Geometry;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
Expand Down Expand Up @@ -319,6 +320,10 @@ private void createRecentWorkspacesComposite(final Composite composite) {
recentWorkspacesForm.getBody().setLayout(new GridLayout());
ExpandableComposite recentWorkspacesExpandable = toolkit.createExpandableComposite(recentWorkspacesForm.getBody(),
ExpandableComposite.TWISTIE);
recentWorkspacesExpandable.setTitleBarForeground(composite.getForeground());
recentWorkspacesExpandable.setForeground(composite.getForeground());
recentWorkspacesExpandable.setToggleColor(composite.getForeground());
recentWorkspacesExpandable.setActiveToggleColor(composite.getForeground());
recentWorkspacesForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
recentWorkspacesExpandable.setBackground(composite.getBackground());
recentWorkspacesExpandable.setText(IDEWorkbenchMessages.ChooseWorkspaceDialog_recentWorkspaces);
Expand Down Expand Up @@ -352,6 +357,7 @@ public void expansionStateChanged(ExpansionEvent e) {
final String recentWorkspace = uniqueWorkspaceEntry.getValue();

Link link = new Link(panel, SWT.WRAP);
link.setForeground(JFaceColors.getHyperlinkText(composite.getDisplay()));
link.setLayoutData(new RowData(SWT.DEFAULT, SWT.DEFAULT));
link.setText("<a>" + uniqueWorkspaceEntry.getKey() + "</a>"); //$NON-NLS-1$ //$NON-NLS-2$
link.setToolTipText(recentWorkspace);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ private void createSettingsControls(Composite workArea) {

copySettingsExpandable.setText(IDEWorkbenchMessages.ChooseWorkspaceWithSettingsDialog_SettingsGroupName);
copySettingsExpandable.setBackground(workArea.getBackground());
copySettingsExpandable.setTitleBarForeground(workArea.getForeground());
copySettingsExpandable.setToggleColor(workArea.getForeground());
copySettingsExpandable.setActiveToggleColor(workArea.getForeground());
copySettingsExpandable.setLayout(new GridLayout());
copySettingsExpandable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
copySettingsExpandable.addExpansionListener(new IExpansionListener() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void testFormHeadingFlatLook() {
FormHeading head = (FormHeading) form.getHead();
head.setSize(100, 50);

Color color = new Color(display, 255, 0, 0);
Color color = new Color(255, 0, 0);
Color[] identicalColors = new Color[] { color, color };
int[] percents = new int[] { 100 };

Expand All @@ -74,7 +74,7 @@ public void testFormHeadingFlatLook() {
});

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

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

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

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

Color color1 = new Color(display, 255, 0, 0);
Color color2 = new Color(display, 0, 0, 255);
Color color1 = new Color(255, 0, 0);
Color color2 = new Color(0, 0, 255);
head.setTextBackground(new Color[] { color1, color2 }, new int[] { 100 }, true);

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

// First set a real gradient
Color color1 = new Color(display, 255, 0, 0);
Color color2 = new Color(display, 0, 0, 255);
Color color1 = new Color(255, 0, 0);
Color color2 = new Color(0, 0, 255);
head.setTextBackground(new Color[] { color1, color2 }, new int[] { 100 }, true);
assertNotNull(head.getBackgroundImage());

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

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

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

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

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

Color color1 = new Color(display, 255, 0, 0);
Color color2 = new Color(display, 0, 0, 255);
Color color1 = new Color(255, 0, 0);
Color color2 = new Color(0, 0, 255);
head.setTextBackground(new Color[] { color1, color2 }, new int[] { 100 }, true);
assertNotNull(head.getBackgroundImage());

Expand All @@ -185,7 +185,7 @@ public void testResetToNullClearsGradient() {
@Test
public void testSectionFlatLook() {
Section section = new Section(shell, Section.TITLE_BAR);
Color bg = new Color(display, 240, 240, 240);
Color bg = new Color(240, 240, 240);
section.setTitleBarBackground(bg);
section.setTitleBarBorderColor(bg);

Expand All @@ -200,7 +200,7 @@ public void testSectionFlatLook() {
@Test
public void testFormImagesFlatGradient() throws Exception {
FormImages instance = FormImages.getInstance();
Color color = new Color(display, 100, 100, 100);
Color color = new Color(100, 100, 100);

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