blob: 4a64fddc78d361a83b028c039a0632784755d3a5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.themes;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.commands.common.EventManager;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.FontRegistry;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.misc.StatusUtil;
import org.eclipse.ui.internal.util.PrefUtil;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.ui.themes.ITheme;
import org.eclipse.ui.themes.IThemeManager;
/**
* Theme manager for the Workbench.
*
* @since 3.0
*/
public class WorkbenchThemeManager extends EventManager implements
IThemeManager {
private static final String SYSTEM_DEFAULT_THEME = "org.eclipse.ui.ide.systemDefault";//$NON-NLS-1$
private static WorkbenchThemeManager instance;
/**
* Returns the singelton instance of the WorkbenchThemeManager
*
* @return singleton instance
*/
public static synchronized WorkbenchThemeManager getInstance() {
if (instance == null) {
instance = new WorkbenchThemeManager();
instance.getCurrentTheme(); // initialize the current theme
}
return instance;
}
private ITheme currentTheme;
private IPropertyChangeListener currentThemeListener = new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
firePropertyChange(event);
if (event.getSource() instanceof FontRegistry) {
JFaceResources.getFontRegistry().put(event.getProperty(),
(FontData[]) event.getNewValue());
} else if (event.getSource() instanceof ColorRegistry) {
JFaceResources.getColorRegistry().put(event.getProperty(),
(RGB) event.getNewValue());
}
}
};
private ColorRegistry defaultThemeColorRegistry;
private FontRegistry defaultThemeFontRegistry;
private IThemeRegistry themeRegistry;
private Map themes = new HashMap(7);
/*
* Initialize the WorkbenchThemeManager.
* Determine the default theme according to the following rules:
* 1) If we're in HC mode then default to system default
* 2) Otherwise, if preference already set (e.g. via plugin_customization.ini), then observe that value
* 3) Otherwise, use our default
* Call dispose when we close.
*/
private WorkbenchThemeManager() {
defaultThemeColorRegistry = new ColorRegistry(PlatformUI.getWorkbench()
.getDisplay());
defaultThemeFontRegistry = new FontRegistry(PlatformUI.getWorkbench()
.getDisplay());
// copy the font values from preferences.
FontRegistry jfaceFonts = JFaceResources.getFontRegistry();
for (Iterator i = jfaceFonts.getKeySet().iterator(); i.hasNext();) {
String key = (String) i.next();
defaultThemeFontRegistry.put(key, jfaceFonts.getFontData(key));
}
//Theme might be set via plugin_configuration.ini
String themeId = PrefUtil.getAPIPreferenceStore().getDefaultString(IWorkbenchPreferenceConstants.CURRENT_THEME_ID);
//If not set, use default
if(themeId.length() == 0)
themeId = IThemeManager.DEFAULT_THEME;
// Check if we are in high contrast mode. If so then set the theme to
// the system default
if (PlatformUI.getWorkbench().getDisplay() != null) {
// Determine the high contrast setting before
// any access to preferences
final boolean[] highContrast = new boolean[] { false };
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
/*
* (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
public void run() {
highContrast[0] = Display.getCurrent().getHighContrast();
Display.getCurrent().addListener(SWT.Settings, new Listener() {
public void handleEvent(Event event) {
updateThemes();
}
});
}
});
//If in HC, *always* use the system default.
//This ignores any default theme set via plugin_customization.ini
if (highContrast[0])
themeId = SYSTEM_DEFAULT_THEME;
}
PrefUtil.getAPIPreferenceStore().setDefault(
IWorkbenchPreferenceConstants.CURRENT_THEME_ID, themeId);
}
/*
* Update existing theme contents, descriptors, and registries.
* Reread the themes and recompute the registries.
*/
private void updateThemes() {
//reread the themes since their descriptors have changed in value
ThemeRegistryReader reader = new ThemeRegistryReader();
reader.readThemes(Platform.getExtensionRegistry(),(ThemeRegistry) getThemeRegistry());
//DEFAULT_THEME is not in getThemes() list so must be handled special
ThemeElementHelper.populateRegistry(getTheme(IThemeManager.DEFAULT_THEME), getThemeRegistry().getColors(), PrefUtil.getInternalPreferenceStore());
IThemeDescriptor[] themeDescriptors = getThemeRegistry().getThemes();
for (int i=0; i < themeDescriptors.length; i++) {
IThemeDescriptor themeDescriptor = themeDescriptors[i];
ITheme theme = (ITheme) themes.get(themeDescriptor);
//If theme is in our themes table then its already been populated
if (theme != null) {
ColorDefinition[] colorDefinitions = themeDescriptor.getColors();
if (colorDefinitions.length > 0) {
ThemeElementHelper.populateRegistry(theme, colorDefinitions,PrefUtil.getInternalPreferenceStore());
}
}
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.themes.IThemeManager#addPropertyChangeListener(org.eclipse.jface.util.IPropertyChangeListener)
*/
public void addPropertyChangeListener(IPropertyChangeListener listener) {
addListenerObject(listener);
}
/**
* Disposes all ThemeEntries.
*/
public void dispose() {
for (Iterator i = themes.values().iterator(); i.hasNext();) {
ITheme theme = (ITheme) i.next();
theme.removePropertyChangeListener(currentThemeListener);
theme.dispose();
}
themes.clear();
}
private boolean doSetCurrentTheme(String id) {
ITheme oldTheme = currentTheme;
ITheme newTheme = getTheme(id);
if (oldTheme != newTheme && newTheme != null) {
currentTheme = newTheme;
return true;
}
return false;
}
protected void firePropertyChange(PropertyChangeEvent event) {
Object[] listeners = getListeners();
for (int i = 0; i < listeners.length; i++) {
((IPropertyChangeListener) listeners[i]).propertyChange(event);
}
}
protected void firePropertyChange(String changeId, ITheme oldTheme,
ITheme newTheme) {
PropertyChangeEvent event = new PropertyChangeEvent(this, changeId,
oldTheme, newTheme);
firePropertyChange(event);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.themes.IThemeManager#getCurrentTheme()
*/
public ITheme getCurrentTheme() {
if (currentTheme == null) {
String themeId = PrefUtil.getAPIPreferenceStore().getString(
IWorkbenchPreferenceConstants.CURRENT_THEME_ID);
if (themeId == null) // missing preference
setCurrentTheme(IThemeManager.DEFAULT_THEME);
else {
setCurrentTheme(themeId);
if (currentTheme == null) { // still null - the preference
// didn't resolve to a proper theme
setCurrentTheme(IThemeManager.DEFAULT_THEME);
StatusManager
.getManager()
.handle(
StatusUtil
.newStatus(
PlatformUI.PLUGIN_ID,
"Could not restore current theme: " + themeId, null)); //$NON-NLS-1$
}
}
}
return currentTheme;
}
/**
* Return the default color registry.
*
* @return the default color registry
*/
public ColorRegistry getDefaultThemeColorRegistry() {
return defaultThemeColorRegistry;
}
/**
* Return the default font registry.
*
* @return the default font registry
*/
public FontRegistry getDefaultThemeFontRegistry() {
return defaultThemeFontRegistry;
}
private ITheme getTheme(IThemeDescriptor td) {
ITheme theme = (ITheme) themes.get(td);
if (theme == null) {
theme = new Theme(td);
themes.put(td, theme);
}
return theme;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.themes.IThemeManager#getTheme(java.lang.String)
*/
public ITheme getTheme(String id) {
if (id.equals(IThemeManager.DEFAULT_THEME)) {
return getTheme((IThemeDescriptor) null);
}
IThemeDescriptor td = getThemeRegistry().findTheme(id);
if (td == null) {
return null;
}
return getTheme(td);
}
/**
* Answer the IThemeRegistry for the Workbench
*/
private IThemeRegistry getThemeRegistry() {
if (themeRegistry == null) {
themeRegistry = WorkbenchPlugin.getDefault().getThemeRegistry();
}
return themeRegistry;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.themes.IThemeManager#removePropertyChangeListener(org.eclipse.jface.util.IPropertyChangeListener)
*/
public void removePropertyChangeListener(IPropertyChangeListener listener) {
removeListenerObject(listener);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.themes.IThemeManager#setCurrentTheme(java.lang.String)
*/
public void setCurrentTheme(String id) {
ITheme oldTheme = currentTheme;
if (WorkbenchThemeManager.getInstance().doSetCurrentTheme(id)) {
firePropertyChange(CHANGE_CURRENT_THEME, oldTheme,
getCurrentTheme());
if (oldTheme != null) {
oldTheme.removePropertyChangeListener(currentThemeListener);
}
currentTheme.addPropertyChangeListener(currentThemeListener);
// update the preference if required.
if (!PrefUtil.getAPIPreferenceStore().getString(
IWorkbenchPreferenceConstants.CURRENT_THEME_ID).equals(id)) {
PrefUtil.getAPIPreferenceStore().setValue(
IWorkbenchPreferenceConstants.CURRENT_THEME_ID, id);
PrefUtil.saveAPIPrefs();
}
// update the jface registries
{
ColorRegistry jfaceColors = JFaceResources.getColorRegistry();
ColorRegistry themeColors = currentTheme.getColorRegistry();
for (Iterator i = themeColors.getKeySet().iterator(); i
.hasNext();) {
String key = (String) i.next();
jfaceColors.put(key, themeColors.getRGB(key));
}
}
{
FontRegistry jfaceFonts = JFaceResources.getFontRegistry();
FontRegistry themeFonts = currentTheme.getFontRegistry();
for (Iterator i = themeFonts.getKeySet().iterator(); i
.hasNext();) {
String key = (String) i.next();
jfaceFonts.put(key, themeFonts.getFontData(key));
}
}
}
}
}