diff options
Diffstat (limited to 'plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus')
6 files changed, 971 insertions, 478 deletions
diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/engine/WorkspaceCSSEngine.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/engine/WorkspaceCSSEngine.java index f01dfca3c52..c0c64096067 100644 --- a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/engine/WorkspaceCSSEngine.java +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/engine/WorkspaceCSSEngine.java @@ -1,71 +1,97 @@ -/*****************************************************************************
- * Copyright (c) 2012 CEA LIST.
- *
- * 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:
- * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
- *****************************************************************************/
-package org.eclipse.papyrus.infra.gmfdiag.css.engine;
-
-import java.net.URL;
-
-import org.eclipse.e4.ui.css.core.dom.IElementProvider;
-import org.eclipse.e4.ui.css.core.engine.CSSElementContext;
-import org.eclipse.papyrus.infra.gmfdiag.css.theme.ThemeManager;
-import org.w3c.dom.Element;
-
-/**
- * A Singleton CSSEngine, handling the CSS stylesheets applied to the whole
- * workspace.
- *
- * This Engine is a child of the BaseCSSEngine.
- *
- * It should not be used directly.
- *
- * @author Camille Letavernier
- *
- * @see DiagramCSSEngine
- */
-@SuppressWarnings("restriction")
-public class WorkspaceCSSEngine extends ExtendedCSSEngineImpl {
-
- private WorkspaceCSSEngine() {
- super(BaseCSSEngine.INSTANCE);
- }
-
- public static ExtendedCSSEngine instance = new WorkspaceCSSEngine();
-
- @Override
- protected void reloadStyleSheets() {
- styleSheetURLs.clear();
- for(URL styleSheetURL : ThemeManager.instance.getWorkspaceStyleSheets()) {
- styleSheetURLs.add(styleSheetURL);
- }
- }
-
- //Unsupported operations. The WorkspaceCSSEngine should never be used directly.
-
- @Override
- public Element getElement(Object node) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public IElementProvider getElementProvider() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setElementProvider(IElementProvider elementProvider) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public CSSElementContext getCSSElementContext(Object node) {
- throw new UnsupportedOperationException();
- }
-}
+/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.net - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.css.engine; + +import java.net.MalformedURLException; +import java.net.URL; + +import org.eclipse.core.resources.IFile; +import org.eclipse.e4.ui.css.core.dom.IElementProvider; +import org.eclipse.e4.ui.css.core.engine.CSSElementContext; +import org.eclipse.papyrus.infra.gmfdiag.css.Activator; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.StyleSheet; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.StyleSheetReference; +import org.eclipse.papyrus.infra.gmfdiag.css.theme.ThemeManager; +import org.eclipse.papyrus.infra.widgets.util.FileUtil; +import org.w3c.dom.Element; + +/** + * A Singleton CSSEngine, handling the CSS stylesheets applied to the whole + * workspace. + * + * This Engine is a child of the BaseCSSEngine. + * + * It should not be used directly. + * + * @author Camille Letavernier + * + * @see DiagramCSSEngine + */ +@SuppressWarnings("restriction") +public class WorkspaceCSSEngine extends ExtendedCSSEngineImpl { + + private WorkspaceCSSEngine() { + super(BaseCSSEngine.INSTANCE); + } + + public static ExtendedCSSEngine instance = new WorkspaceCSSEngine(); + + @Override + protected void reloadStyleSheets() { + styleSheetURLs.clear(); + styleSheets.clear(); + for(StyleSheet styleSheet : ThemeManager.instance.getWorkspaceStyleSheets()) { + + if(styleSheet instanceof StyleSheetReference) { + IFile iFile = FileUtil.getIFile(((StyleSheetReference)styleSheet).getPath()); + if(iFile != null) { + styleSheets.add(styleSheet); + } else { + try { + + URL styleSheetURL = new URL(((StyleSheetReference)styleSheet).getPath()); + styleSheetURLs.add(styleSheetURL); + } catch (MalformedURLException e) { + Activator.log.error(e); + } + } + + } else { + styleSheets.add(styleSheet); + } + + } + } + + //Unsupported operations. The WorkspaceCSSEngine should never be used directly. + + @Override + public Element getElement(Object node) { + throw new UnsupportedOperationException(); + } + + @Override + public IElementProvider getElementProvider() { + throw new UnsupportedOperationException(); + } + + @Override + public void setElementProvider(IElementProvider elementProvider) { + throw new UnsupportedOperationException(); + } + + @Override + public CSSElementContext getCSSElementContext(Object node) { + throw new UnsupportedOperationException(); + } +} diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/helper/WorkspaceThemesHelper.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/helper/WorkspaceThemesHelper.java new file mode 100644 index 00000000000..73be411d40c --- /dev/null +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/helper/WorkspaceThemesHelper.java @@ -0,0 +1,302 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * 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: + * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.net - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.css.helper; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.IPath; +import org.eclipse.emf.common.CommonPlugin; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.ecore.xmi.XMIResource; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.papyrus.infra.gmfdiag.css.Activator; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.StyleSheetReference; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.StylesheetsFactory; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.StylesheetsPackage; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.Theme; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.WorkspaceThemes; + + + +/** + * Helper to define a theme from CSS style sheet file. + * + * @author gpascual + * + */ +public class WorkspaceThemesHelper { + + + /** + * Default constructor. + * + */ + public WorkspaceThemesHelper() { + } + + /** + * Define a theme from selected files. + * <p> + * FIXME User could select several CSS files to create a theme + * <P> + * + * @param file + */ + public Theme defineCSSStyleSheetFilesAsTheme(IStructuredSelection selection) { + List<IFile> selectedCSSFilesList = new ArrayList<IFile>(); + + // Extract file from selection + Iterator<?> selectionIterator = selection.iterator(); + + while(selectionIterator.hasNext()) { + Object next = selectionIterator.next(); + if(next instanceof IFile) { + selectedCSSFilesList.add((IFile)next); + } + } + + // Create a theme from selected CSS file + Theme theme = createThemeFromSelection(selectedCSSFilesList); + theme.setId(EcoreUtil.generateUUID()); + + return theme; + + } + + /** + * Method to persist deleted and edited theme in workspace preference file. + * + * @param editedThemesArray + * Array of edited themes to persist + * @param deletedThemesArray + * Array of deleted theme to persist + */ + public void saveWorkspaceThemesPreferenceResource(Theme[] editedThemesArray, Theme[] deletedThemesArray) { + + // Get current resource of workspace theme preferences + Resource currentThemefile = findThemeFile(); + WorkspaceThemes workspaceThemes = (WorkspaceThemes)EcoreUtil.getObjectByType(currentThemefile.getContents(), StylesheetsPackage.Literals.WORKSPACE_THEMES); + + // Handle edited themes + for(Theme editedTheme : editedThemesArray) { + boolean updateResult = updateWorkspaceTheme(editedTheme, workspaceThemes); + + // If update haven't done, theme must be added + if(!updateResult) { + workspaceThemes.getThemes().add(editedTheme); + } + } + + // Handle deleted themes + for(Theme deletedTheme : deletedThemesArray) { + removeWorkspaceTheme(deletedTheme, workspaceThemes); + } + + // Save edited preference file + saveResource(currentThemefile); + + } + + /** + * Method to delete a theme in workspace theme. + * + * @param deletedTheme + * Theme to delete + * @param workspaceThemes + * Current workspace themes + */ + private void removeWorkspaceTheme(Theme deletedTheme, WorkspaceThemes workspaceThemes) { + // Search resource value of edited theme + Iterator<Theme> currentThemesIterator = workspaceThemes.getThemes().iterator(); + Theme themeId = null; + boolean found = false; + + while(currentThemesIterator.hasNext() && !found) { + themeId = currentThemesIterator.next(); + found = themeId.getId().equals(deletedTheme.getId()); + } + + if(found) { + // Replace in resource the current value with the edited one and save resource + EcoreUtil.remove(workspaceThemes, StylesheetsPackage.eINSTANCE.getWorkspaceThemes_Themes(), themeId); + } + + + + } + + /** + * Replace in current workspace themes resource theme with the edited value. + * + * @param editedTheme + * New theme value + */ + public void saveWorkspaceThemesPreferenceResource(Theme editedTheme) { + // Get current resource of workspace theme preferences + Resource currentThemefile = findThemeFile(); + WorkspaceThemes workspaceThemes = (WorkspaceThemes)EcoreUtil.getObjectByType(currentThemefile.getContents(), StylesheetsPackage.Literals.WORKSPACE_THEMES); + + updateWorkspaceTheme(editedTheme, workspaceThemes); + + saveResource(currentThemefile); + } + + /** + * + * Update in current workspace themes resource the theme with the edited one. + * + * @param editedTheme + * Theme with new value + * @param workspaceThemes + * workspace themes + */ + private boolean updateWorkspaceTheme(Theme editedTheme, WorkspaceThemes workspaceThemes) { + // Search resource value of edited theme + Iterator<Theme> currentThemesIterator = workspaceThemes.getThemes().iterator(); + Theme themeId = null; + boolean found = false; + + while(currentThemesIterator.hasNext() && !found) { + themeId = currentThemesIterator.next(); + found = themeId.getId().equals(editedTheme.getId()); + } + + if(found) { + // Replace in resource the current value with the edited one and save resource + EcoreUtil.replace(workspaceThemes, StylesheetsPackage.eINSTANCE.getWorkspaceThemes_Themes(), themeId, editedTheme); + } + + return found; + } + + /** + * Save style sheets EMF Resource. + * + * @param styleSheetsResource + * + */ + private void saveResource(Resource styleSheetsResource) { + // Save theme preference file + if(styleSheetsResource != null) { + try { + Map<String, Object> options = new HashMap<String, Object>(); + options.put(XMIResource.XMI_ID, Boolean.TRUE); + styleSheetsResource.save(options); + } catch (IOException e) { + Activator.log.error(e); + } + } + } + + + /** + * Save theme in workspace preferences. + * + * @param theme + * Theme to save + */ + public void saveNewThemeWorkspacePreference(Theme theme) { + Resource themeFile = theme.eResource(); + + if(themeFile == null) { + themeFile = findThemeFile(); + } + + // Get workspace themes + WorkspaceThemes workspaceThemes = (WorkspaceThemes)EcoreUtil.getObjectByType(themeFile.getContents(), StylesheetsPackage.eINSTANCE.getWorkspaceThemes()); + + // Create a workspace themes root + if(workspaceThemes == null) { + workspaceThemes = StylesheetsFactory.eINSTANCE.createWorkspaceThemes(); + themeFile.getContents().add(workspaceThemes); + } + + // Add created theme + workspaceThemes.getThemes().add(theme); + + saveResource(themeFile); + + } + + /** + * Created a style sheets theme from project selection. + * + * @param selectedCSSFilesList + * @return + */ + private Theme createThemeFromSelection(List<IFile> selectedCSSFilesList) { + + // Factory to create necessary elements + StylesheetsFactory styleSheetsFactory = StylesheetsFactory.eINSTANCE; + + // Create new theme + Theme newTheme = styleSheetsFactory.createTheme(); + + for(IFile cssFile : selectedCSSFilesList) { + + //Style sheets to add in theme + StyleSheetReference styleSheetsReference = styleSheetsFactory.createStyleSheetReference(); + styleSheetsReference.setPath(cssFile.getFullPath().toString()); + newTheme.getStylesheets().add(styleSheetsReference); + } + return newTheme; + } + + /** + * Look for theme workspace preferences file. + * + * @return Created resource if it don't exist, otherwise loaded + */ + private Resource findThemeFile() { + + IPath themeFilePath = getThemeWorkspacePreferenceFilePath(); + + // Create associated URI + URI resolvedURI = CommonPlugin.resolve(URI.createFileURI(themeFilePath.toOSString())); + + // Create EMF resource + ResourceSet resourceSet = new ResourceSetImpl(); + Resource resource = null; + + if(themeFilePath.toFile().exists()) { + resource = resourceSet.getResource(resolvedURI, true); + } else { + resource = resourceSet.createResource(resolvedURI); + } + + return resource; + } + + /** + * Build path to access preference file. + * + * @return Path to theme.xmi file in workspace preference directory + */ + public IPath getThemeWorkspacePreferenceFilePath() { + // Get workspace path + IPath pluginStatePath = Activator.getDefault().getStateLocation(); + + // Build preference file path + IPath themeFilePath = pluginStatePath.append("theme.xmi"); + return themeFilePath; + } +} diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/preferences/ThemePreferenceInitializer.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/preferences/ThemePreferenceInitializer.java index 5e4956b2956..45e320fa97c 100644 --- a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/preferences/ThemePreferenceInitializer.java +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/preferences/ThemePreferenceInitializer.java @@ -1,25 +1,34 @@ -/*****************************************************************************
- * Copyright (c) 2012 CEA LIST.
- *
- * 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:
- * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
- *****************************************************************************/
-package org.eclipse.papyrus.infra.gmfdiag.css.preferences;
-
-import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
-
-//Unused
-public class ThemePreferenceInitializer extends AbstractPreferenceInitializer {
-
- @Override
- public void initializeDefaultPreferences() {
- // IPreferenceStore store = Activator.getDefault().getPreferenceStore();
- // store.setDefault(ThemePreferencesPage.CURRENT_THEME, null);
- }
-
-}
+/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Gabriel Pascual (ALL4TEC) - Initial API and Implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.css.preferences; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.papyrus.infra.gmfdiag.css.Activator; + + +/** + * Theme preference initializer. + * + * @author gpascual + * + */ +public class ThemePreferenceInitializer extends AbstractPreferenceInitializer { + + @Override + public void initializeDefaultPreferences() { + IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + store.setDefault(ThemePreferences.CURRENT_THEME, "org.eclipse.papyrus.css.papyrus_theme"); + } + +} diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/preferences/ThemePreferencesPage.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/preferences/ThemePreferencesPage.java deleted file mode 100644 index 0d1f24dd949..00000000000 --- a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/preferences/ThemePreferencesPage.java +++ /dev/null @@ -1,95 +0,0 @@ -/*****************************************************************************
- * Copyright (c) 2012 CEA LIST.
- *
- * 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:
- * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
- *****************************************************************************/
-package org.eclipse.papyrus.infra.gmfdiag.css.preferences;
-
-import java.util.List;
-
-import org.eclipse.jface.preference.ComboFieldEditor;
-import org.eclipse.jface.preference.FieldEditor;
-import org.eclipse.jface.preference.FieldEditorPreferencePage;
-import org.eclipse.jface.util.PropertyChangeEvent;
-import org.eclipse.papyrus.infra.gmfdiag.common.helper.DiagramHelper;
-import org.eclipse.papyrus.infra.gmfdiag.css.Activator;
-import org.eclipse.papyrus.infra.gmfdiag.css.engine.WorkspaceCSSEngine;
-import org.eclipse.papyrus.infra.gmfdiag.css.theme.Theme;
-import org.eclipse.papyrus.infra.gmfdiag.css.theme.ThemeManager;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.IWorkbenchPreferencePage;
-
-/**
- * A Preference page for selecting the Workspace CSS Theme
- *
- * @author Camille Letavernier
- */
-public class ThemePreferencesPage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
-
- public boolean needsRefresh = false;
-
- /**
- *
- * Constructor.
- *
- */
- public ThemePreferencesPage() {
- super("CSS Theme", org.eclipse.papyrus.infra.widgets.Activator.getDefault().getImageDescriptor("/icons/papyrus.png"), FLAT);
- }
-
- public void init(IWorkbench workbench) {
- setPreferenceStore(Activator.getDefault().getPreferenceStore());
- setDescription("Papyrus Theme preferences");
- }
-
- @Override
- protected void createFieldEditors() {
- String[][] themes = getFieldThemes();
- ComboFieldEditor editor = new ComboFieldEditor(ThemePreferences.CURRENT_THEME, "Current theme:", themes, getFieldEditorParent());
- addField(editor);
- }
-
- @Override
- public void propertyChange(PropertyChangeEvent event) {
- super.propertyChange(event);
- if(ThemePreferences.CURRENT_THEME.equals(event.getProperty())) {
- needsRefresh = true;
- }
- if(FieldEditor.VALUE.equals(event.getProperty())) {
- if(ThemePreferences.CURRENT_THEME.equals(((FieldEditor)event.getSource()).getPreferenceName())) {
- needsRefresh = true;
- }
- }
- }
-
- @Override
- public boolean performOk() {
- boolean result = super.performOk();
- if(needsRefresh) {
- WorkspaceCSSEngine.instance.reset();
- DiagramHelper.setNeedsRefresh();
- DiagramHelper.refreshDiagrams();
- }
- return result;
- }
-
- protected String[][] getFieldThemes() {
- List<Theme> themes = ThemeManager.instance.getThemes();
-
- String[][] result = new String[themes.size()][2];
- int i = 0;
- for(Theme theme : themes) {
- result[i][0] = theme.getLabel();
- result[i][1] = theme.getId();
- i++;
- }
- return result;
- }
-
-}
diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/theme/Theme.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/theme/Theme.java deleted file mode 100644 index 91e2172dc61..00000000000 --- a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/theme/Theme.java +++ /dev/null @@ -1,67 +0,0 @@ -/*****************************************************************************
- * Copyright (c) 2012 CEA LIST.
- *
- * 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:
- * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
- *****************************************************************************/
-package org.eclipse.papyrus.infra.gmfdiag.css.theme;
-
-import java.net.URL;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.eclipse.swt.graphics.Image;
-
-/**
- * A CSS Theme descriptor
- *
- * @author Camille Letavernier
- */
-public class Theme {
-
- private String label;
-
- private Image icon;
-
- private final String id;
-
- private final List<URL> styleSheets;
-
- public Theme(String id) {
- this.id = id;
- this.styleSheets = new LinkedList<URL>();
- }
-
- public String getLabel() {
- return label == null || "".equals(label) ? id : label;
- }
-
- public void setLabel(String label) {
- this.label = label;
- }
-
- public Image getIcon() {
- return icon;
- }
-
- public void setIcon(Image icon) {
- this.icon = icon;
- }
-
- public String getId() {
- return id;
- }
-
- public void addStyleSheet(URL url) {
- styleSheets.add(url);
- }
-
- public List<URL> getStyleSheets() {
- return styleSheets;
- }
-}
diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/theme/ThemeManager.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/theme/ThemeManager.java index d7ca686c397..a01d7fdf426 100644 --- a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/theme/ThemeManager.java +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css/src/org/eclipse/papyrus/infra/gmfdiag/css/theme/ThemeManager.java @@ -1,220 +1,538 @@ -/*****************************************************************************
- * Copyright (c) 2012 CEA LIST.
- *
- * 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:
- * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
- *****************************************************************************/
-package org.eclipse.papyrus.infra.gmfdiag.css.theme;
-
-import java.io.IOException;
-import java.net.URL;
-import java.text.Collator;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.core.runtime.IConfigurationElement;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.jface.preference.IPersistentPreferenceStore;
-import org.eclipse.jface.preference.IPreferenceStore;
-import org.eclipse.papyrus.infra.gmfdiag.css.Activator;
-import org.eclipse.papyrus.infra.gmfdiag.css.preferences.ThemePreferences;
-import org.eclipse.swt.graphics.Image;
-
-/**
- * A Singleton to manage CSS Themes. Reads Themes from an extension point,
- * and provides an access to them.
- *
- * @author Camille Letavernier
- *
- */
-public class ThemeManager {
-
- public static String EXTENSION_ID = Activator.PLUGIN_ID + ".theme";
-
- public static ThemeManager instance = new ThemeManager();
-
- private Map<String, Theme> allThemes;
-
- /**
- * Returns all the Themes, sorted alphabetically
- *
- * @return
- */
- public List<Theme> getThemes() {
- List<Theme> sortedThemes = new LinkedList<Theme>(getAllThemes().values());
- Collections.sort(sortedThemes, ThemeComparator.instance);
- return sortedThemes;
- }
-
- /**
- * Returns the list of the workspace stylesheet's URLs.
- *
- * @return
- */
- public List<URL> getWorkspaceStyleSheets() {
- Theme current = findCurrentTheme();
- if(current == null) {
- return Collections.emptyList();
- }
- return current.getStyleSheets();
- }
-
- /**
- * Returns the theme associated to the given id, or null if it doesn't
- * exist
- *
- * @param themeId
- * @return
- */
- public Theme getTheme(String themeId) {
- return getAllThemes().get(themeId);
- }
-
- private Map<String, Theme> getAllThemes() {
- if(allThemes == null) {
- allThemes = new LinkedHashMap<String, Theme>(); //Keep the themes ordered, to avoid nondeterministic behavior
- allThemes.put(EmptyTheme.instance.getId(), EmptyTheme.instance);
- IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(EXTENSION_ID);
-
- loadThemeDefinitions(config);
- loadThemeContributions(config);
- }
-
- return allThemes;
- }
-
- private void loadThemeDefinitions(IConfigurationElement[] config) {
- for(IConfigurationElement themeConfig : config) {
- if(!themeConfig.getName().equals("themeDefinition")) {
- continue;
- }
-
- final String themeId = themeConfig.getAttribute("id");
- if(themeId == null) {
- Activator.log.warn("Cannot define a CSS Theme with an empty id (Contributed by " + themeConfig.getContributor() + ")");
- continue;
- }
- Theme theme = new Theme(themeId);
-
- String themeLabel = themeConfig.getAttribute("label");
- theme.setLabel(themeLabel);
-
- String themeIcon = themeConfig.getAttribute("icon");
- if(themeIcon != null) {
- //FIXME: Use the Papyrus Image service when it is available
- Image icon = org.eclipse.papyrus.infra.widgets.Activator.getDefault().getImage(themeConfig.getContributor().getName(), themeIcon);
- if(icon != null) {
- theme.setIcon(icon);
- }
- }
-
- allThemes.put(themeId, theme);
- }
- }
-
- private void loadThemeContributions(IConfigurationElement[] config) {
- for(IConfigurationElement themeConfig : config) {
- if(!themeConfig.getName().equals("themeContribution")) {
- continue;
- }
-
- final String themeId = themeConfig.getAttribute("id");
- if(themeId == null || !allThemes.containsKey(themeId)) {
- Activator.log.warn("Cannot contribute to an undefined theme: " + themeId);
- continue;
- }
-
- Theme theme = allThemes.get(themeId);
-
- IConfigurationElement[] stylesheets = themeConfig.getChildren("stylesheet");
- for(IConfigurationElement stylesheetConfig : stylesheets) {
- String path = stylesheetConfig.getAttribute("stylesheetPath");
- try {
- URL url = new URL("platform:/plugin/" + themeConfig.getContributor().getName() + "/" + path);
- theme.addStyleSheet(url);
- } catch (IOException ex) {
- Activator.log.error(ex);
- }
- }
- }
- }
-
- private Theme findCurrentTheme() {
- IPreferenceStore store = Activator.getDefault().getPreferenceStore();
-
- if(store.contains(ThemePreferences.CURRENT_THEME)) {
- String themeId = store.getString(ThemePreferences.CURRENT_THEME);
- Theme theme = getAllThemes().containsKey(themeId) ? getAllThemes().get(themeId) : EmptyTheme.instance;
- return theme;
- }
-
- //The theme has not been defined: return the first one, and store it
- List<Theme> sortedThemes = new ArrayList<Theme>(getAllThemes().values());
- if(sortedThemes.size() < 2) {
- return EmptyTheme.instance;
- }
-
- //Index 0 is EmptyTheme ; we return the first non-empty theme
- Theme theme = sortedThemes.get(1);
- store.setValue(ThemePreferences.CURRENT_THEME, theme.getId());
- try {
- ((IPersistentPreferenceStore)store).save();
- } catch (IOException e) {
- Activator.log.error(e);
- }
- return theme;
- }
-
- public static class EmptyTheme extends Theme {
-
- public static Theme instance = new EmptyTheme();
-
- private EmptyTheme() {
- super("none"); //$NON-NLS-1$
- setLabel("No theme");
- Image icon = org.eclipse.papyrus.infra.widgets.Activator.getDefault().getImage("icons/Delete_12x12.gif");
- setIcon(icon);
- }
- }
-
- /**
- * Sorts the Themes alphabetically (Based on their label). The Empty theme
- * is always the first element.
- *
- * @author Camille Letavernier
- */
- private static class ThemeComparator implements Comparator<Theme> {
-
- private ThemeComparator() {
- }
-
- @Override
- public int compare(Theme o1, Theme o2) {
- if(o1 == EmptyTheme.instance) {
- return -1;
- }
- if(o2 == EmptyTheme.instance) {
- return 1;
- }
-
- return Collator.getInstance().compare(o1.getLabel(), o2.getLabel());
- }
-
- public static Comparator<Theme> instance = new ThemeComparator();
-
- }
-
- private ThemeManager() {
-
- }
-}
+/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.net - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.css.theme; + +import java.io.IOException; +import java.net.URL; +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.emf.common.CommonPlugin; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.jface.preference.IPersistentPreferenceStore; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.papyrus.infra.gmfdiag.css.Activator; +import org.eclipse.papyrus.infra.gmfdiag.css.helper.WorkspaceThemesHelper; +import org.eclipse.papyrus.infra.gmfdiag.css.preferences.ThemePreferences; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.StyleSheet; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.StyleSheetReference; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.StylesheetsFactory; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.StylesheetsPackage; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.Theme; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.WorkspaceThemes; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.impl.ThemeImpl; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.PlatformUI; + +/** + * A Singleton to manage CSS Themes. Reads Themes from an extension point + * and provides an access to them. + * + * @author Camille Letavernier + * + */ +public class ThemeManager { + + /** Extension point ID. */ + public static String EXTENSION_ID = Activator.PLUGIN_ID + ".theme"; + + /** Unique instance of manager. */ + public static ThemeManager instance = new ThemeManager(); + + /** All found themes in application. */ + private Map<String, Theme> allThemes = null; + + /** Unsaved themes. */ + private List<Theme> temporaryThemesList = new ArrayList<Theme>(); + + /** Themes to delete. */ + private List<Theme> deletedThemesList = new ArrayList<Theme>(); + + /** Workspace themes helper. */ + private WorkspaceThemesHelper workspaceThemesHelper = new WorkspaceThemesHelper(); + + /** + * Default constructor. + */ + private ThemeManager() { + //Singleton + } + + /** + * Returns all the Themes, sorted alphabetically + * + * @return + */ + public List<Theme> getThemes() { + List<Theme> sortedThemes = new LinkedList<Theme>(getAllThemes().values()); + Collections.sort(sortedThemes, ThemeComparator.instance); + + return sortedThemes; + } + + /** + * Returns the list of the workspace stylesheet's URLs. + * + * @return + */ + public List<StyleSheet> getWorkspaceStyleSheets() { + Theme current = findCurrentTheme(); + if(current == null) { + return Collections.emptyList(); + } + return current.getStylesheets(); + } + + /** + * Returns the theme associated to the given id, or <code>null</code> if it doesn't + * exist + * + * @param themeId + * @return + */ + public Theme getTheme(String themeId) { + return getAllThemes().get(themeId); + } + + /** + * Permit to reload known themes list. + */ + public void reloadThemes() { + allThemes = null; + } + + /** + * Refresh known themes list by merging states of themes. + */ + public void refreshThemes() { + + // Handle added themes + for(Theme addedTheme : temporaryThemesList) { + + String key = addedTheme.getId(); + if(!allThemes.containsKey(key)) { + allThemes.put(key, addedTheme); + } + } + + // Handle deleted themes + for(Theme deletedTheme : deletedThemesList) { + String key = deletedTheme.getId(); + if(allThemes.containsKey(key)) { + allThemes.remove(key); + } + } + + } + + + /** + * Clean temporary list of themes. + */ + public void clearTemporaryThemes() { + temporaryThemesList.clear(); + } + + /** + * Clean deleted theme list. + */ + public void clearDeletedThemes() { + deletedThemesList.clear(); + } + + /** + * Add a temporary theme. + * + * @param temporaryTheme + * Theme to add in workspace themes preference + * + */ + public void addTemporaryTheme(Theme temporaryTheme) { + temporaryThemesList.add(temporaryTheme); + } + + /** + * Delete theme from preferences. + * + * @param theme + * Theme to delete + */ + public void delete(Theme theme) { + + // If theme is temporary don't maintain in associated list + if(temporaryThemesList.contains(theme)) { + temporaryThemesList.remove(theme); + } else { + // Else store in a list to be able to cancel + deletedThemesList.add(theme); + } + } + + /** + * Get icon from a theme. Icon can register with plugin URI or file URI. + * + * @param theme + * Theme which can have an icon + * @return Loaded image, otherwise <code>null</code> + */ + public Image getThemeIcon(Theme theme) { + Image icon = null; + + + String iconPath = theme.getIcon(); + if(iconPath != null) { + + // First : looking for theme in contribution + IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(EXTENSION_ID); + icon = handleThemeDefinition(theme, config); + + // Second : Try to load image from its path + if(icon == null) { + + // Test path to icon + IPath path = new Path(iconPath); + if(path.toFile().exists()) { + icon = new Image(PlatformUI.getWorkbench().getDisplay(), iconPath); + } + + } + } + + return icon; + } + + /** + * Return only workspace themes preference. + * + * @return Workspace themes preference (instance of {@link WorkspaceThemes}) if it exist, otherwise <code>null</code> + */ + public WorkspaceThemes getWorkspaceThemesPreferences() { + WorkspaceThemes workspaceThemes = null; + + + // Get path of preference file + IPath path = workspaceThemesHelper.getThemeWorkspacePreferenceFilePath(); + + // If file exist, themes can load + if(path.toFile().exists()) { + // Resolve URI + URI fileURI = CommonPlugin.resolve(URI.createFileURI(path.toOSString())); + + // Create associated resource + ResourceSet resourceSet = new ResourceSetImpl(); + + Resource resource = resourceSet.getResource(fileURI, true); + + + // Get workspace theme + workspaceThemes = (WorkspaceThemes)EcoreUtil.getObjectByType(resource.getContents(), StylesheetsPackage.eINSTANCE.getWorkspaceThemes()); + } + + return workspaceThemes; + + } + + /** + * Know if theme is editable. Only themes of workspace or temporary can be edited. + * + * @param id + * Id of theme to check + * @return <code>true</code> if theme can be edited, otherwise <code>false<code> + */ + public boolean isEditable(String id) { + boolean isEditable = false; + + WorkspaceThemes workspacePreference = getWorkspaceThemesPreferences(); + if(workspacePreference != null) { + + // Check if theme existing in temporary + isEditable = temporaryThemesList.contains(allThemes.get(id)); + + //Check if theme comes from workspace preferences + Iterator<Theme> themesIterator = workspacePreference.getThemes().iterator(); + while(themesIterator.hasNext() && !isEditable) { + isEditable = id.equals(themesIterator.next().getId()); + } + + + } + + return isEditable; + } + + /** + * Persist state of the manager. + */ + public void persist() { + Theme[] editableThemes = getEditableThemes(); + workspaceThemesHelper.saveWorkspaceThemesPreferenceResource(editableThemes, deletedThemesList.toArray(new Theme[deletedThemesList.size()])); + + // Reset manager + allThemes = null; + deletedThemesList.clear(); + temporaryThemesList.clear(); + } + + /** + * @return + */ + private Theme[] getEditableThemes() { + List<Theme> editableThemeList = new ArrayList<Theme>(); + + for(Theme theme : allThemes.values()) { + if(isEditable(theme.getId())) { + editableThemeList.add(theme); + } + } + return editableThemeList.toArray(new Theme[editableThemeList.size()]); + } + + /** + * Look for corresponding theme in theme definition contribution and load its image. + * + * @param theme + * Theme to find in all contribution + * @param config + * Configuration of all theme contribution + * @return Loaded image if theme is came from contribution, otherwise <code>null</code> + */ + private Image handleThemeDefinition(Theme theme, IConfigurationElement[] config) { + Image icon = null; + + for(IConfigurationElement themeContribution : config) { + + // Verify that contribution is a theme definition + if(!themeContribution.getName().equals("themeDefinition")) { + continue; + } + + // Get label and Id of definition to compare to parameter + String themeId = themeContribution.getAttribute("id"); + String themeLabel = themeContribution.getAttribute("label"); + + if(themeId != null && themeId.equals(theme.getId()) && themeLabel != null && themeLabel.equals(theme.getLabel())) { + //FIXME: Use the Papyrus Image service when it is available + icon = org.eclipse.papyrus.infra.widgets.Activator.getDefault().getImage(themeContribution.getContributor().getName(), theme.getIcon()); + } + } + + return icon; + } + + private Map<String, Theme> getAllThemes() { + if(allThemes == null) { + allThemes = new LinkedHashMap<String, Theme>(); //Keep the themes ordered, to avoid nondeterministic behavior + allThemes.put(EmptyTheme.instance.getId(), EmptyTheme.instance); + IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(EXTENSION_ID); + + loadThemeDefinitions(config); + loadThemeContributions(config); + loadThemePreferenceWorkspace(); + loadTemporaryThemes(); + + // Remove deleted themes + for(Theme theme : deletedThemesList) { + String themeId = theme.getId(); + if(allThemes.containsKey(themeId)) { + allThemes.remove(themeId); + } + } + } + + return allThemes; + } + + /** + * Load theme definitions. + * + * @param config + * configuration of all contribution definition + */ + private void loadThemeDefinitions(IConfigurationElement[] config) { + + // For all theme definitions + for(IConfigurationElement themeConfig : config) { + + if(!themeConfig.getName().equals("themeDefinition")) { + continue; + } + + final String themeId = themeConfig.getAttribute("id"); + if(themeId == null) { + Activator.log.warn("Cannot define a CSS Theme with an empty id (Contributed by " + themeConfig.getContributor() + ")"); + continue; + } + + //Create theme + Theme theme = StylesheetsFactory.eINSTANCE.createTheme(); + theme.setId(themeId); + + String themeLabel = themeConfig.getAttribute("label"); + theme.setLabel(themeLabel); + + String themeIcon = themeConfig.getAttribute("icon"); + if(themeIcon != null) { + + theme.setIcon(themeIcon); + + } + + allThemes.put(themeId, theme); + } + } + + /** + * Load theme contributions. + * + * @param config + * configuration of all contribution definition + */ + private void loadThemeContributions(IConfigurationElement[] config) { + for(IConfigurationElement themeConfig : config) { + + // Verify that + if(!themeConfig.getName().equals("themeContribution")) { + continue; + } + + final String themeId = themeConfig.getAttribute("id"); + if(themeId == null || !allThemes.containsKey(themeId)) { + Activator.log.warn("Cannot contribute to an undefined theme: " + themeId); + continue; + } + + Theme theme = allThemes.get(themeId); + + IConfigurationElement[] stylesheets = themeConfig.getChildren("stylesheet"); + for(IConfigurationElement stylesheetConfig : stylesheets) { + String path = stylesheetConfig.getAttribute("stylesheetPath"); + try { + URL url = new URL("platform:/plugin/" + themeConfig.getContributor().getName() + "/" + path); + StyleSheetReference styleSheet = StylesheetsFactory.eINSTANCE.createStyleSheetReference(); + styleSheet.setPath(url.toString()); + theme.getStylesheets().add(styleSheet); + } catch (IOException ex) { + Activator.log.error(ex); + } + } + } + } + + /** + * Load themes of workspace preference. + */ + private void loadThemePreferenceWorkspace() { + + WorkspaceThemes workspaceThemes = getWorkspaceThemesPreferences(); + + // If file exist, themes can load + if(workspaceThemes != null) { + + + // Add each themme to current list + for(Theme theme : workspaceThemes.getThemes()) { + allThemes.put(theme.getId(), theme); + } + + } + } + + /** + * Add temporary themes in current themes list. + */ + private void loadTemporaryThemes() { + for(Theme theme : temporaryThemesList) { + allThemes.put(theme.getId(), theme); + } + + } + + private Theme findCurrentTheme() { + IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + + if(store.contains(ThemePreferences.CURRENT_THEME)) { + String themeId = store.getString(ThemePreferences.CURRENT_THEME); + Theme theme = getAllThemes().containsKey(themeId) ? getAllThemes().get(themeId) : EmptyTheme.instance; + return theme; + } + + //The theme has not been defined: return the first one, and store it + List<Theme> sortedThemes = new ArrayList<Theme>(getAllThemes().values()); + if(sortedThemes.size() < 2) { + return EmptyTheme.instance; + } + + //Index 0 is EmptyTheme ; we return the first non-empty theme + Theme theme = sortedThemes.get(1); + store.setValue(ThemePreferences.CURRENT_THEME, theme.getId()); + try { + ((IPersistentPreferenceStore)store).save(); + } catch (IOException e) { + Activator.log.error(e); + } + return theme; + } + + public static class EmptyTheme extends ThemeImpl { + + public static Theme instance = new EmptyTheme(); + + private EmptyTheme() { + setId("none"); + setLabel("No theme"); + setIcon("icons/Delete_12x12.gif"); + } + } + + /** + * Sorts the Themes alphabetically (Based on their label). The Empty theme + * is always the first element. + * + * @author Camille Letavernier + */ + private static class ThemeComparator implements Comparator<Theme> { + + private ThemeComparator() { + } + + @Override + public int compare(Theme o1, Theme o2) { + if(o1 == EmptyTheme.instance) { + return -1; + } + if(o2 == EmptyTheme.instance) { + return 1; + } + + return Collator.getInstance().compare(o1.getLabel(), o2.getLabel()); + } + + public static Comparator<Theme> instance = new ThemeComparator(); + + } +} |