/******************************************************************************* * Copyright (c) 2004, 2007 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)); } } } } }