From 1c348bb3ee551cbe290aa2e7a122df180bdd57df Mon Sep 17 00:00:00 2001 From: cletavernie Date: Mon, 2 Apr 2012 09:33:06 +0000 Subject: 370797: [Theme] Papyrus should provide a support for CSS files on its diagrams https://bugs.eclipse.org/bugs/show_bug.cgi?id=370797 --- .../.classpath | 7 + .../.project | 28 ++ .../.settings/org.eclipse.jdt.core.prefs | 7 + .../META-INF/MANIFEST.MF | 23 ++ .../build.properties | 6 + .../icons/sourceEditor.gif | Bin 0 -> 353 bytes .../plugin.xml | 57 +++ .../infra/gmfdiag/css/configuration/Activator.java | 69 ++++ .../configuration/handler/CreateStyleHandler.java | 339 ++++++++++++++++++ .../configuration/handler/EditStyleHandler.java | 32 ++ .../configuration/handler/GMFToCSSConverter.java | 133 +++++++ .../configuration/handler/StyleCreationDialog.java | 393 +++++++++++++++++++++ 12 files changed, 1094 insertions(+) create mode 100644 plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/.classpath create mode 100644 plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/.project create mode 100644 plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/.settings/org.eclipse.jdt.core.prefs create mode 100644 plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/META-INF/MANIFEST.MF create mode 100644 plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/build.properties create mode 100644 plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/icons/sourceEditor.gif create mode 100644 plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/plugin.xml create mode 100644 plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/Activator.java create mode 100644 plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/CreateStyleHandler.java create mode 100644 plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/EditStyleHandler.java create mode 100644 plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/GMFToCSSConverter.java create mode 100644 plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/StyleCreationDialog.java (limited to 'plugins/infra/gmfdiag') diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/.classpath b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/.classpath new file mode 100644 index 00000000000..2d1a4302f04 --- /dev/null +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/.project b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/.project new file mode 100644 index 00000000000..1b939fb2cc4 --- /dev/null +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/.project @@ -0,0 +1,28 @@ + + + org.eclipse.papyrus.infra.gmfdiag.css.configuration + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/.settings/org.eclipse.jdt.core.prefs b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..44217f8c068 --- /dev/null +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/META-INF/MANIFEST.MF b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..566a644a919 --- /dev/null +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/META-INF/MANIFEST.MF @@ -0,0 +1,23 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: CSS Configuration +Bundle-SymbolicName: org.eclipse.papyrus.infra.gmfdiag.css.configuration;singleton:=true +Bundle-Version: 0.9.0.qualifier +Bundle-Activator: org.eclipse.papyrus.infra.gmfdiag.css.configuration.Activator +Bundle-Vendor: Eclipse Modeling Project +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.papyrus.infra.core.log;bundle-version="0.9.0", + org.eclipse.papyrus.infra.gmfdiag.common;bundle-version="0.9.0", + org.eclipse.papyrus.infra.gmfdiag.css.xtext;bundle-version="1.0.0", + org.eclipse.gmf.runtime.notation;bundle-version="1.5.0", + org.eclipse.gmf.runtime.draw2d.ui;bundle-version="1.5.0", + org.eclipse.draw2d;bundle-version="3.8.0", + org.eclipse.papyrus.infra.core;bundle-version="0.9.0", + org.eclipse.papyrus.infra.widgets;bundle-version="0.9.0", + org.eclipse.papyrus.infra.gmfdiag.css.properties;bundle-version="0.9.0", + org.eclipse.papyrus.infra.emf;bundle-version="0.9.0", + org.eclipse.papyrus.infra.gmfdiag.css.model;bundle-version="0.9.0", + org.eclipse.papyrus.infra.gmfdiag.css;bundle-version="0.9.0" +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-ActivationPolicy: lazy diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/build.properties b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/build.properties new file mode 100644 index 00000000000..285b8bf47b6 --- /dev/null +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/build.properties @@ -0,0 +1,6 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + icons/ diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/icons/sourceEditor.gif b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/icons/sourceEditor.gif new file mode 100644 index 00000000000..75ebdb85865 Binary files /dev/null and b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/icons/sourceEditor.gif differ diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/plugin.xml b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/plugin.xml new file mode 100644 index 00000000000..4c4cd0021d4 --- /dev/null +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/plugin.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/Activator.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/Activator.java new file mode 100644 index 00000000000..aac4232ff39 --- /dev/null +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/Activator.java @@ -0,0 +1,69 @@ +/***************************************************************************** + * 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.configuration; + +import org.eclipse.papyrus.infra.core.log.LogHelper; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.papyrus.infra.gmfdiag.css.configuration"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + public static LogHelper log; + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + log = new LogHelper(this); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + +} diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/CreateStyleHandler.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/CreateStyleHandler.java new file mode 100644 index 00000000000..81ede998d5f --- /dev/null +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/CreateStyleHandler.java @@ -0,0 +1,339 @@ +/***************************************************************************** + * 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.configuration.handler; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.emf.common.util.Enumerator; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.EEnum; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.gmf.runtime.draw2d.ui.figures.FigureUtilities; +import org.eclipse.gmf.runtime.notation.Diagram; +import org.eclipse.gmf.runtime.notation.NamedStyle; +import org.eclipse.gmf.runtime.notation.NotationPackage; +import org.eclipse.gmf.runtime.notation.Style; +import org.eclipse.gmf.runtime.notation.View; +import org.eclipse.gmf.runtime.notation.datatype.GradientData; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.papyrus.infra.core.services.ServiceException; +import org.eclipse.papyrus.infra.core.utils.ServiceUtilsForActionHandlers; +import org.eclipse.papyrus.infra.gmfdiag.common.helper.NotationHelper; +import org.eclipse.papyrus.infra.gmfdiag.css.ATTRIBUTE_OP; +import org.eclipse.papyrus.infra.gmfdiag.css.Attribute; +import org.eclipse.papyrus.infra.gmfdiag.css.AttributeValue; +import org.eclipse.papyrus.infra.gmfdiag.css.CompositeSelector; +import org.eclipse.papyrus.infra.gmfdiag.css.CssFactory; +import org.eclipse.papyrus.infra.gmfdiag.css.Declaration; +import org.eclipse.papyrus.infra.gmfdiag.css.Ruleset; +import org.eclipse.papyrus.infra.gmfdiag.css.SelectorCondition; +import org.eclipse.papyrus.infra.gmfdiag.css.SimpleSelector; +import org.eclipse.papyrus.infra.gmfdiag.css.Stylesheet; +import org.eclipse.papyrus.infra.gmfdiag.css.configuration.Activator; +import org.eclipse.papyrus.infra.gmfdiag.css.handler.CSSRefreshHandler; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.StyleSheet; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.StyleSheetReference; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.xtext.resource.XtextResourceSet; + + +public class CreateStyleHandler extends AbstractHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection selection; + try { + selection = ServiceUtilsForActionHandlers.getInstance().getNestedActiveIEditorPart().getSite().getSelectionProvider().getSelection(); + if(selection.isEmpty()) { + return null; + } + } catch (ServiceException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + + if(!(selection instanceof IStructuredSelection)) { + return null; + } + + IStructuredSelection sSelection = (IStructuredSelection)selection; + Object element = sSelection.getFirstElement(); + + View view = NotationHelper.findView(element); + if(view == null) { + Activator.log.warn("Cannot create a Style from the selected element ; the element is not a View"); + return null; + } + + Shell parentShell = ((Event)event.getTrigger()).widget.getDisplay().getActiveShell(); + + if(view.getElement() == null || view instanceof Diagram) { + MessageDialog.open(MessageDialog.WARNING, parentShell, "Style error", "The selected element's style cannot be exported", SWT.NONE); + return null; + } + + Map declarations = handleStyles(view); + Map conditions = handleSemantic(view); + + String selectorName = view.getElement().eClass().getName(); + + StyleCreationDialog dialog = new StyleCreationDialog(parentShell, conditions, declarations, selectorName, view); + if(dialog.open() != Dialog.OK) { + return null; + } + + Ruleset ruleset = CssFactory.eINSTANCE.createRuleset(); + SimpleSelector selector = CssFactory.eINSTANCE.createSimpleSelector(); + + if(dialog.useSelectorName()) { + selector.setElementName(selectorName); + } else { + selector.setElementName("*"); //$NON-NLS-1$ + } + + if(dialog.getDiagramRestriction()) { + String diagramType = view.getDiagram().getType(); + CompositeSelector compositeSelector = CssFactory.eINSTANCE.createCompositeSelector(); + compositeSelector.setRight(selector); + + SimpleSelector diagramSelector = CssFactory.eINSTANCE.createSimpleSelector(); + diagramSelector.setElementName(diagramType); + compositeSelector.setLeft(diagramSelector); + + ruleset.getSelectors().add(compositeSelector); + } else { + ruleset.getSelectors().add(selector); + } + + if(dialog.getCSSClass() != null) { + String cssClass = dialog.getCSSClass(); + org.eclipse.papyrus.infra.gmfdiag.css.Class classCondition = CssFactory.eINSTANCE.createClass(); + classCondition.setClass(cssClass); + selector.getCondition().add(classCondition); + } + + for(SelectorCondition condition : conditions.keySet()) { + if(conditions.get(condition)) { + selector.getCondition().add(condition); + } + } + + for(Declaration declaration : declarations.keySet()) { + if(declarations.get(declaration)) { + ruleset.getProperties().add(declaration); + } + } + + StyleSheet styleSheet = dialog.getStylesheet(); + if(styleSheet == null) { + MessageDialog.open(MessageDialog.ERROR, parentShell, "Stylesheet error", "Invalid stylesheet", SWT.NONE); + return null; + } + + ResourceSet resourceSet = new XtextResourceSet(); + Resource resource; + + if(styleSheet instanceof StyleSheetReference) { + //Supported pathes: + // //path/file.css (Workspace, platform:/resource/) + // relative/path/file.css (Relative) + String path = ((StyleSheetReference)styleSheet).getPath(); + if(!path.endsWith(".css")) { + //FIXME: The X-Text editor supports CSS Content Types, but it is not yet configured + //to automatically accept other extensions than *.css + //The parser should rely on the file's content type instead of the file extension + //Attemps to serialize to a custom extension (even an extension compatible with CSS Content Type) + //would result in xmi serialization. We'd better stop here. + MessageDialog.open(MessageDialog.ERROR, parentShell, "Stylesheet error", "The stylesheet must have the *.css extension", SWT.NONE); + return null; + } + URI uri; + if(path.startsWith("/")) { + uri = URI.createPlatformResourceURI(path, true); + } else { + uri = URI.createURI(path); + uri = uri.resolve(view.eResource().getURI()); + } + + try { + resource = resourceSet.getResource(uri, true); + } catch (Exception ex) { + resource = resourceSet.createResource(uri, "org.eclipse.wst.css.core.csssource"); + } + } else { + MessageDialog.open(MessageDialog.ERROR, parentShell, "Stylesheet error", "Embedded stylesheets are not yet supported", SWT.NONE); + return null; + } + + Stylesheet xtextStylesheet; + + if(resource.getContents().isEmpty()) { + xtextStylesheet = CssFactory.eINSTANCE.createStylesheet(); + xtextStylesheet.setCharset("UTF-8"); + resource.getContents().add(xtextStylesheet); + } else { + xtextStylesheet = (Stylesheet)resource.getContents().get(0); + } + + xtextStylesheet.getContents().add(ruleset); + + try { + resource.save(new HashMap()); + (new CSSRefreshHandler()).execute(null); + } catch (IOException ex) { + Activator.log.error(ex); + MessageDialog.open(MessageDialog.ERROR, parentShell, "Style error", "An unexpected error occured while trying to save the Stylesheet", SWT.NONE); + } catch (Exception ex) { + Activator.log.error(ex); + MessageDialog.open(MessageDialog.ERROR, parentShell, "Style error", "An unexpected error occured while trying to save the Stylesheet", SWT.NONE); + } + + return null; + } + + private Map handleStyles(View view) { + Map declarations = new LinkedHashMap(); + + for(Object styleObject : view.getStyles()) { + Style style = (Style)styleObject; + declarations.putAll(handleStyle(style)); + } + + if(view instanceof Style) { + declarations.putAll(handleStyle((Style)view)); + } + + return declarations; + } + + private Map handleSemantic(View view) { + Map result = new LinkedHashMap(); + + EObject semanticElement = view.getElement(); + + for(EStructuralFeature feature : semanticElement.eClass().getEAllStructuralFeatures()) { + if(isBoolean(feature) || isInteger(feature) || feature.getEType() instanceof EEnum) { + Attribute attributeCondition = CssFactory.eINSTANCE.createAttribute(); + attributeCondition.setName(feature.getName()); + + AttributeValue attributeValue = CssFactory.eINSTANCE.createAttributeValue(); + attributeValue.setOperator(ATTRIBUTE_OP.EQUALS); + attributeValue.setValue(semanticElement.eGet(feature).toString()); + attributeCondition.setValue(attributeValue); + + boolean check = semanticElement.eGet(feature) != feature.getDefaultValue(); + + result.put(attributeCondition, check); + } + } + + return result; + } + + private boolean isBoolean(EStructuralFeature feature) { + if(feature.getEType() == EcorePackage.eINSTANCE.getEBoolean() || feature.getEType() == EcorePackage.eINSTANCE.getEBooleanObject()) { + return true; + } + + if(feature.getEType() instanceof EDataType) { + EDataType datatype = (EDataType)feature.getEType(); + return datatype.getName().equals("Boolean"); + } + + return false; + } + + private boolean isString(EStructuralFeature feature) { + return feature.getEType() == EcorePackage.eINSTANCE.getEString(); + } + + private boolean isInteger(EStructuralFeature feature) { + if(feature.getEType() == EcorePackage.eINSTANCE.getEInt() || feature.getEType() == EcorePackage.eINSTANCE.getEIntegerObject()) { + return true; + } + + if(feature.getEType() instanceof EDataType) { + EDataType datatype = (EDataType)feature.getEType(); + return datatype.getName().equals("Integer"); + } + + return false; + } + + private Map handleStyle(Style style) { + if(style instanceof NamedStyle) { + return Collections.emptyMap(); + } + + Map declarations = new LinkedHashMap(); + + for(EStructuralFeature feature : style.eClass().getEAllStructuralFeatures()) { + if(NotationPackage.eINSTANCE.getStyle().isSuperTypeOf(feature.getEContainingClass())) { + boolean check = style.eGet(feature) != feature.getDefaultValue(); + declarations.put(handleStyleFeature(style, feature), check); + } + } + + return declarations; + } + + private Declaration handleStyleFeature(Style style, EStructuralFeature feature) { + Declaration declaration = CssFactory.eINSTANCE.createDeclaration(); + declaration.setProperty(feature.getName()); + + GMFToCSSConverter converter = GMFToCSSConverter.instance; + + if(isString(feature)) { + declaration.setExpression(converter.convert((String)style.eGet(feature))); + } + + if(isInteger(feature)) { + if(feature.getName().endsWith("Color")) { + declaration.setExpression(converter.convert(FigureUtilities.integerToColor((Integer)style.eGet(feature)))); + } else { + declaration.setExpression(converter.convert((Integer)style.eGet(feature))); + } + } + + if(feature.getEType() == NotationPackage.eINSTANCE.getGradientData()) { + declaration.setExpression(converter.convert((GradientData)style.eGet(feature))); + } + + if(feature.getEType() instanceof EEnum) { + declaration.setExpression(converter.convert((Enumerator)style.eGet(feature))); + } + + if(isBoolean(feature)) { + declaration.setExpression(converter.convert((Boolean)style.eGet(feature))); + } + + return declaration; + } + +} diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/EditStyleHandler.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/EditStyleHandler.java new file mode 100644 index 00000000000..7932fbe9665 --- /dev/null +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/EditStyleHandler.java @@ -0,0 +1,32 @@ +/***************************************************************************** + * 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.configuration.handler; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Shell; + + +public class EditStyleHandler extends AbstractHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + //TODO + Shell parentShell = ((Event)event.getTrigger()).widget.getDisplay().getActiveShell(); + MessageDialog.open(MessageDialog.WARNING, parentShell, "Edit style error", "This action is not yet supported", SWT.NONE); + return null; + } + +} diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/GMFToCSSConverter.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/GMFToCSSConverter.java new file mode 100644 index 00000000000..fdacd0d7190 --- /dev/null +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/GMFToCSSConverter.java @@ -0,0 +1,133 @@ +/***************************************************************************** + * 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.configuration.handler; + +import org.eclipse.emf.common.util.Enumerator; +import org.eclipse.gmf.runtime.draw2d.ui.figures.FigureUtilities; +import org.eclipse.gmf.runtime.notation.GradientStyle; +import org.eclipse.gmf.runtime.notation.datatype.GradientData; +import org.eclipse.papyrus.infra.gmfdiag.css.CssFactory; +import org.eclipse.papyrus.infra.gmfdiag.css.Expression; +import org.eclipse.papyrus.infra.gmfdiag.css.HexColor; +import org.eclipse.papyrus.infra.gmfdiag.css.Name; +import org.eclipse.papyrus.infra.gmfdiag.css.Number; +import org.eclipse.papyrus.infra.gmfdiag.css.StringValue; +import org.eclipse.papyrus.infra.gmfdiag.css.Subterm; +import org.eclipse.papyrus.infra.gmfdiag.css.Term; +import org.eclipse.papyrus.infra.gmfdiag.css.UNARY; +import org.eclipse.papyrus.infra.gmfdiag.css.UnaryOperator; +import org.eclipse.swt.graphics.Color; + + +public class GMFToCSSConverter { + + public static final GMFToCSSConverter instance = new GMFToCSSConverter(); + + private GMFToCSSConverter() { + + } + + public Expression convert(Color color) { + HexColor hexColor = getColor(color); + return getExpression(hexColor); + } + + private HexColor getColor(Color color) { + HexColor hexColor = CssFactory.eINSTANCE.createHexColor(); + + String hexString = twoDigitsHexString(color.getRed()) + twoDigitsHexString(color.getGreen()) + twoDigitsHexString(color.getBlue()); + hexColor.setValue(hexString.toUpperCase()); + return hexColor; + } + + private HexColor getColor(int color) { + return getColor(FigureUtilities.integerToColor(color)); + } + + private String twoDigitsHexString(int color) { + String hexString = Integer.toHexString(color); + if(hexString.length() < 2) { + hexString = "0" + hexString; + } + return hexString; + } + + public Expression convert(GradientData gradient) { + if(gradient == null) { + Name noGradient = CssFactory.eINSTANCE.createName(); + noGradient.setValue("none"); + return getExpression(noGradient); + } + + HexColor gradientColor = getColor(gradient.getGradientColor1()); + + Name gradientStyle = CssFactory.eINSTANCE.createName(); + int style = gradient.getGradientStyle(); + + if(style == GradientStyle.HORIZONTAL) { + gradientStyle.setValue("horizontal"); + } else { + gradientStyle.setValue("vertical"); + } + + return getExpression(gradientColor, gradientStyle); + } + + public Expression convert(String string) { + StringValue stringValue = CssFactory.eINSTANCE.createStringValue(); + stringValue.setValue(string); + return getExpression(stringValue); + } + + public Expression convert(Integer intValue) { + Number numberValue = CssFactory.eINSTANCE.createNumber(); + numberValue.setValue(Integer.toString(Math.abs(intValue))); + if(intValue < 0) { + UnaryOperator operator = CssFactory.eINSTANCE.createUnaryOperator(); + operator.setOperator(UNARY.NEG); + numberValue.setOp(operator); + } + + return getExpression(numberValue); + } + + public Expression convert(Enumerator enumerated) { + Name literalValue = CssFactory.eINSTANCE.createName(); + + literalValue.setValue(enumerated.getName()); + + return getExpression(literalValue); + } + + private Expression getExpression(Term... values) { + if(values.length == 0) { + throw new IllegalArgumentException("An expression must contain at least one value"); + } + + Expression result = CssFactory.eINSTANCE.createExpression(); + result.setTerms(values[0]); + + for(int i = 1; i < values.length; i++) { + Subterm subterm = CssFactory.eINSTANCE.createSubterm(); + subterm.setTerm(values[i]); + result.getSubterms().add(subterm); + } + + return result; + } + + public Expression convert(boolean booleanValue) { + Name nameValue = CssFactory.eINSTANCE.createName(); + nameValue.setValue(booleanValue ? "true" : "false"); + return getExpression(nameValue); + } +} diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/StyleCreationDialog.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/StyleCreationDialog.java new file mode 100644 index 00000000000..5a0eda76c54 --- /dev/null +++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.configuration/src/org/eclipse/papyrus/infra/gmfdiag/css/configuration/handler/StyleCreationDialog.java @@ -0,0 +1,393 @@ +/***************************************************************************** + * 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.configuration.handler; + +import java.util.Map; + +import org.eclipse.gmf.runtime.notation.View; +import org.eclipse.jface.dialogs.TrayDialog; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.papyrus.infra.gmfdiag.css.Attribute; +import org.eclipse.papyrus.infra.gmfdiag.css.Declaration; +import org.eclipse.papyrus.infra.gmfdiag.css.Expression; +import org.eclipse.papyrus.infra.gmfdiag.css.HexColor; +import org.eclipse.papyrus.infra.gmfdiag.css.Name; +import org.eclipse.papyrus.infra.gmfdiag.css.Number; +import org.eclipse.papyrus.infra.gmfdiag.css.SelectorCondition; +import org.eclipse.papyrus.infra.gmfdiag.css.StringValue; +import org.eclipse.papyrus.infra.gmfdiag.css.Subterm; +import org.eclipse.papyrus.infra.gmfdiag.css.Term; +import org.eclipse.papyrus.infra.gmfdiag.css.properties.provider.CSSStyleSheetContentProvider; +import org.eclipse.papyrus.infra.gmfdiag.css.properties.provider.CSSStyleSheetLabelProvider; +import org.eclipse.papyrus.infra.gmfdiag.css.stylesheets.EmbeddedStyleSheet; +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.util.CssSwitch; +import org.eclipse.papyrus.infra.widgets.editors.AbstractEditor; +import org.eclipse.papyrus.infra.widgets.editors.BooleanCheckbox; +import org.eclipse.papyrus.infra.widgets.editors.EnumRadio; +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.papyrus.infra.widgets.editors.ReferenceDialog; +import org.eclipse.papyrus.infra.widgets.editors.StringEditor; +import org.eclipse.papyrus.infra.widgets.editors.StringFileSelector; +import org.eclipse.papyrus.infra.widgets.providers.StaticContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CTabFolder; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + + +public class StyleCreationDialog extends TrayDialog { + + private final Map conditions; + + private final Map declarations; + + private final String selectorName; + + private boolean useSelectorName = true; + + private boolean diagramRestriction = false; + + private String cssClass; + + private View contextView; + + private StyleSheet stylesheet; + + /** + * + * @param shell + * @param conditions + * inout + * @param declarations + * inout + * @param selectorName + */ + public StyleCreationDialog(Shell shell, Map conditions, Map declarations, String selectorName, View context) { + super(shell); + this.conditions = conditions; + this.declarations = declarations; + this.selectorName = selectorName; + this.contextView = context; + } + + @Override + public void create() { + super.create(); + Composite parent = getDialogArea(); + + CTabFolder tabFolder = new CTabFolder(parent, SWT.BORDER); + tabFolder.setLayoutData(new GridData(GridData.FILL_BOTH)); + + CTabItem conditionsTab = new CTabItem(tabFolder, SWT.NONE); + CTabItem declarationsTab = new CTabItem(tabFolder, SWT.NONE); + CTabItem stylesheetTab = new CTabItem(tabFolder, SWT.NONE); + + conditionsTab.setText("Conditions"); + declarationsTab.setText("Properties"); + stylesheetTab.setText("Stylesheet"); + + Composite conditionsContainer = new Composite(tabFolder, SWT.NONE); + conditionsContainer.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, true, true)); + conditionsContainer.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE)); + conditionsContainer.setBackgroundMode(SWT.INHERIT_DEFAULT); + + conditionsTab.setControl(conditionsContainer); + + Composite declarationsContainer = new Composite(tabFolder, SWT.NONE); + declarationsContainer.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, true, true)); + declarationsContainer.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE)); + declarationsContainer.setBackgroundMode(SWT.INHERIT_DEFAULT); + + declarationsTab.setControl(declarationsContainer); + + Composite stylesheetContainer = new Composite(tabFolder, SWT.NONE); + stylesheetContainer.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, true, true)); + stylesheetContainer.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE)); + stylesheetContainer.setBackgroundMode(SWT.INHERIT_DEFAULT); + + stylesheetTab.setControl(stylesheetContainer); + + createConditions(conditionsContainer); + createDeclarations(declarationsContainer); + createStylesheet(stylesheetContainer); + + getShell().setText("New Style"); + getShell().pack(); + } + + protected void createConditions(Composite parent) { + parent.setLayout(new GridLayout(3, false)); + + Label conditionsLabel = new Label(parent, SWT.WRAP); + conditionsLabel.setText("Select the condition(s) under which the style will be applied."); + conditionsLabel.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 3, 1)); + + createElementNameSection(parent); + createAttributeSelectorsSection(parent); + createStyleNameSection(parent); + } + + protected void createElementNameSection(Composite parent) { + EnumRadio diagramRestrictionWidget = new EnumRadio(parent, SWT.NONE, "Diagram:"); + diagramRestrictionWidget.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 3, 1)); + + ILabelProvider labelProvider = new LabelProvider() { + + @Override + public String getText(Object element) { + Boolean value = (Boolean)element; + return value ? contextView.getDiagram().getType() + " only" : "Any diagram"; + } + }; + + diagramRestrictionWidget.setProviders(new StaticContentProvider(new Boolean[]{ true, false }), labelProvider); + diagramRestrictionWidget.setValue(this.diagramRestriction); + diagramRestrictionWidget.addCommitListener(new ICommitListener() { + + public void commit(AbstractEditor editor) { + diagramRestriction = (Boolean)((EnumRadio)editor).getValue(); + } + }); + + EnumRadio selectorNameWidget = new EnumRadio(parent, SWT.NONE, "Applies to:"); + selectorNameWidget.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 3, 1)); + + labelProvider = new LabelProvider() { + + @Override + public String getText(Object element) { + Boolean value = (Boolean)element; + return value ? selectorName + " only" : "Any kind of element"; + } + }; + + selectorNameWidget.setProviders(new StaticContentProvider(new Boolean[]{ true, false }), labelProvider); + selectorNameWidget.setValue(this.useSelectorName); + selectorNameWidget.addCommitListener(new ICommitListener() { + + public void commit(AbstractEditor editor) { + useSelectorName = (Boolean)((EnumRadio)editor).getValue(); + } + }); + } + + protected void createAttributeSelectorsSection(Composite parent) { + if(conditions.isEmpty()) { + return; + } + + Label detailLabel = new Label(parent, SWT.NONE); + detailLabel.setText("If the following properties are matched:"); + detailLabel.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 3, 1)); + + for(SelectorCondition condition : conditions.keySet()) { + final Attribute currentCondition = (Attribute)condition; + + String attributeLabel = currentCondition.getName(); + if(currentCondition.getValue() != null) { + attributeLabel += " " + currentCondition.getValue().getOperator() + " " + currentCondition.getValue().getValue(); + } + + BooleanCheckbox checkbox = new BooleanCheckbox(parent, SWT.NONE, attributeLabel); + checkbox.setValue(conditions.get(currentCondition)); + + checkbox.addCommitListener(new ICommitListener() { + + public void commit(AbstractEditor editor) { + conditions.put(currentCondition, ((BooleanCheckbox)editor).getValue()); + } + }); + } + } + + protected void createStyleNameSection(Composite parent) { + Label styleNameLabel = new Label(parent, SWT.WRAP); + + String label = "If a name is used for this style, it will have to be applied manually:"; + + styleNameLabel.setText(label); + styleNameLabel.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 3, 1)); + + StringEditor styleNameEditor = new StringEditor(parent, SWT.NONE, "Style name:"); + styleNameEditor.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 3, 1)); + // styleNameEditor.setToolTipText(label); + styleNameEditor.addCommitListener(new ICommitListener() { + + public void commit(AbstractEditor editor) { + cssClass = (String)((StringEditor)editor).getValue(); + } + + }); + } + + protected void createDeclarations(Composite parent) { + parent.setLayout(new GridLayout(3, false)); + // parent.setLayout(new FillLayout()); + + Label declarationsLabel = new Label(parent, SWT.WRAP); + declarationsLabel.setText("Select the properties you want to set. Unchecked properties will keep their default value (Which might be inherited from another style)."); + declarationsLabel.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 3, 1)); + + for(Declaration declaration : declarations.keySet()) { + String label = declaration.getProperty() + ": " + getLabel(declaration.getExpression()); + BooleanCheckbox checkbox = new BooleanCheckbox(parent, SWT.NONE, label); + checkbox.setValue(declarations.get(declaration)); + + final Declaration currentDeclaration = declaration; + checkbox.addCommitListener(new ICommitListener() { + + public void commit(AbstractEditor editor) { + declarations.put(currentDeclaration, ((BooleanCheckbox)editor).getValue()); + } + }); + } + } + + protected void createStylesheet(Composite parent) { + //TODO: Use a preference to remember the last edited Stylesheet (Per model? Diagram? Workspace? With user choice?) + + parent.setLayout(new GridLayout(1, false)); + + //Create or use an existing External Stylesheet + StringFileSelector externalStylesheet = new StringFileSelector(parent, SWT.NONE); + externalStylesheet.setAllowFileSystem(false); + externalStylesheet.setLabel("External stylesheet:"); + externalStylesheet.setToolTipText("Create or use an existing external CSS Stylesheet"); + externalStylesheet.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); + externalStylesheet.addCommitListener(new ICommitListener() { + + public void commit(AbstractEditor editor) { + String path = (String)((StringEditor)editor).getValue(); + StyleSheetReference stylesheetReference = StylesheetsFactory.eINSTANCE.createStyleSheetReference(); + stylesheetReference.setPath(path); + stylesheet = stylesheetReference; + } + }); + + Label orLabel = new Label(parent, SWT.NONE); + orLabel.setText("-- OR --"); + + //Create a new Embedded Stylesheet + StringEditor embeddedStylesheet = new StringEditor(parent, SWT.NONE); + embeddedStylesheet.setLabel("New local stylesheet:"); + embeddedStylesheet.setToolTipText("Create a new local stylesheet. The stylesheet will be embedded in the current model. Unsupported yet"); + embeddedStylesheet.setReadOnly(true); + embeddedStylesheet.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); + embeddedStylesheet.addCommitListener(new ICommitListener() { + + public void commit(AbstractEditor editor) { + String name = (String)((StringEditor)editor).getValue(); + EmbeddedStyleSheet embeddedStylesheet = StylesheetsFactory.eINSTANCE.createEmbeddedStyleSheet(); + embeddedStylesheet.setLabel(name); + stylesheet = embeddedStylesheet; + } + }); + + orLabel = new Label(parent, SWT.NONE); + orLabel.setText("-- OR --"); + + //Use an existing applied stylesheet (Either Reference or Embedded) + ReferenceDialog appliedStylesheet = new ReferenceDialog(parent, SWT.NONE); + appliedStylesheet.setLabel("Applied stylesheet:"); + appliedStylesheet.setToolTipText("Use an existing stylesheet, from the stylesheets applied to the current model"); + appliedStylesheet.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); + appliedStylesheet.setContentProvider(new CSSStyleSheetContentProvider(contextView)); + appliedStylesheet.setLabelProvider(new CSSStyleSheetLabelProvider()); + appliedStylesheet.addCommitListener(new ICommitListener() { + + public void commit(AbstractEditor editor) { + StyleSheet value = (StyleSheet)((ReferenceDialog)editor).getValue(); + stylesheet = value; + } + }); + + } + + public String getCSSClass() { + if(cssClass != null) { + return cssClass.trim().equals("") ? null : cssClass.trim(); + } + return null; + } + + protected String getLabel(Expression expression) { + String label = getLabel(expression.getTerms()); + for(Subterm subTerm : expression.getSubterms()) { + if(subTerm.getOperator() != null) { + label += subTerm.getOperator(); + } + label += " " + getLabel(subTerm.getTerm()); + } + return label; + } + + protected String getLabel(Term term) { + return (new CssSwitch() { + + @Override + public String caseHexColor(HexColor term) { + return '#' + term.getValue(); + } + + @Override + public String caseName(Name term) { + return term.getValue(); + } + + @Override + public String caseStringValue(StringValue term) { + return "\"" + term.getValue() + "\""; + } + + @Override + public String caseNumber(Number term) { + String label = ""; + if(term.getOp() != null) { + label += term.getOp().getOperator(); + } + label += term.getValue(); + return label; + } + }).doSwitch(term); + } + + public StyleSheet getStylesheet() { + return stylesheet; + } + + @Override + protected boolean isResizable() { + return true; + } + + @Override + public Composite getDialogArea() { + return (Composite)super.getDialogArea(); + } + + public boolean useSelectorName() { + return useSelectorName; + } + + public boolean getDiagramRestriction() { + return diagramRestriction; + } + +} -- cgit v1.2.3