Skip to content

Commit

Permalink
More theme handling
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexisDrogoul committed Dec 5, 2020
1 parent 0796872 commit ab8f0de
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static msi.gama.common.preferences.GamaPreferences.create;
import static msi.gama.common.preferences.GamaPreferences.Interface.APPEARANCE;
import static msi.gama.common.preferences.GamaPreferences.Interface.NAME;
import static org.eclipse.swt.widgets.Display.isSystemDarkTheme;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
Expand All @@ -14,10 +15,10 @@
import org.eclipse.e4.ui.css.swt.theme.IThemeEngine;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.Workbench;
import org.osgi.framework.FrameworkUtil;
import org.osgi.service.event.EventHandler;
import org.osgi.service.prefs.BackingStoreException;
import msi.gama.common.preferences.Pref;
import msi.gaml.types.IType;

Expand All @@ -28,10 +29,16 @@ public class ThemeHelper {
public static final String E4_CLASSIC_THEME_ID = "org.eclipse.e4.ui.css.theme.e4_classic";
public static final String THEME_ID_PREFERENCE = "themeid";
public static final String THEME_ID = "cssTheme";
public static final String THEME_FOLLOW_PROPERTY = "org.eclipse.swt.display.useSystemTheme";
public static final String ENABLED_THEME_KEY = "themeEnabled";
public static final String SWT_PREFERENCES = "org.eclipse.e4.ui.workbench.renderers.swt";

private static final List<IThemeListener> listeners = new ArrayList<>();

public static final Pref<Boolean> CORE_THEME_FOLLOW =
create("pref_theme_follow", "Follow OS theme", true, IType.BOOL, false).in(NAME, APPEARANCE)
.deactivates("pref_theme_light").onChange(yes -> {
create("pref_theme_follow", "Follow OS theme", followOSTheme(), IType.BOOL, false).in(NAME, APPEARANCE)
.restartRequired().deactivates("pref_theme_light").onChange(yes -> {
followOSTheme(yes);
chooseThemeBasedOnPreferences();
});

Expand All @@ -41,70 +48,108 @@ public class ThemeHelper {
chooseThemeBasedOnPreferences();
});

public static void chooseThemeBasedOnPreferences() {
final var isGamaAlreadyDark = isDark();
if ( CORE_THEME_FOLLOW.getValue() ) {
final var isOSDark = Display.isSystemDarkTheme();
if ( isGamaAlreadyDark && isOSDark )
return;
if ( isGamaAlreadyDark && !isOSDark ) {
changeToLight();
return;
}
if ( !isGamaAlreadyDark && isOSDark ) {
changeToDark();
return;
}
if ( !isGamaAlreadyDark && !isOSDark )
return;
} else {
if ( CORE_THEME_LIGHT.getValue() )
changeToLight();
else changeToDark();
}
/**
* Chooses a light/dark theme based on the GAMA preferences and the actual theme
* @return whether a change has been made
*/
private static boolean chooseThemeBasedOnPreferences() {
return CORE_THEME_FOLLOW.getValue() && changeTo(!isSystemDarkTheme()) || changeTo(CORE_THEME_LIGHT.getValue());
}

private static final List<IThemeListener> listeners = new ArrayList<>();

private static IEclipseContext getContext() {
return Workbench.getInstance().getContext();
}

public static void install() {
private static Boolean followOSTheme() {
final var prefs = getSwtRendererPreferences();
final var val = prefs.get(THEME_FOLLOW_PROPERTY, null);
if ( val != null ) { return Boolean.valueOf(val); }
return Boolean.valueOf(System.getProperty(THEME_FOLLOW_PROPERTY, "true"));
}

private static void followOSTheme(Boolean follow) {
Display.getDefault().setData(THEME_FOLLOW_PROPERTY, follow);
System.setProperty(THEME_FOLLOW_PROPERTY, follow.toString());
// We create a new preference
getSwtRendererPreferences().putBoolean(THEME_FOLLOW_PROPERTY, follow);
try {
getSwtRendererPreferences().flush();
} catch (final BackingStoreException e) {
e.printStackTrace();
}
}

public static boolean isDark() {
String id;
final var themeEngine = getContext().get(IThemeEngine.class);
if ( themeEngine == null ) {
id = (String) getContext().get(THEME_ID);
if ( id == null ) {
// Still no trace of a theme, let's look at preferences
final var prefs = getThemeEclipsePreferences();
id = prefs.get(THEME_ID_PREFERENCE, null);
}

} else {
final var theme = (themeEngine.getActiveTheme());
id = (theme == null) ? null : (theme.getId());
}
return (id != null) && (id.contains("dark"));
}

if ( !PlatformUI.isWorkbenchRunning() ) { return; }
public static void install() {
// if ( !PlatformUI.isWorkbenchRunning() ) { return; }
// We transfer the preference to the system property (to be read by Eclipse)
System.setProperty(THEME_FOLLOW_PROPERTY, followOSTheme().toString());
final var eventBroker = Workbench.getInstance().getService(IEventBroker.class);
final var themeChangedHandler = new WorkbenchThemeChangedHandler();
if ( eventBroker != null ) {
final var themeChangedHandler = new WorkbenchThemeChangedHandler();
eventBroker.subscribe(UIEvents.UILifeCycle.THEME_CHANGED, themeChangedHandler);
eventBroker.subscribe(IThemeEngine.Events.THEME_CHANGED, themeChangedHandler);
}
chooseThemeBasedOnPreferences();
}

public static void changeToLight() {
changeTo(E4_LIGHT_THEME_ID);
private static IEclipsePreferences getThemeEclipsePreferences() {
return InstanceScope.INSTANCE.getNode(FrameworkUtil.getBundle(ThemeEngine.class).getSymbolicName());
}

public static void changeToDark() {
changeTo(E4_DARK_THEME_ID);
private static IEclipsePreferences getSwtRendererPreferences() {
return InstanceScope.INSTANCE.getNode("org.eclipse.e4.ui.workbench.renderers.swt"); //$NON-NLS-1$
}

private static void changeTo(String id) {
final var themeEngine = getContext().get(IThemeEngine.class);
if ( themeEngine == null ) {
// early in the cycle
getContext().set(THEME_ID, id);
getPreferences().put(THEME_ID_PREFERENCE, id);
return;
/**
* Changes to a light or dark theme depending on the value of the argument
* @param light whether to choose a light (true) or dark (false) theme
* @return whether a change has been necessary
*/
private static boolean changeTo(boolean light) {
// OS.setTheme(!light);
return changeTo(light ? E4_LIGHT_THEME_ID : E4_DARK_THEME_ID);
}

/**
* Changes the current theme in both the theme engine and the preferences (so that they can stick)
* @param id the identifier of the theme
*/
private static boolean changeTo(String id) {
// even early in the cycle
getContext().set(THEME_ID, id);
getThemeEclipsePreferences().put(THEME_ID_PREFERENCE, id);
try {
getThemeEclipsePreferences().flush();
} catch (final BackingStoreException e) {
e.printStackTrace();
}
final var themeEngine = getContext().get(IThemeEngine.class);
if ( themeEngine == null ) { return true; }
final var theme = (themeEngine.getActiveTheme());
if ( theme != null ) {
if ( theme.getId().startsWith(id) )
return;
return false;
}
getPreferences().put(THEME_ID_PREFERENCE, id);
themeEngine.setTheme(id, true);
return true;
}

public static void addListener(IThemeListener l) {
Expand All @@ -116,15 +161,12 @@ public static void removeListener(IThemeListener l) {
listeners.remove(l);
}

private static IEclipsePreferences getPreferences() {
return InstanceScope.INSTANCE.getNode(FrameworkUtil.getBundle(ThemeEngine.class).getSymbolicName());
}

public static class WorkbenchThemeChangedHandler implements EventHandler {

@Override
public void handleEvent(org.osgi.service.event.Event event) {
final var theme = getTheme(event);
System.out.println("PROPERTY " + THEME_FOLLOW_PROPERTY + " = " + System.getProperty(THEME_FOLLOW_PROPERTY));
System.out.println("THEME = " + theme);
if ( theme == null )
return;
Expand All @@ -147,30 +189,4 @@ public interface IThemeListener {
void themeChanged(boolean light);
}

public static boolean isDark() {
final var themeEngine = getContext().get(IThemeEngine.class);
if ( themeEngine == null ) {
final var id = (String) getContext().get(THEME_ID);
return (id != null) && (id.startsWith(E4_DARK_THEME_ID));
}
final var theme = (themeEngine.getActiveTheme());

final var result = (theme != null) && (theme.getId().startsWith(E4_DARK_THEME_ID));
return result;
}

}

// Bundle b = FrameworkUtil.getBundle(getClass());
// BundleContext context = b.getBundleContext();
// ServiceReference serviceRef = context
// .getServiceReference(IThemeManager.class.getName());
// IThemeManager themeManager = (IThemeManager) context
// .getService(serviceRef);
// final IThemeEngine engine = themeManager.getEngineForDisplay(Display
// .getCurrent());
// engine.setTheme("org.eclipse.e4.ui.examples.css.rcp", true);
// if (serviceRef != null) {
// serviceRef = null;
// }
// themeManager = null;
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.eclipse.ui.console.IOConsoleOutputStream;
import org.eclipse.ui.internal.console.IOConsoleViewer;

import msi.gama.application.workbench.ThemeHelper;
import msi.gama.common.interfaces.IGamaView;
import msi.gama.common.preferences.GamaPreferences;
import msi.gama.kernel.experiment.ITopLevelAgent;
Expand Down Expand Up @@ -65,13 +66,13 @@ public void setCharacterLimit(final int limit) {
public void ownCreatePartControl(final Composite parent) {
msgConsole = new IOConsole("GAMA Console", null);
setCharacterLimit(GamaPreferences.Interface.CORE_CONSOLE_SIZE.getValue());
GamaPreferences.Interface.CORE_CONSOLE_SIZE.onChange(newValue -> setCharacterLimit(newValue));
GamaPreferences.Interface.CORE_CONSOLE_SIZE.onChange(this::setCharacterLimit);
viewer = new IOConsoleViewer(parent, msgConsole);
viewer.setWordWrap(GamaPreferences.Interface.CORE_CONSOLE_WRAP.getValue());
}

private BufferedWriter getWriterFor(final ITopLevelAgent root, final GamaUIColor color) {
final Color c = color == null ? getColorFor(root) : color.color();
final Color c = getColorFor(root, color);
BufferedWriter writer = writers.get(c);
if (writer == null) {
final IOConsoleOutputStream stream = msgConsole.newOutputStream();
Expand All @@ -83,13 +84,10 @@ private BufferedWriter getWriterFor(final ITopLevelAgent root, final GamaUIColor
return writer;
}

/**
* @param root
* @return
*/
private Color getColorFor(final ITopLevelAgent root) {
if (root == null) { return IGamaColors.BLACK.color(); }
return GamaColors.get(root.getColor()).color();
private Color getColorFor(final ITopLevelAgent root, final GamaUIColor requested) {
final GamaUIColor result =
requested == null ? root == null ? IGamaColors.BLACK : GamaColors.get(root.getColor()) : requested;
return ThemeHelper.isDark() ? result.lighter() : result.color();
}

private boolean indicated = false;
Expand Down
28 changes: 13 additions & 15 deletions ummisco.gama.ui.shared/src/ummisco/gama/ui/utils/WebHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,24 @@
**********************************************************************************************/
package ummisco.gama.ui.utils;

import static msi.gama.application.workbench.ThemeHelper.isDark;
import static org.eclipse.core.runtime.FileLocator.toFileURL;
import static org.eclipse.core.runtime.Platform.getBundle;

import java.io.IOException;
import java.net.URL;

import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.FileStoreEditorInput;
import org.eclipse.ui.internal.part.NullEditorInput;
import org.eclipse.ui.part.FileEditorInput;

import msi.gama.application.workbench.IWebHelper;
import msi.gama.common.interfaces.IGamaView;
import msi.gama.common.interfaces.IGamaView.Html;
import msi.gama.common.preferences.GamaPreferences;

Expand All @@ -49,8 +47,8 @@ private WebHelper() {}
public static URL getWelcomePageURL() {
if (HOME_URL == null)
try {
HOME_URL = FileLocator
.toFileURL(Platform.getBundle("ummisco.gama.ui.shared").getEntry("/welcome/welcome.html"));
final var welcomePage = "/welcome/" + (isDark() ? "dark" : "light") + "/welcome.html";
HOME_URL = toFileURL(getBundle("ummisco.gama.ui.shared").getEntry(welcomePage));
} catch (final IOException e) {
e.printStackTrace();
}
Expand All @@ -61,18 +59,18 @@ public static void openWelcomePage(final boolean ifEmpty) {
if (ifEmpty && WorkbenchHelper.getPage().getActiveEditor() != null) { return; }
if (ifEmpty && !GamaPreferences.Interface.CORE_SHOW_PAGE.getValue()) { return; }
// get the workspace
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
final var workspace = ResourcesPlugin.getWorkspace();

// create the path to the file
final IPath location = new Path(getWelcomePageURL().getPath());

// try to get the IFile (returns null if it could not be found in the
// workspace)
final IFile file = workspace.getRoot().getFileForLocation(location);
final var file = workspace.getRoot().getFileForLocation(location);
IEditorInput input;
if (file == null) {
// not found in the workspace, get the IFileStore (external files)
final IFileStore fileStore = EFS.getLocalFileSystem().getStore(location);
final var fileStore = EFS.getLocalFileSystem().getStore(location);
input = new FileStoreEditorInput(fileStore);

} else {
Expand All @@ -89,18 +87,18 @@ public static void openWelcomePage(final boolean ifEmpty) {
public static void showWeb2Editor(final URL url) {

// get the workspace
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
final var workspace = ResourcesPlugin.getWorkspace();

// create the path to the file
final IPath location = new Path(url.getPath());

// try to get the IFile (returns null if it could not be found in the
// workspace)
final IFile file = workspace.getRoot().getFileForLocation(location);
final var file = workspace.getRoot().getFileForLocation(location);
IEditorInput input;
if (file == null) {
// not found in the workspace, get the IFileStore (external files)
final IFileStore fileStore = EFS.getLocalFileSystem().getStore(location);
final var fileStore = EFS.getLocalFileSystem().getStore(location);
input = new FileStoreEditorInput(fileStore);

} else {
Expand All @@ -117,7 +115,7 @@ public static void showWeb2Editor(final URL url) {

public static void openPage(final String string) {
try {
final IGamaView.Html view =
final var view =
(Html) WorkbenchHelper.getPage().openEditor(new NullEditorInput(), "msi.gama.application.browser");
view.setUrl(string);
} catch (final PartInitException e) {
Expand Down

0 comments on commit ab8f0de

Please sign in to comment.