Skip to content

Commit f08ce51

Browse files
committed
Provide Explicit "isDarkTheme" Attribute
Up to now we had some heuristics to check if a theme is a dark theme. This now makes this explicit. - Add attribute to extension point - Fill this attribute for the platforms dark theme - Remove heuristics and now check this explicit flag - Add tests
1 parent 037c5d7 commit f08ce51

File tree

9 files changed

+117
-32
lines changed

9 files changed

+117
-32
lines changed

bundles/org.eclipse.e4.ui.css.swt.theme/schema/org.eclipse.e4.ui.css.swt.theme.exsd

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,13 @@
134134
</documentation>
135135
</annotation>
136136
</attribute>
137+
<attribute name="isDarkTheme" type="boolean">
138+
<annotation>
139+
<documentation>
140+
Set this to true if the theme uses dark background.
141+
</documentation>
142+
</annotation>
143+
</attribute>
137144
</complexType>
138145
</element>
139146

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public class Theme implements ITheme {
1919
private String id;
2020
private String label;
2121
private String osVersion;
22+
private String isDark;
2223

2324
public Theme(String id, String label) {
2425
this.id = id;
@@ -43,10 +44,25 @@ public String getOsVersion() {
4344
return this.osVersion;
4445
}
4546

47+
@Override
48+
public boolean isDark() {
49+
if (isDark == null) {
50+
// fallback for themes that don't yet set the "isDark" attribute
51+
// will be removed in a later release
52+
return id.contains("dark");
53+
} else {
54+
return Boolean.parseBoolean(isDark);
55+
}
56+
}
57+
58+
public void setIsDark(String isDark) {
59+
this.isDark = isDark;
60+
}
61+
4662
@Override
4763
public String toString() {
4864
return "Theme [id=" + id + ", label='" + label + "', osVersion="
49-
+ osVersion + "]";
65+
+ osVersion + " isDark=" + isDark + "]";
5066
}
5167

5268

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

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public class ThemeEngine implements IThemeEngine {
8181
private HashMap<String, List<IResourceLocator>> sourceLocators = new HashMap<>();
8282

8383
private static final String THEMEID_KEY = "themeid";
84+
private static final String THEME_IS_DARK_KEY = "themeIsDark";
8485

8586
public static final String THEME_PLUGIN_ID = "org.eclipse.e4.ui.css.swt.theme";
8687

@@ -121,6 +122,7 @@ public ThemeEngine(Display display) {
121122
String id = ce.getAttribute("id");
122123
String os = ce.getAttribute("os");
123124
String version = ce.getAttribute("os_version");
125+
String isDarkTheme = ce.getAttribute("isDarkTheme");
124126

125127
/*
126128
* Code to support e4 dark theme on Mac 10.13 and older. For e4 dark theme on
@@ -154,7 +156,8 @@ public ThemeEngine(Display display) {
154156
basestylesheeturi = "platform:/plugin/" + ce.getContributor().getName() + "/"
155157
+ basestylesheeturi;
156158
}
157-
registerTheme(themeId, label, basestylesheeturi, version);
159+
160+
registerTheme(themeId, label, basestylesheeturi, version, isDarkTheme);
158161

159162
//check for modified files
160163
if (modifiedFiles != null) {
@@ -250,11 +253,11 @@ private boolean isOsVersionMatch(String osVersionList) {
250253
@Override
251254
public synchronized ITheme registerTheme(String id, String label, String basestylesheetURI)
252255
throws IllegalArgumentException {
253-
return registerTheme(id, label, basestylesheetURI, "");
256+
return registerTheme(id, label, basestylesheetURI, "", "");
254257
}
255258

256259
public synchronized ITheme registerTheme(String id, String label,
257-
String basestylesheetURI, String osVersion) throws IllegalArgumentException {
260+
String basestylesheetURI, String osVersion, String isDark) throws IllegalArgumentException {
258261
for (Theme t : themes) {
259262
if (t.getId().equals(id)) {
260263
throw new IllegalArgumentException("A theme with the id '" + id
@@ -265,6 +268,9 @@ public synchronized ITheme registerTheme(String id, String label,
265268
if (osVersion != "") {
266269
theme.setOsVersion(osVersion);
267270
}
271+
if (isDark != "") {
272+
theme.setIsDark(isDark);
273+
}
268274
themes.add(theme);
269275
registerStyle(id, basestylesheetURI, false);
270276
return theme;
@@ -496,6 +502,7 @@ public void setTheme(ITheme theme, boolean restore, boolean force) {
496502
EclipsePreferencesHelper.setCurrentThemeId(theme.getId());
497503

498504
pref.put(THEMEID_KEY, theme.getId());
505+
pref.putBoolean(THEME_IS_DARK_KEY, theme.isDark());
499506
try {
500507
pref.flush();
501508
} catch (BackingStoreException e) {
@@ -560,6 +567,10 @@ private String getPreferenceThemeId() {
560567
return getPreferences().get(THEMEID_KEY, null);
561568
}
562569

570+
private boolean getPreferenceThemeIsDark(boolean fallback) {
571+
return getPreferences().getBoolean(THEME_IS_DARK_KEY, fallback);
572+
}
573+
563574
private IEclipsePreferences getPreferences() {
564575
return InstanceScope.INSTANCE.getNode(FrameworkUtil.getBundle(ThemeEngine.class).getSymbolicName());
565576
}
@@ -593,12 +604,24 @@ public void restore(String alternateTheme) {
593604
for (ITheme t : getThemes()) {
594605
if (prefThemeId.equals(t.getId())) {
595606
setTheme(t, false);
607+
608+
// also update "isDark" attribute in the pref-store (might be not set there)
609+
// will be removed in a later release
610+
IEclipsePreferences preferences = getPreferences();
611+
if (preferences.get(THEME_IS_DARK_KEY, null) == null) {
612+
preferences.putBoolean(THEME_IS_DARK_KEY, t.isDark());
613+
try {
614+
preferences.flush();
615+
} catch (BackingStoreException e) {
616+
ThemeEngineManager.logError(e.getMessage(), e);
617+
}
618+
}
596619
return;
597620
}
598621
}
599622
}
600623

601-
boolean hasDarkTheme = getThemes().stream().anyMatch(t -> t.getId().startsWith(E4_DARK_THEME_ID));
624+
boolean hasDarkTheme = getThemes().stream().anyMatch(t -> t.isDark());
602625
boolean overrideWithDarkTheme = false;
603626
if (hasDarkTheme) {
604627
if (prefThemeId != null) {
@@ -607,7 +630,7 @@ public void restore(String alternateTheme) {
607630
* this case want to fall back to respect whether that previous choice was dark
608631
* or not. https://github.com/eclipse-platform/eclipse.platform.ui/issues/2776
609632
*/
610-
overrideWithDarkTheme = prefThemeId.contains("dark");
633+
overrideWithDarkTheme = getPreferenceThemeIsDark(prefThemeId.contains("dark"));
611634
} else {
612635
/*
613636
* No previous theme selection in preferences. In this case check if the system

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,10 @@ public interface ITheme {
2626
* @return the label
2727
*/
2828
String getLabel();
29+
30+
/**
31+
*
32+
* @return does the theme use a dark background color
33+
*/
34+
boolean isDark();
2935
}

bundles/org.eclipse.e4.ui.swt.gtk/src/org/eclipse/e4/ui/swt/internal/gtk/DarkThemeProcessor.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,11 @@ public void intialize() {
4040
return;
4141
}
4242
ITheme theme = (ITheme) event.getProperty("theme");
43-
final boolean isDark = theme.getId().contains("dark"); //$NON-NLS-1$
4443
Display display = (Display) event.getProperty(IThemeEngine.Events.DEVICE);
4544

4645
// not using UISynchronize as this is specific to SWT/GTK
4746
// scenarios
48-
display.asyncExec(() -> OS.setDarkThemePreferred(isDark));
47+
display.asyncExec(() -> OS.setDarkThemePreferred(theme.isDark()));
4948
};
5049
// using the IEventBroker explicitly because the @EventTopic annotation
5150
// is unpredictable with processors within the debugger

bundles/org.eclipse.e4.ui.swt.win32/src/org/eclipse/e4/ui/swt/internal/win32/DarkThemeProcessor.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ public void intialize() {
3939
return;
4040
}
4141
ITheme theme = (ITheme) event.getProperty("theme");
42-
boolean isDark = theme.getId().contains("dark"); //$NON-NLS-1$
43-
OS.setTheme (isDark);
42+
OS.setTheme (theme.isDark());
4443
};
4544
// using the IEventBroker explicitly because the @EventTopic annotation
4645
// is unpredictable with processors within the debugger

bundles/org.eclipse.e4.ui.workbench.renderers.swt.cocoa/src/org/eclipse/e4/ui/swt/internal/cocoa/CocoaDarkThemeProcessor.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,23 @@ public void intialize() {
3939
return;
4040
}
4141
ITheme theme = (ITheme) event.getProperty("theme"); //$NON-NLS-1$
42-
final boolean isDark = theme.getId().contains("dark"); //$NON-NLS-1$
4342
Display display = (Display) event.getProperty(IThemeEngine.Events.DEVICE);
4443

4544
// not using UISynchronize as this is specific to SWT/Mac
4645
// scenarios
47-
display.asyncExec(() -> OS.setTheme(isDark));
46+
display.asyncExec(() -> OS.setTheme(theme.isDark()));
4847
};
4948
// using the IEventBroker explicitly because the @EventTopic annotation
5049
// is unpredictable with processors within the debugger
5150
eventBroker.subscribe(IThemeEngine.Events.THEME_CHANGED, eventHandler);
5251
}
5352

