X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.diagram%2Fsrc%2Forg%2Fsimantics%2Fdiagram%2Fprofile%2FTextGridStyle.java;h=c6040c0c16b4bd390cfdc67fd7a282871d403fad;hp=d660d47a5be007f7e33acd9349c820cd1d1c7615;hb=HEAD;hpb=0ae2b770234dfc3cbb18bd38f324125cf0faca07 diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/profile/TextGridStyle.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/profile/TextGridStyle.java index d660d47a5..c6040c0c1 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/profile/TextGridStyle.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/profile/TextGridStyle.java @@ -5,6 +5,11 @@ import java.awt.Font; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import org.simantics.databoard.Bindings; import org.simantics.datatypes.literal.Vec2d; @@ -27,6 +32,7 @@ import org.simantics.scenegraph.utils.GeometryUtils; import org.simantics.scenegraph.utils.NodeUtil; import org.simantics.scl.runtime.function.Function1; import org.simantics.ui.colors.Colors; +import org.simantics.utils.datastructures.Pair; /** * @author Antti Villberg @@ -38,17 +44,15 @@ public abstract class TextGridStyle extends StyleBase { private final Color BACKGROUND_COLOR = new Color(255, 255, 255, 192); private static final Rectangle2D EMPTY_BOUNDS = new Rectangle2D.Double(0, 0, 0, 0); - // NOTE: this is a hack - String id; - protected double xOffset; protected double yOffset; - public TextGridStyle() { - this(0.0, 2.1); + public TextGridStyle(Resource r) { + this(r, 0.0, 2.1); } - public TextGridStyle(double xOffset, double yOffset) { + public TextGridStyle(Resource r, double xOffset, double yOffset) { + super(r); this.xOffset = xOffset; this.yOffset = yOffset; } @@ -94,7 +98,7 @@ public abstract class TextGridStyle extends StyleBase { String name = graph.getPossibleRelatedValue(config, getPropertyRelation(graph,element), Bindings.STRING); return name; } - + public AffineTransform getTransform(INode node, AffineTransform parentTransform, Rectangle2D elementBounds, int location, boolean up) { return getTransform(parentTransform, elementBounds, location, up); } @@ -110,7 +114,7 @@ public abstract class TextGridStyle extends StyleBase { at.scale(0.15, 0.15); return at; - + } protected String rowId() { @@ -151,171 +155,188 @@ public abstract class TextGridStyle extends StyleBase { @Override public void applyStyleForNode(EvaluationContext observer, INode _node, MonitorTextGridResult result) { - String value = result != null ? result.getText1() : null; boolean enabled = result != null ? result.getEnabled() : false; if (value != null && enabled) { - // if (value != null && !value.isEmpty() && !value.trim().isEmpty()) { - - String value2 = result != null ? result.getText2() : null; - String value3 = result != null ? result.getText3() : null; - - double spacing = result.getSpacing(); - - final Function1 modifier = result != null ? result.getModifier() : null; - final Function1 validator = result != null ? result.getValidator() : null; - final Function1 translator = result != null ? result.getTranslator() : null; - final RVI rvi = result != null ? result.getRVI() : null; - - final TextGridNode node = ProfileVariables.claimChild(_node, "", "TextGridStyle", TextGridNode.class, observer); - if (node == null) + Map> rows = observer.getProperty(_node, "rows"); + if (rows == null) { + rows = new HashMap>(); + observer.setProperty(_node, "rows", rows); + } + Pair oldResultPair = rows.get(result.getRowId()); + if (oldResultPair != null && oldResultPair.first == this && oldResultPair.second.sameStructure(result)) { return; - - // This assumes that this TextGridStyle instance will be devoted to - // this row ID until the end of its life. - String id = result.getRowId(); - //System.out.println(this + " ID: " + id); - if (!id.equals(this.id)) { - //System.out.println(this + " SET ID: " + this.id + " -> " + id); - this.id = id; } - Integer newRow = observer.getTemporaryProperty(_node, "location"); - if (newRow == null) - newRow = 1; + rows.put(rowIdKey(), new Pair(this, result)); - // Remove from existing row to add to another row if necessary. - Integer row = observer.getProperty(_node, id); - if (row != null && row != newRow) { - String actualId = node.getRowId(row); - if (id.equals(actualId)) { - node.removeRow(row); - } - } - row = newRow; - - node.setRowId(row, id); - observer.setProperty(_node, id, row); - observer.setTemporaryProperty(_node, "location", row + 1); + // FIXME: Improve performance by calling refreshAll only once after all text grid style changes have been applied + refreshAll(observer, _node); + } else { + cleanupStyleForNode(observer, _node); + } + } - node.setText(2, row, value2); - node.setUp(result.getUp()); + private static final Comparator> ROW_PRIORITY_COMPARATOR = + (o1, o2) -> Double.compare(o1.first.getPriority(), o2.first.getPriority()); - MonitorTextGridResult cache = node.getCache(1, row); - if(cache != null && cache.sameStructure(result)) return; + private static void refreshAll(EvaluationContext observer, INode _node) { + final TextGridNode node = ProfileVariables.claimChild(_node, "", "TextGridStyle", TextGridNode.class, observer); + if (node == null) + return; - node.setCache(1, row, result); + int row = 0; + Map> rows = observer.getProperty(_node, "rows"); + if (rows != null) { + List> sortedRows = rows.values().stream() + .sorted(ROW_PRIORITY_COMPARATOR) + .collect(Collectors.toList()); - boolean isConnection = _node instanceof ConnectionNode; - - Rectangle2D elementBounds = isConnection ? EMPTY_BOUNDS : NodeUtil.getLocalElementBounds(_node); - if(elementBounds == null) { - new Exception("Cannot get local element bounds for node " + _node.toString()).printStackTrace(); - // This is here for checking why getLocalElementBounds failed in the debugger. - NodeUtil.getLocalElementBounds(_node); - return; - } + for (Pair resultPair : sortedRows) { + row++; + TextGridStyle style = resultPair.first; + MonitorTextGridResult result = resultPair.second; - // System.err.println("elementBounds " + elementBounds); - // System.err.println("parentTransform " + result.getParentTransform()); - - AffineTransform at = getTransform(_node,result.getParentTransform(), elementBounds, row, result.getUp()); - Vec2d offset = result.getOffset(); - - Point2D[] cellOffsets = getCellOffsets(); - - AffineTransform at1 = new AffineTransform(at); - at1.translate(cellOffsets[0].getX(),cellOffsets[0].getY()); - AffineTransform at2 = new AffineTransform(at); - at2.translate(cellOffsets[1].getX()+spacing,cellOffsets[1].getY()); - AffineTransform at3 = new AffineTransform(at); - at3.translate(cellOffsets[2].getX()+spacing,cellOffsets[2].getY()); - - at1.translate(offset.x, offset.y); - at2.translate(offset.x, offset.y); - at3.translate(offset.x, offset.y); - - node.setTransform(1, row, at1); - node.setTransform(2, row, at2); - node.setTransform(3, row, at3); - - Alignment[] alignments = result.getAlignments(); - if(alignments != null) { - node.setHorizontalAlignment(1, row, (byte) alignments[0].ordinal()); - node.setHorizontalAlignment(2, row, (byte) alignments[1].ordinal()); - node.setHorizontalAlignment(3, row, (byte) alignments[2].ordinal()); - } else { - node.setHorizontalAlignment(1, row, (byte) getAlignment(1).ordinal()); - node.setHorizontalAlignment(2, row, (byte) getAlignment(2).ordinal()); - node.setHorizontalAlignment(3, row, (byte) getAlignment(3).ordinal()); - } - - Alignment[] verticalAlignments = result.getVerticalAlignments(); - if(verticalAlignments != null) { - node.setVerticalAlignment(1, row, (byte) verticalAlignments[0].ordinal()); - node.setVerticalAlignment(2, row, (byte) verticalAlignments[1].ordinal()); - node.setVerticalAlignment(3, row, (byte) verticalAlignments[2].ordinal()); - } else { - node.setVerticalAlignment(1, row, (byte) getVerticalAlignment(1).ordinal()); - node.setVerticalAlignment(2, row, (byte) getVerticalAlignment(2).ordinal()); - node.setVerticalAlignment(3, row, (byte) getVerticalAlignment(3).ordinal()); - } + String value = result != null ? result.getText1() : null; + String value2 = result != null ? result.getText2() : null; + String value3 = result != null ? result.getText3() : null; - node.setZIndex(3000); + double spacing = result.getSpacing(); - org.simantics.common.color.Color color = result.getColor(); - java.awt.Color awtColor = color != null ? Colors.awt(color) : Color.DARK_GRAY; + final Function1 modifier = result != null ? result.getModifier() : null; + final Function1 validator = result != null ? result.getValidator() : null; + final Function1 translator = result != null ? result.getTranslator() : null; + final RVI rvi = result != null ? result.getRVI() : null; - setTextNodeData(node, 1, row, value, FONT, awtColor, BACKGROUND_COLOR); - setTextNodeData(node, 2, row, value2, result.getPending(), FONT, awtColor, BACKGROUND_COLOR); - setTextNodeData(node, 3, row, value3, FONT, awtColor, BACKGROUND_COLOR); + node.setRowId(row, result.getRowId()); - node.setEditable(1, row, false); - node.setForceEventListening(2, row, true); - node.setEditable(2, row, modifier != null); - node.setEditable(3, row, false); + //setCurrentRowNumber(observer, _node, result.getRowId(), row); - final int finalRow = row; + //observer.setTemporaryProperty(_node, "location", row + 1); - if (modifier != null) { - node.setTextListener(2, row, new ITextListener() { - @Override - public void textChanged() {} + node.setText(2, row, value2); + node.setUp(result.getUp()); - @Override - public void textEditingStarted() {} + //MonitorTextGridResult cache = node.getCache(1, row); + //if(cache != null && cache.sameStructure(result)) return; - @Override - public void textEditingCancelled() { - } + node.setCache(1, row, result); - @Override - public void textEditingEnded() { + boolean isConnection = _node instanceof ConnectionNode; - TextNode t = node.get(2, finalRow); - if (t == null) - return; + Rectangle2D elementBounds = isConnection ? EMPTY_BOUNDS : NodeUtil.getLocalElementBounds(_node); + if (elementBounds == null) { + new Exception("Cannot get local element bounds for node " + _node.toString()).printStackTrace(); + // This is here for checking why getLocalElementBounds failed in the debugger. + NodeUtil.getLocalElementBounds(_node); + return; + } + + //System.err.println("elementBounds " + elementBounds); + //System.err.println("parentTransform " + result.getParentTransform()); + + AffineTransform at = style.getTransform(_node,result.getParentTransform(), elementBounds, row, result.getUp()); + Vec2d offset = result.getOffset(); + + Point2D[] cellOffsets = style.getCellOffsets(); + + AffineTransform at1 = new AffineTransform(at); + at1.translate(cellOffsets[0].getX(),cellOffsets[0].getY()); + AffineTransform at2 = new AffineTransform(at); + at2.translate(cellOffsets[1].getX()+spacing,cellOffsets[1].getY()); + AffineTransform at3 = new AffineTransform(at); + at3.translate(cellOffsets[2].getX()+spacing,cellOffsets[2].getY()); + + at1.translate(offset.x, offset.y); + at2.translate(offset.x, offset.y); + at3.translate(offset.x, offset.y); + + node.setTransform(1, row, at1); + node.setTransform(2, row, at2); + node.setTransform(3, row, at3); + + Alignment[] alignments = result.getAlignments(); + if(alignments != null) { + node.setHorizontalAlignment(1, row, (byte) alignments[0].ordinal()); + node.setHorizontalAlignment(2, row, (byte) alignments[1].ordinal()); + node.setHorizontalAlignment(3, row, (byte) alignments[2].ordinal()); + } else { + node.setHorizontalAlignment(1, row, (byte) style.getAlignment(1).ordinal()); + node.setHorizontalAlignment(2, row, (byte) style.getAlignment(2).ordinal()); + node.setHorizontalAlignment(3, row, (byte) style.getAlignment(3).ordinal()); + } - if(!t.getText().equals(t.getTextBeforeEdit())) - modifier.apply(t.getText()); + Alignment[] verticalAlignments = result.getVerticalAlignments(); + if(verticalAlignments != null) { + node.setVerticalAlignment(1, row, (byte) verticalAlignments[0].ordinal()); + node.setVerticalAlignment(2, row, (byte) verticalAlignments[1].ordinal()); + node.setVerticalAlignment(3, row, (byte) verticalAlignments[2].ordinal()); + } else { + node.setVerticalAlignment(1, row, (byte) style.getVerticalAlignment(1).ordinal()); + node.setVerticalAlignment(2, row, (byte) style.getVerticalAlignment(2).ordinal()); + node.setVerticalAlignment(3, row, (byte) style.getVerticalAlignment(3).ordinal()); + } - } - }); - } else { - node.setTextListener(2, row, null); - } + node.setZIndex(3000); + + org.simantics.common.color.Color color = result.getColor(); + Color awtColor = color != null ? Colors.awt(color) : Color.DARK_GRAY; + Color bgColor = style.getBackgroundColor(); + Font font = style.getFont(); + style.setTextNodeData(node, 1, row, value, font, awtColor, bgColor); + style.setTextNodeData(node, 2, row, value2, result.getPending(), font, awtColor, bgColor); + style.setTextNodeData(node, 3, row, value3, font, awtColor, bgColor); + + node.setEditable(1, row, false); + node.setForceEventListening(2, row, true); + node.setEditable(2, row, modifier != null); + node.setEditable(3, row, false); + + final int finalRow = row; + + if (modifier != null) { + node.setTextListener(2, row, new ITextListener() { + @Override + public void textChanged() {} + + @Override + public void textEditingStarted() {} + + @Override + public void textEditingCancelled() { + } + + @Override + public void textEditingEnded() { + + TextNode t = node.get(2, finalRow); + if (t == null) + return; + + if(!t.getText().equals(t.getTextBeforeEdit())) + modifier.apply(t.getText()); + + } + }); + } else { + node.setTextListener(2, row, null); + } - node.setInputValidator(2, row, validator); - node.setTranslator(translator); - - node.setRVI(2, row, rvi); + node.setInputValidator(2, row, validator); + node.setTranslator(translator); - postProcessNode(node, row); + node.setRVI(2, row, rvi); - } else { - cleanupStyleForNode(observer, _node); + style.postProcessNode(node, row); + } + } + // remove excess rows + int rowCount = node.computeRows(); + while (row < rowCount) { + row++; + node.removeRow(row); } } @@ -336,6 +357,14 @@ public abstract class TextGridStyle extends StyleBase { node.setPending(x, y, pending); } + protected Font getFont() { + return FONT; + } + + protected Color getBackgroundColor() { + return BACKGROUND_COLOR; + } + protected Alignment getAlignment(int column) { switch(column) { case 1: return Alignment.TRAILING; @@ -351,18 +380,21 @@ public abstract class TextGridStyle extends StyleBase { @Override protected void cleanupStyleForNode(EvaluationContext observer, INode _node) { - Integer row = observer.getProperty(_node, id); - //System.out.println(this + " cleanup(" + id + ", " + row + ")"); - //System.out.println(element); - if (row == null) - return; - observer.setProperty(_node, id, null); - TextGridNode node = ProfileVariables.browseChild(_node, "TextGridStyle"); - if (node != null) - node.removeRow(row); + Map> rows = observer.getProperty(_node, "rows"); + if (rows != null) { + rows.remove(rowIdKey()); + if (rows.isEmpty()) { + observer.setProperty(_node, "rows", null); + } + } + refreshAll(observer, _node); } protected void postProcessNode(TextGridNode node, int row) { } + private String rowIdKey() { + return "style" + getIdentity().toString(); + } + }