From 02b10d835835f201757afe9a9b53951424258cf2 Mon Sep 17 00:00:00 2001 From: rensink Date: Fri, 15 Nov 2024 14:09:51 +0100 Subject: [PATCH] Color declaration compatibility check for subtypes --- .../groove/grammar/model/TypeModel.java | 5 +-- .../groove/grammar/type/TypeGraph.java | 34 +++++++++++++++---- .../utwente/groove/grammar/type/TypeNode.java | 34 ++++++++++++++----- .../groove/gui/action/SelectColorAction.java | 2 +- .../utwente/groove/gui/look/ColorValue.java | 21 +----------- 5 files changed, 58 insertions(+), 38 deletions(-) diff --git a/src/main/java/nl/utwente/groove/grammar/model/TypeModel.java b/src/main/java/nl/utwente/groove/grammar/model/TypeModel.java index 50c511393..2712f4351 100644 --- a/src/main/java/nl/utwente/groove/grammar/model/TypeModel.java +++ b/src/main/java/nl/utwente/groove/grammar/model/TypeModel.java @@ -249,8 +249,9 @@ private void addNodeType(AspectNode modelNode, TypeLabel typeLabel, if (modelNode.has(IMPORT)) { typeNode.setImported(true); } - if (modelNode.hasColor()) { - typeNode.setColor(modelNode.getColor()); + var color = modelNode.getColor(); + if (color != null) { + typeNode.setDeclaredColor(color); } if (modelNode.has(EDGE)) { typeNode.setLabelPattern(modelNode.getEdgePattern()); diff --git a/src/main/java/nl/utwente/groove/grammar/type/TypeGraph.java b/src/main/java/nl/utwente/groove/grammar/type/TypeGraph.java index 1e4725d9c..64f4043d7 100644 --- a/src/main/java/nl/utwente/groove/grammar/type/TypeGraph.java +++ b/src/main/java/nl/utwente/groove/grammar/type/TypeGraph.java @@ -121,8 +121,9 @@ public Map add(TypeGraph other) throws FormatException { if (source.isAbstract()) { image.setAbstract(); } - if (source.getColor() != null) { - image.setColor(source.getColor()); + var color = source.getDeclaredColor(); + if (color != null) { + image.setDeclaredColor(color); } image.setLabelPattern(source.getLabelPattern()); boolean imported = source.isImported() && (oldImage == null || oldImage.isImported()); @@ -296,9 +297,28 @@ && hasCommonSubtype(edge1.target(), edge2.target())) { } } // check for inconsistent color specifications in the type hierarchy - // this occurs if a node type has no color specification, whereas two - // of its supertypes have distinct ones. - + // this occurs if two node types with declared colours share a subtype. + var coloredNodes = nodeSet().stream().filter(TypeNode::hasDeclaredColor).toList(); + for (var n1 : coloredNodes) { + var n1Color = n1.getDeclaredColor(); + assert n1Color != null; + boolean start = false; + for (var n2 : coloredNodes) { + if (n1 == n2) { + start = true; + continue; + } + if (!start) { + continue; + } + if (n1Color.equals(n2.getDeclaredColor())) { + continue; + } + if (hasCommonSubtype(n1, n2)) { + errors.add("Incompatible color declarations on %s and %s", n1, n2); + } + } + } errors.throwException(); } @@ -331,7 +351,7 @@ public boolean setFixed() { } } // propagate colours to subtypes - var coloredNodes = nodeSet().stream().filter(TypeNode::hasColor).toList(); + var coloredNodes = nodeSet().stream().filter(TypeNode::hasDeclaredColor).toList(); for (TypeNode node : coloredNodes) { // propagate colours Color color = node.getColor(); @@ -343,7 +363,7 @@ public boolean setFixed() { TypeNode subNode = subNodeIter.next(); subNodeIter.remove(); if (subNode.getColor() == null) { - subNode.setColor(color); + subNode.setDerivedColor(color); } else { propagatees.removeAll(this.nodeSubtypeMap.get(subNode)); } diff --git a/src/main/java/nl/utwente/groove/grammar/type/TypeNode.java b/src/main/java/nl/utwente/groove/grammar/type/TypeNode.java index a09f6fcb7..0089c68f6 100644 --- a/src/main/java/nl/utwente/groove/grammar/type/TypeNode.java +++ b/src/main/java/nl/utwente/groove/grammar/type/TypeNode.java @@ -201,23 +201,41 @@ public final void setLabelPattern(@Nullable LabelPattern pattern) { /** The label pattern of this node, if any. */ private @Nullable LabelPattern pattern; + /** Sets the declared (and derived) colour of this type node. */ + public void setDeclaredColor(Color colour) { + this.declaredColour = this.derivedColour = colour; + } + + /** Indicates if this type node has a declared display colour. */ + public boolean hasDeclaredColor() { + return this.declaredColour != null; + } + + /** Returns the declared colour of this type node, if any. */ + public @Nullable Color getDeclaredColor() { + return this.declaredColour; + } + + /** The declared display colour of this node, if any. */ + private @Nullable Color declaredColour; + /** Returns the (possibly {@code null}) colour of this type node. */ public final @Nullable Color getColor() { - return this.colour; + return this.derivedColour; } - /** Indicates if this type node has an explicitly set colour. */ + /** Indicates if this type node has a (declared or derived) display colour. */ public final boolean hasColor() { - return this.colour != null; + return this.derivedColour != null; } - /** Sets the colour of this type node. */ - public final void setColor(@Nullable Color colour) { - this.colour = colour; + /** Sets the derived colour of this type node. */ + void setDerivedColor(Color colour) { + this.derivedColour = colour; } - /** The display colour of this node, if any. */ - private @Nullable Color colour; + /** The derived display colour of this node, if any. */ + private @Nullable Color derivedColour; @Override public TypeGraph getGraph() { diff --git a/src/main/java/nl/utwente/groove/gui/action/SelectColorAction.java b/src/main/java/nl/utwente/groove/gui/action/SelectColorAction.java index 74700cf90..7b58ee16e 100644 --- a/src/main/java/nl/utwente/groove/gui/action/SelectColorAction.java +++ b/src/main/java/nl/utwente/groove/gui/action/SelectColorAction.java @@ -103,7 +103,7 @@ private void checkLabelTree(LabelTree tree) { public void execute() { TypeNode typeNode = getGrammarModel().getTypeGraph().getNode(this.label); assert typeNode != null; // ensured by the label - Color initColour = typeNode.getColor(); + Color initColour = typeNode.getDeclaredColor(); if (initColour != null) { this.chooser.setColor(initColour); } diff --git a/src/main/java/nl/utwente/groove/gui/look/ColorValue.java b/src/main/java/nl/utwente/groove/gui/look/ColorValue.java index 2a313229d..b170c3cd9 100644 --- a/src/main/java/nl/utwente/groove/gui/look/ColorValue.java +++ b/src/main/java/nl/utwente/groove/gui/look/ColorValue.java @@ -17,16 +17,12 @@ package nl.utwente.groove.gui.look; import java.awt.Color; -import java.util.Objects; - -import org.eclipse.jdt.annotation.NonNull; import nl.utwente.groove.grammar.aspect.AspectNode; import nl.utwente.groove.grammar.type.TypeNode; import nl.utwente.groove.graph.GraphRole; import nl.utwente.groove.gui.jgraph.AspectJEdge; import nl.utwente.groove.gui.jgraph.AspectJVertex; -import nl.utwente.groove.util.Groove; /** * Refresher for the controlled colour value of a JCell. @@ -44,28 +40,13 @@ protected Color getForJVertex(AspectJVertex jVertex) { } else { TypeNode nodeType = jVertex.getNodeType(); if (nodeType != null) { - result = getColor(nodeType); + result = nodeType.getColor(); } } } return result; } - /** Recursively finds the "closest" color specification among this node type and its supertypes. */ - private Color getColor(@NonNull TypeNode nodeType) { - Color result = nodeType.getColor(); - if (result == null) { - result = Groove - .orElseNull(nodeType - .getDirectSupertypes() - .stream() - .map(this::getColor) - .filter(Objects::nonNull) - .findFirst()); - } - return result; - } - @Override protected Color getForJEdge(AspectJEdge jEdge) { Color result = null;