diff --git a/.gitignore b/.gitignore index 585203ce5..db78f1b8f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,9 @@ bin/ xtend-gen/ target/ -localM2/ -klighd-snapshots/ -klighd/ +/localM2/ +/klighd-snapshots/ +/klighd/ .svn/ .DS_Store *.class diff --git a/plugins/de.cau.cs.kieler.klighd.ide/src/de/cau/cs/kieler/klighd/ide/syntheses/EObjectFallbackSynthesis.xtend b/plugins/de.cau.cs.kieler.klighd.ide/src/de/cau/cs/kieler/klighd/ide/syntheses/EObjectFallbackSynthesis.xtend index 43e1890ae..175c9321f 100644 --- a/plugins/de.cau.cs.kieler.klighd.ide/src/de/cau/cs/kieler/klighd/ide/syntheses/EObjectFallbackSynthesis.xtend +++ b/plugins/de.cau.cs.kieler.klighd.ide/src/de/cau/cs/kieler/klighd/ide/syntheses/EObjectFallbackSynthesis.xtend @@ -139,6 +139,7 @@ class EObjectFallbackSynthesis extends AbstractDiagramSynthesis { rootNode.setLayoutOption(LayeredOptions::NODE_PLACEMENT_BK_EDGE_STRAIGHTENING, EdgeStraighteningStrategy.IMPROVE_STRAIGHTNESS); rootNode.setLayoutOption(LayeredOptions::SPACING_EDGE_NODE, LayeredOptions.SPACING_NODE_NODE.^default * 1.1f); rootNode.setLayoutOption(LayeredOptions::SPACING_EDGE_NODE_BETWEEN_LAYERS, LayeredOptions.SPACING_NODE_NODE.^default * 1.1f); + rootNode.setProperty(KlighdProperties.DIAGRAM_BACKGROUND, backgroundColor) // transform root object rootNode.children += model.transformToNode diff --git a/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/KGraphDiagramGenerator.xtend b/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/KGraphDiagramGenerator.xtend index aa2ecb3c6..b62109f36 100644 --- a/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/KGraphDiagramGenerator.xtend +++ b/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/KGraphDiagramGenerator.xtend @@ -152,6 +152,12 @@ class KGraphDiagramGenerator implements IDiagramGenerator { id = uri children = new ArrayList ] + + // Special property for the diagram background, to be set on the diagram root. + val background = parentNode.getProperty(KlighdProperties.DIAGRAM_BACKGROUND) + if (background !== null) { + (diagramRoot as SKGraph).properties.put(KlighdProperties.DIAGRAM_BACKGROUND.id, background) + } diagramRoot.children.addAll(createNodesAndPrepareEdges(#[parentNode], diagramRoot)) // Do post processing. diff --git a/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/KGraphDiagramServer.xtend b/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/KGraphDiagramServer.xtend index 14a9b0ec3..531c7dea8 100644 --- a/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/KGraphDiagramServer.xtend +++ b/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/KGraphDiagramServer.xtend @@ -62,7 +62,6 @@ import org.eclipse.emf.ecore.EObject import org.eclipse.sprotty.Action import org.eclipse.sprotty.ActionMessage import org.eclipse.sprotty.RejectAction -import org.eclipse.sprotty.RequestModelAction import org.eclipse.sprotty.SModelElement import org.eclipse.sprotty.SModelRoot import org.eclipse.sprotty.SelectAction @@ -253,25 +252,6 @@ class KGraphDiagramServer extends LanguageAwareDiagramServer { notificationHandler.sendErrorAndThrow(e) } } - - /** - * additionally read the color preferences from the request model action. - */ - override protected handle(RequestModelAction request) { - super.handle(request) - if (model.type == 'NONE' && diagramLanguageServer !== null) { - synchronized (diagramState) { - // In the request model action there may be some further information for the client color preferences to - // be applied here. - val foregroundColor = LSPUtil.parseColor(request.options.get("clientColorPreferenceForeground")) - val backgroundColor = LSPUtil.parseColor(request.options.get("clientColorPreferenceBackground")) - val highlightColor = LSPUtil.parseColor(request.options.get("clientColorPreferenceHighlight")) - if (foregroundColor !== null && backgroundColor !== null && highlightColor !== null) { - diagramState.colorPreferences = new ColorPreferences(foregroundColor, backgroundColor, highlightColor) - } - } - } - } /** * Called when a {@link PerformActionAction} is received. @@ -377,11 +357,12 @@ class KGraphDiagramServer extends LanguageAwareDiagramServer { * Tells the server that the client has new color preferences available that should be considered. */ protected def handle(ClientColorPreferencesAction action) { + val kind = action.clientColorPreferences.kind val foregroundColor = LSPUtil.parseColor(action.clientColorPreferences.foreground) val backgroundColor = LSPUtil.parseColor(action.clientColorPreferences.background) val highlightColor = LSPUtil.parseColor(action.clientColorPreferences.highlight) - val colorPreferences = new ColorPreferences(foregroundColor, backgroundColor, highlightColor) + val colorPreferences = new ColorPreferences(kind, foregroundColor, backgroundColor, highlightColor) synchronized (diagramState) { diagramState.colorPreferences = colorPreferences } diff --git a/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/LSPUtil.xtend b/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/LSPUtil.xtend index 7dc588b49..1c69a1649 100644 --- a/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/LSPUtil.xtend +++ b/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/LSPUtil.xtend @@ -3,7 +3,7 @@ * * http://rtsys.informatik.uni-kiel.de/kieler * - * Copyright 2020 by + * Copyright 2020-2024 by * + Kiel University * + Department of Computer Science * + Real-Time and Embedded Systems Group @@ -23,6 +23,7 @@ import de.cau.cs.kieler.klighd.kgraph.KNode import de.cau.cs.kieler.klighd.krendering.KColor import de.cau.cs.kieler.klighd.krendering.KRenderingFactory import de.cau.cs.kieler.klighd.util.ColorPreferences +import de.cau.cs.kieler.klighd.util.ColorThemeKind import java.awt.Color /** @@ -93,14 +94,16 @@ class LSPUtil { */ static def ColorPreferences parseColorPreferences(JsonElement jsonColors) { if (jsonColors === null || !jsonColors.isJsonObject) return null + val kind = jsonColors.asJsonObject.get("kind") val foreground = jsonColors.asJsonObject.get("foreground") val background = jsonColors.asJsonObject.get("background") val highlight = jsonColors.asJsonObject.get("highlight") + val ColorThemeKind colorKind = if (kind === null) ColorThemeKind.LIGHT else ColorThemeKind.values.get(kind.asInt) val foregroundColor = parseColor(foreground) val backgroundColor = parseColor(background) val highlightColor = parseColor(highlight) - return new ColorPreferences(foregroundColor, backgroundColor, highlightColor) + return new ColorPreferences(colorKind, foregroundColor, backgroundColor, highlightColor) } /** @@ -122,7 +125,7 @@ class LSPUtil { * Parses a single color string in the form #RRGGBB into a KColor, or null if the string is unparsable. */ static def KColor parseColor(JsonElement jsonColor) { - if (!jsonColor.isJsonPrimitive) return null + if (jsonColor === null || !jsonColor.isJsonPrimitive) return null return parseColor(jsonColor.asString) } } diff --git a/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/model/Actions.xtend b/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/model/Actions.xtend index cc41a9a79..6a045734b 100644 --- a/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/model/Actions.xtend +++ b/plugins/de.cau.cs.kieler.klighd.lsp/src/de/cau/cs/kieler/klighd/lsp/model/Actions.xtend @@ -17,6 +17,7 @@ package de.cau.cs.kieler.klighd.lsp.model import de.cau.cs.kieler.klighd.krendering.KImage +import de.cau.cs.kieler.klighd.util.ColorThemeKind import java.util.List import java.util.Map import java.util.Set @@ -184,6 +185,7 @@ class ClientColorPreferencesAction implements Action { */ @Accessors class ClientColorPreferences { + ColorThemeKind kind String foreground String background String highlight diff --git a/plugins/de.cau.cs.kieler.klighd.piccolo/src/de/cau/cs/kieler/klighd/piccolo/viewer/PiccoloViewer.java b/plugins/de.cau.cs.kieler.klighd.piccolo/src/de/cau/cs/kieler/klighd/piccolo/viewer/PiccoloViewer.java index 3fb0b6203..2535f2f4a 100644 --- a/plugins/de.cau.cs.kieler.klighd.piccolo/src/de/cau/cs/kieler/klighd/piccolo/viewer/PiccoloViewer.java +++ b/plugins/de.cau.cs.kieler.klighd.piccolo/src/de/cau/cs/kieler/klighd/piccolo/viewer/PiccoloViewer.java @@ -63,6 +63,7 @@ import de.cau.cs.kieler.klighd.piccolo.internal.nodes.KlighdMainCamera; import de.cau.cs.kieler.klighd.piccolo.internal.util.NodeUtil; import de.cau.cs.kieler.klighd.util.ColorPreferences; +import de.cau.cs.kieler.klighd.util.ColorThemeKind; import de.cau.cs.kieler.klighd.util.KlighdProperties; import de.cau.cs.kieler.klighd.viewers.AbstractViewer; import de.cau.cs.kieler.klighd.viewers.ContextViewer; @@ -156,6 +157,7 @@ public PiccoloViewer(final ContextViewer theParentViewer, final Composite parent // Simulate dark mode background = Color.decode("#2f2f2f"); ColorPreferences colors = new ColorPreferences( + ColorThemeKind.DARK, KRenderingUtil.getColor("#cccccc"), KRenderingUtil.getColor("#2f2f2f"), KRenderingUtil.getColor("#cccccc") diff --git a/plugins/de.cau.cs.kieler.klighd/src/de/cau/cs/kieler/klighd/util/ColorPreferences.java b/plugins/de.cau.cs.kieler.klighd/src/de/cau/cs/kieler/klighd/util/ColorPreferences.java index 32545869f..edaca03c0 100644 --- a/plugins/de.cau.cs.kieler.klighd/src/de/cau/cs/kieler/klighd/util/ColorPreferences.java +++ b/plugins/de.cau.cs.kieler.klighd/src/de/cau/cs/kieler/klighd/util/ColorPreferences.java @@ -3,7 +3,7 @@ * * http://rtsys.informatik.uni-kiel.de/kieler * - * Copyright 2023 by + * Copyright 2023-2024 by * + Kiel University * + Department of Computer Science * + Real-Time and Embedded Systems Group @@ -21,12 +21,16 @@ /** * Color preferences for KLighD syntheses. May provide information about the foreground, background, and a highlighting - * color, that may be set by a frontend. + * color, that may be set by a frontend. Alternatively, this preference sets a general color theme kind instead of + * pre-defined colors. * * @author nre */ public class ColorPreferences { +// The kind of color theme to let the synthesis pick its own color palette. + private ColorThemeKind kind; + /** * The foreground color, to be used e.g. for texts, lines, etc., or as a reference. */ @@ -46,42 +50,76 @@ public class ColorPreferences { * Default constructor for color preferences, setting foreground and highlight to black, background to white. */ public ColorPreferences() { - this(null, null, null); + this(null, null, null, null); } /** * Creates a new ColorPreferences with the given colors, or the default colors if some parameters are {@code null}. * + * @param kind * @param foreground * @param background * @param highlight */ - public ColorPreferences(KColor foreground, KColor background, KColor highlight) { + public ColorPreferences(ColorThemeKind kind, KColor foreground, KColor background, KColor highlight) { + this.kind = kind; + if (this.kind == null) { + this.kind = ColorThemeKind.LIGHT; + } if (foreground == null) { - foreground = KRenderingFactory.eINSTANCE.createKColor(); - foreground.setRed(0); - foreground.setGreen(0); - foreground.setBlue(0); + this.foreground = KRenderingFactory.eINSTANCE.createKColor(); + if (this.kind == ColorThemeKind.LIGHT || this.kind == ColorThemeKind.HIGH_CONTRAST_LIGHT) { + this.foreground.setRed(0); + this.foreground.setGreen(0); + this.foreground.setBlue(0); + } else { // dark theme + // D4D4D4 + this.foreground.setRed(212); + this.foreground.setGreen(212); + this.foreground.setBlue(212); + } } else { this.foreground = foreground; } if (background == null) { - background = KRenderingFactory.eINSTANCE.createKColor(); - background.setRed(255); - background.setGreen(255); - background.setBlue(255); + this.background = KRenderingFactory.eINSTANCE.createKColor(); + if (this.kind == ColorThemeKind.LIGHT || this.kind == ColorThemeKind.HIGH_CONTRAST_LIGHT) { + this.background.setRed(255); + this.background.setGreen(255); + this.background.setBlue(255); + } else { // dark theme + // 1E1E1E + this.background.setRed(30); + this.background.setGreen(30); + this.background.setBlue(30); + } } else { this.background = background; } if (highlight == null) { - highlight = KRenderingFactory.eINSTANCE.createKColor(); - highlight.setRed(0); - highlight.setGreen(0); - highlight.setBlue(0); + this.highlight = KRenderingFactory.eINSTANCE.createKColor(); + if (this.kind == ColorThemeKind.LIGHT || this.kind == ColorThemeKind.HIGH_CONTRAST_LIGHT) { + // 005FB8 + this.highlight.setRed(0); + this.highlight.setGreen(95); + this.highlight.setBlue(184); + } else { // dark theme + // 0078D4 + this.highlight.setRed(0); + this.highlight.setGreen(120); + this.highlight.setBlue(212); + } } else { this.highlight = highlight; } } + + /** + * @return the theme kind + */ + public ColorThemeKind getKind() { + return kind; + } /** * @return the foreground color diff --git a/plugins/de.cau.cs.kieler.klighd/src/de/cau/cs/kieler/klighd/util/ColorThemeKind.java b/plugins/de.cau.cs.kieler.klighd/src/de/cau/cs/kieler/klighd/util/ColorThemeKind.java new file mode 100644 index 000000000..cac59a21c --- /dev/null +++ b/plugins/de.cau.cs.kieler.klighd/src/de/cau/cs/kieler/klighd/util/ColorThemeKind.java @@ -0,0 +1,41 @@ +/* + * KIELER - Kiel Integrated Environment for Layout Eclipse RichClient + * + * http://rtsys.informatik.uni-kiel.de/kieler + * + * Copyright 2024 by + * + Kiel University + * + Department of Computer Science + * + Real-Time and Embedded Systems Group + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + */ +package de.cau.cs.kieler.klighd.util; + +/** + * Kinds of color themes, as an enum similar to VS Code's ColorThemeKind. + * + * @author nre + */ +public enum ColorThemeKind { + /** + * Light color theme with light backgrounds and darker writing + */ + LIGHT, + /** + * Dark color theme with dark backgrounds and lighter writing + */ + DARK, + /** + * Light color theme with a higher contrast. + */ + HIGH_CONTRAST_LIGHT, + /** + * Dark color theme with a higher contrast. + */ + HIGH_CONTRAST_DARK +} diff --git a/plugins/de.cau.cs.kieler.klighd/src/de/cau/cs/kieler/klighd/util/KlighdProperties.java b/plugins/de.cau.cs.kieler.klighd/src/de/cau/cs/kieler/klighd/util/KlighdProperties.java index a79002db5..9eb5d795e 100644 --- a/plugins/de.cau.cs.kieler.klighd/src/de/cau/cs/kieler/klighd/util/KlighdProperties.java +++ b/plugins/de.cau.cs.kieler.klighd/src/de/cau/cs/kieler/klighd/util/KlighdProperties.java @@ -33,6 +33,7 @@ import de.cau.cs.kieler.klighd.kgraph.KGraphData; import de.cau.cs.kieler.klighd.kgraph.KGraphElement; import de.cau.cs.kieler.klighd.kgraph.KNode; +import de.cau.cs.kieler.klighd.krendering.KColor; import de.cau.cs.kieler.klighd.krendering.KText; import de.cau.cs.kieler.klighd.microlayout.Bounds; @@ -387,6 +388,12 @@ public static boolean isSelectable(final EObject viewElement) { */ public static final IProperty COLOR_PREFERENCES = new Property("klighd.colorPreferences", null); + /** + * Property to be set on the root node of the graph that defines a custom background color that the diagram + * canvas should use. Null means no custom background, a default white one will be used. + */ + public static final IProperty DIAGRAM_BACKGROUND = + new Property("klighd.diagramBackground", null); /** * Property determining whether this node should be rendered as a proxy.