5453
/**
55-
* Unsubscribes the {@code eventHandler} from the {@code eventBroker} to cleanup the resources
54+
* Unsubscribes the {@code eventHandler} from the {@code eventBroker} to cleanup
55+
* the resources
5656
*
57-
* Assumption : Both {@code eventHandler} and {@code eventBroker} are initialized and non null
57+
* Assumption : Both {@code eventHandler} and {@code eventBroker} are
58+
* initialized and non null
5859
*/
5960
@PreDestroy
6061
public void cleanUp() {

bundles/org.eclipse.ui.themes/plugin.xml

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,33 @@
99
label="%theme.classic">
1010
</theme>
1111
<theme
12-
basestylesheeturi="css/e4-dark_linux.css"
13-
id="org.eclipse.e4.ui.css.theme.e4_dark"
14-
label="%theme.dark"
15-
os="linux">
12+
basestylesheeturi="css/e4-dark_linux.css"
13+
id="org.eclipse.e4.ui.css.theme.e4_dark"
14+
isDarkTheme="true"
15+
label="%theme.dark"
16+
os="linux">
1617
</theme>
1718
<theme
18-
basestylesheeturi="css/e4-dark_win.css"
19-
id="org.eclipse.e4.ui.css.theme.e4_dark"
20-
label="%theme.dark"
21-
os="win32">
19+
basestylesheeturi="css/e4-dark_win.css"
20+
id="org.eclipse.e4.ui.css.theme.e4_dark"
21+
isDarkTheme="true"
22+
label="%theme.dark"
23+
os="win32">
2224
</theme>
2325
<theme
24-
basestylesheeturi="css/e4-dark_mac1013.css"
25-
id="org.eclipse.e4.ui.css.theme.e4_dark"
26-
label="%theme.dark"
27-
os="macosx"
28-
os_version="10.11,10.12,10.13">
26+
basestylesheeturi="css/e4-dark_mac1013.css"
27+
id="org.eclipse.e4.ui.css.theme.e4_dark"
28+
isDarkTheme="true"
29+
label="%theme.dark"
30+
os="macosx"
31+
os_version="10.11,10.12,10.13">
2932
</theme>
3033
<theme
31-
basestylesheeturi="css/e4-dark_mac.css"
32-
id="org.eclipse.e4.ui.css.theme.e4_dark"
33-
label="%theme.dark"
34-
os="macosx">
34+
basestylesheeturi="css/e4-dark_mac.css"
35+
id="org.eclipse.e4.ui.css.theme.e4_dark"
36+
isDarkTheme="true"
37+
label="%theme.dark"
38+
os="macosx">
3539
</theme>
3640
<theme
3741
basestylesheeturi="css/e4_default_gtk.css"

tests/org.eclipse.e4.ui.tests.css.swt/src/org/eclipse/e4/ui/tests/css/swt/ThemeTest.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ public void setUp() {
5757
@Override
5858
@AfterEach
5959
public void tearDown() {
60-
themeListenerRegistration.unregister();
60+
if (themeListenerRegistration != null) {
61+
themeListenerRegistration.unregister();
62+
}
6163
super.tearDown();
6264
}
6365

@@ -94,4 +96,32 @@ private IThemeEngine getThemeEngine(Display display) {
9496
return manager.getEngineForDisplay(display);
9597
}
9698

99+
@Test
100+
void settingIsDarkToTrueShoulReportThemeIsDark() {
101+
Theme theme = new Theme("IdDoesntCare", "DescriptionDoesntCare");
102+
theme.setIsDark("true");
103+
assertTrue(theme.isDark(), "Theme should report to be dark");
104+
}
105+
106+
@Test
107+
void settingIsDarkToFalseShoulReportThemeIsNotDark() {
108+
Theme theme = new Theme("IdDoesntCare", "DescriptionDoesntCare");
109+
theme.setIsDark("false");
110+
assertFalse(theme.isDark(), "Theme should report to be NOT dark");
111+
}
112+
113+
@Test
114+
void settingIsDarkToNullShoulReportThemeIsNotDark() {
115+
Theme theme = new Theme("IdDoesntCare", "DescriptionDoesntCare");
116+
theme.setIsDark(null);
117+
assertFalse(theme.isDark(), "Theme should report to be NOT dark");
118+
}
119+
120+
@Test
121+
void settingIsDarkToInvalidValueShoulReportThemeIsNotDark() {
122+
Theme theme = new Theme("IdDoesntCare", "DescriptionDoesntCare");
123+
theme.setIsDark("invalid");
124+
assertFalse(theme.isDark(), "Theme should report to be NOT dark");
125+
}
126+
97127
}

0 commit comments

Comments
 (0)