]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Preliminary implementation to update only changed profile entries
authorJussi Koskela <jussi.koskela@semantum.fi>
Wed, 24 Oct 2018 12:23:23 +0000 (15:23 +0300)
committerAntti Villberg <antti.villberg@semantum.fi>
Tue, 13 Nov 2018 04:53:02 +0000 (06:53 +0200)
Marks related elements dirty.

Change-Id: Id93d9126393f6840cb028c11cac095b1078f229e

bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/ConstantStyle.java
bundles/org.simantics.diagram/src/org/simantics/diagram/elements/TextGridNode.java
bundles/org.simantics.diagram/src/org/simantics/diagram/profile/ShowRelatedElements.java
bundles/org.simantics.diagram/src/org/simantics/diagram/profile/StyleBase.java
bundles/org.simantics.diagram/src/org/simantics/diagram/profile/TextGridStyle.java
bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/Observer.java
bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/Style.java
bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ProfileObserver.java

index 4a59f4b3c8e96268a2097746cfc7accbeb452e56..e81d483bb93a3a6efe89b8786c93e6a60356e030 100644 (file)
@@ -38,6 +38,7 @@ public class ConstantStyle implements Style {
     final String name;
     final Map<String, Object> values = new HashMap<String, Object>();
     ObserverGroupListener listener = null;
+    double priority;
 
     public ConstantStyle(ReadGraph graph, Resource style) throws DatabaseException {
         Layer0 L0 = Layer0.getInstance(graph);
@@ -51,6 +52,14 @@ public class ConstantStyle implements Style {
         }
     }
 
+    public void setPriority(double priority) {
+        this.priority = priority;
+    }
+    
+    public double getPriority() {
+        return priority;
+    }
+    
     private Object haxx(String key, Object value) {
         if("alpha".equals(key)) {
             return AlphaComposite.getInstance(AlphaComposite. SRC_OVER, Float.parseFloat((String)value));
@@ -128,6 +137,16 @@ public class ConstantStyle implements Style {
         }
 
     }
+    
+    @Override
+    public final void apply2(Object item, final EvaluationContext evaluationContext) {
+        final DataNodeMap map = evaluationContext.getConstant(ProfileKeys.NODE_MAP);
+        final INode node = map.getNode(item);
+        
+        for(Map.Entry<String, Object> value : values.entrySet()) {
+            ProfileVariables.claimNodeProperty(node, value.getKey(), value.getValue(), evaluationContext);
+        }
+    }
 
     @Override
     public String toString() {
index f482890e9f762f724cf1373b56dfa09465e614ad..9f25778843a51b2d569b1e9804597e466de25510 100644 (file)
@@ -138,7 +138,7 @@ public class TextGridNode extends G2DParentNode implements Decoration {
         }
     }
 
-    private int computeRows() {
+    public int computeRows() {
         MaxY maxy = new MaxY();
         nodes.forEachKey(maxy);
         return maxy.max;
@@ -245,6 +245,7 @@ public class TextGridNode extends G2DParentNode implements Decoration {
     }
 
     public void removeRow(int y) {
+        rowIds.remove(y);
         List<Cell> row = peekRowCells(y);
         if (row.isEmpty())
             return;
index a18191a671e9497151ad3c105e6f10da37821912..cd4786088afc2ad4358e5b51eb17be19aca7d609 100644 (file)
@@ -178,7 +178,7 @@ public class ShowRelatedElements extends StyleBase<Object> {
     public void applyStyleForItem(EvaluationContext evaluationContext, DataNodeMap map, Object item, Object value) {
         INode node = map.getNode(item);
         if (node == null) {
-            evaluationContext.update();
+            evaluationContext.update(this, item);
             return;
         }
 
index 9978076c641abd89d207c86610f664c609fc1b0b..f8565dcf7129437696963642a093bd684dbb36ab 100644 (file)
@@ -27,8 +27,10 @@ import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.procedure.Listener;
 import org.simantics.db.request.Read;
 import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.g2d.canvas.Hints;
 import org.simantics.g2d.canvas.ICanvasContext;
 import org.simantics.g2d.diagram.IDiagram;
+import org.simantics.g2d.diagram.handler.DataElementMap;
 import org.simantics.g2d.element.IElement;
 import org.simantics.scenegraph.INode;
 import org.simantics.scenegraph.profile.DataNodeMap;
@@ -67,6 +69,7 @@ import org.simantics.utils.datastructures.Pair;
 public abstract class StyleBase<Result> implements Style {
 
     private Object identity;
+    private double priority;
 
     public StyleBase(Object identity) {
         this.identity = identity;
@@ -81,6 +84,14 @@ public abstract class StyleBase<Result> implements Style {
         return (T)identity;
     }
 
+    public void setPriority(double priority) {
+        this.priority = priority;
+    }
+    
+    public double getPriority() {
+        return priority;
+    }
+    
     @Override
     public int hashCode() {
         final int prime = 31;
@@ -207,7 +218,7 @@ public abstract class StyleBase<Result> implements Style {
             StyleBaseData.getInstance().removeValue(new Tuple3(this, runtimeDiagram, object));
         else
             StyleBaseData.getInstance().putValue(new Tuple3(this, runtimeDiagram, object), result);
-        observer.update();
+        observer.update(this, object);
     }
 
     /**
@@ -232,7 +243,7 @@ public abstract class StyleBase<Result> implements Style {
         
         final INode node = map.getNode(item);
         if (node == null) {
-            evaluationContext.update();
+            evaluationContext.update(this, item);
             // TODO: continue or return?
             return;
         }
@@ -241,7 +252,6 @@ public abstract class StyleBase<Result> implements Style {
             System.out.println(StyleBase.this + ": applying style for item " + item + " and element " + node + " with result " + value);
 
         applyStyleForNode(evaluationContext, node, value);
-        
     }
 
     /**
@@ -426,7 +436,8 @@ public abstract class StyleBase<Result> implements Style {
                 cleanupItems(observer, diagram, listener.getItems().toArray());
                 diagram = null;
             }
-            observer.update();
+            
+            //observer.update(); TODO: Check if this is required!
         }
 
     }
@@ -436,7 +447,6 @@ public abstract class StyleBase<Result> implements Style {
      */
     @Override
     public final void apply(Resource entry, Group group, final EvaluationContext evaluationContext) {
-
         ICanvasContext context = evaluationContext.getConstant(ProfileKeys.CANVAS);
         
         assert context.getThreadAccess().currentThreadAccess();
@@ -460,10 +470,32 @@ public abstract class StyleBase<Result> implements Style {
         for (Object item : listener.getItems()) {
             Result value = data.getValue(new Tuple3(this, evaluationContext.getResource(), item));
             applyStyleForItem(evaluationContext, map, item, value);
+            
+            IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM);
+            DataElementMap emap = diagram.getDiagramClass().getSingleItem(DataElementMap.class);
+            IElement element = emap.getElement(diagram, item);
+            element.setHint(Hints.KEY_DIRTY, Hints.VALUE_SG_DIRTY);
         }
         
     }
 
+    @Override
+    public final void apply2(Object item, final EvaluationContext evaluationContext) {
+        final DataNodeMap map = evaluationContext.getConstant(ProfileKeys.NODE_MAP);
+        
+        StyleBaseData data = StyleBaseData.getInstance();
+        
+        data.applyRemovals(evaluationContext, this);
+
+        Result value = data.getValue(new Tuple3(this, evaluationContext.getResource(), item));
+        applyStyleForItem(evaluationContext, map, item, value);
+        
+        IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM);
+        DataElementMap emap = diagram.getDiagramClass().getSingleItem(DataElementMap.class);
+        IElement element = emap.getElement(diagram, item);
+        element.setHint(Hints.KEY_DIRTY, Hints.VALUE_SG_DIRTY);
+    }
+    
     /**
      * This is ran when this profile entry gets deactivated after being first
      * active. It allows cleaning up scene graph left-overs for the listened set
@@ -495,6 +527,12 @@ public abstract class StyleBase<Result> implements Style {
 
                 for (Object item : items) {
                     cleanupStyleForItem(evaluationContext, map, item);
+
+                    IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM);
+                    DataElementMap emap = diagram.getDiagramClass().getSingleItem(DataElementMap.class);
+                    IElement element = emap.getElement(diagram, item);
+                    element.setHint(Hints.KEY_DIRTY, Hints.VALUE_SG_DIRTY);
+
                 }
             }
         });
index 997ace1d63f12a87db7fc6fcaaec5f630fc92be3..f4f398da04ecc507490b32d9f864b93b257b21ca 100644 (file)
@@ -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
@@ -149,179 +155,197 @@ public abstract class TextGridStyle extends StyleBase<MonitorTextGridResult> {
 
        @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<String, String> modifier = result != null ? result.getModifier() : null;
-                       final Function1<String, String> validator = result != null ? result.getValidator() : null;
-                       final Function1<Vec2d, Boolean> 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)
-                               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;
-
-                       // Remove from existing row to add to another row if necessary.
-                       Integer row = getCurrentRowNumber(observer, _node);
-                       if (row != null && row != newRow) {
-                               String actualId = node.getRowId(row);
-                               String id = observer.getProperty(_node, rowIdKey());
-                               if (id.equals(actualId)) {
-                                       node.removeRow(row);
-                               }
-                       }
-                       row = newRow;
-
-                       node.setRowId(row, result.getRowId());
-
-                       setCurrentRowNumber(observer, _node, result.getRowId(), row);
-
-                       observer.setTemporaryProperty(_node, "location", row + 1);
-
-                       node.setText(2, row, value2);
-                       node.setUp(result.getUp());
-
-                       MonitorTextGridResult cache = node.getCache(1, row);
-                       if(cache != null && cache.sameStructure(result)) return;
-
-                       node.setCache(1, row, result);
-
-                       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;
+                       Map<String, Pair<TextGridStyle, MonitorTextGridResult>> rows = observer.getProperty(_node, "rows");
+                       if (rows == null) {
+                           rows = new HashMap<String, Pair<TextGridStyle, MonitorTextGridResult>>();
+                           observer.setProperty(_node, "rows", rows);
                        }
-
-                       //            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());
+                       Pair<TextGridStyle, MonitorTextGridResult> oldResultPair = rows.get(result.getRowId());
+                       if (oldResultPair != null && oldResultPair.first == this && oldResultPair.second.sameStructure(result)) {
+                           return;
                        }
-
-                       node.setZIndex(3000);
-
-                       org.simantics.common.color.Color color = result.getColor();
-                       Color awtColor = color != null ? Colors.awt(color) : Color.DARK_GRAY;
-                       Color bgColor = getBackgroundColor();
-                       Font font = getFont();
-
-                       setTextNodeData(node, 1, row, value, font, awtColor, bgColor);
-                       setTextNodeData(node, 2, row, value2, result.getPending(), font, awtColor, bgColor);
-                       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);
-
-                       postProcessNode(node, row);
-
+                       
+                       rows.put(rowIdKey(), new Pair<TextGridStyle, MonitorTextGridResult>(this, result));
+                       
+                       // FIXME: Improve performance by calling refreshAll only once after all text grid style changes have been applied
+                       refreshAll(observer, _node);
                } else {
                        cleanupStyleForNode(observer, _node);
                }
        }
 
+       private static void refreshAll(EvaluationContext observer, INode _node) {
+           final TextGridNode node = ProfileVariables.claimChild(_node, "", "TextGridStyle", TextGridNode.class, observer);
+        if (node == null)
+            return;
+           
+           
+        int row = 0;
+        Map<String, Pair<TextGridStyle, MonitorTextGridResult>> rows = observer.getProperty(_node, "rows");
+           if (rows != null) {
+           List<Pair<TextGridStyle, MonitorTextGridResult>> sortedRows = rows.values().stream().sorted(new Comparator<Pair<TextGridStyle, MonitorTextGridResult>>() {
+                @Override
+                public int compare(Pair<TextGridStyle, MonitorTextGridResult> o1, Pair<TextGridStyle, MonitorTextGridResult> o2) {
+                    return Double.compare(o1.first.getPriority(), o2.first.getPriority());
+                }
+            }).collect(Collectors.toList());
+           
+               
+               for (Pair<TextGridStyle, MonitorTextGridResult> resultPair : sortedRows) {
+               row++;
+               TextGridStyle style = resultPair.first;
+               MonitorTextGridResult result = resultPair.second;
+               
+               String value = result != null ? result.getText1() : null;
+    
+               String value2 = result != null ? result.getText2() : null;
+                String value3 = result != null ? result.getText3() : null;
+    
+                double spacing = result.getSpacing();
+    
+                final Function1<String, String> modifier = result != null ? result.getModifier() : null;
+                final Function1<String, String> validator = result != null ? result.getValidator() : null;
+                final Function1<Vec2d, Boolean> translator = result != null ? result.getTranslator() : null;
+                final RVI rvi = result != null ? result.getRVI() : null;
+    
+               
+                node.setRowId(row, result.getRowId());
+        
+                //setCurrentRowNumber(observer, _node, result.getRowId(), row);
+        
+                //observer.setTemporaryProperty(_node, "location", row + 1);
+        
+                node.setText(2, row, value2);
+                node.setUp(result.getUp());
+        
+                //MonitorTextGridResult cache = node.getCache(1, row);
+                //if(cache != null && cache.sameStructure(result)) return;
+        
+                node.setCache(1, row, result);
+        
+                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;
+                }
+        
+                //            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());
+                }
+        
+                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());
+                }
+        
+                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);
+        
+                style.postProcessNode(node, row);
+           }
+           }
+           // remove excess rows
+        int rowCount = node.computeRows();
+        while (row < rowCount) {
+            row++;
+            node.removeRow(row);
+        }
+           
+       }
+       
        private void setTextNodeData(TextGridNode node, int x, int y, String text, Font font, Color fgColor, Color bgColor) {
                if (text != null) {
                        node.setText(x, y, text);
@@ -362,38 +386,14 @@ public abstract class TextGridStyle extends StyleBase<MonitorTextGridResult> {
 
        @Override
        protected void cleanupStyleForNode(EvaluationContext observer, INode _node) {
-               Integer row = getCurrentRowNumber(observer, _node);
-               //System.out.println(this + " cleanup(" + id + ", " + row + ")");
-               //System.out.println(element);
-               if (row == null)
-                       return;
-               clearCurrentRowNumber(observer, _node);
-               TextGridNode node = ProfileVariables.browseChild(_node, "TextGridStyle");
-               if (node != null)
-                       node.removeRow(row);
-       }
-
-       private Integer getCurrentRowNumber(EvaluationContext observer, INode _node) {
-               String rowId = observer.getProperty(_node, rowIdKey());
-               return observer.getProperty(_node, rowId);
-       }
-
-       private void setCurrentRowNumber(EvaluationContext observer, INode _node, String rowId, int row) {
-               // Mapping style identity -> rowId (resourceId)
-               observer.setProperty(_node, rowIdKey(), rowId);
-               // Mapping rowId (resourceId) -> row number
-               observer.setProperty(_node, rowId, row);
-       }
-
-       private void clearCurrentRowNumber(EvaluationContext observer, INode _node) {
-               String rowId = observer.getProperty(_node, rowIdKey());
-               if(rowId != null) {
-                       observer.setProperty(_node, rowIdKey(), null);
-                       Integer row = observer.getProperty(_node, rowId);
-                       if(row != null) {
-                               observer.setProperty(_node, rowId, null);
-                       }
-               }
+           Map<String, Pair<Double, MonitorTextGridResult>> 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) {
index 48dce8fd2b271d78b96a8348d22bf7b466c1a735..34343870af2001e5b143978c78bd0d2fb6167a4c 100644 (file)
@@ -25,6 +25,12 @@ public interface Observer {
      * requesting for style re-application for the whole diagram.
      */
     void update();
+    
+    /**
+     * Notifies this profile system instance that a profile subsystem is
+     * requesting for style re-application for the given item.
+     */
+    void update(Style style, Object item);
 
     /**
      * For logging exceptional situations that occur within profile entries or
index c719df2d7aaf862afa12b9dee67aeee6b7b3fa2b..4eecce9fc09d33421c8779968f4daec6c715fb00 100644 (file)
@@ -66,5 +66,8 @@ public interface Style {
      * @param observer profile system observer for this canvas context
      */
     void apply(Resource entry, Group group, EvaluationContext observer);
-
+    
+    void apply2(Object item, EvaluationContext observer);
+    void setPriority(double priority);
+    double getPriority();
 }
index efac19055944c8a2ab3bc713dd3100647755d9f8..e3615d4a990a0d79bb3922b7116bd67ef7f82b42 100644 (file)
  *******************************************************************************/
 package org.simantics.scenegraph.profile.common;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
@@ -28,9 +30,11 @@ import org.simantics.scenegraph.INode;
 import org.simantics.scenegraph.g2d.G2DSceneGraph;
 import org.simantics.scenegraph.profile.EvaluationContext;
 import org.simantics.scenegraph.profile.ProfileEntry;
+import org.simantics.scenegraph.profile.Style;
 import org.simantics.scenegraph.profile.impl.DebugPolicy;
 import org.simantics.scenegraph.profile.impl.ProfileActivationListener;
 import org.simantics.scenegraph.profile.request.RuntimeProfileActiveEntries;
+import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.datastructures.disposable.IDisposable;
 import org.simantics.utils.threads.IThreadWorkQueue;
 import org.simantics.utils.threads.ThreadUtils;
@@ -51,9 +55,12 @@ public class ProfileObserver implements EvaluationContext {
     private final Runnable                    notification;
     private final G2DSceneGraph               sceneGraph;
 
-    private boolean                           dirty               = true;
-    private boolean                           disposed            = false;
+    private volatile boolean                           dirty               = true;
+    private volatile boolean                           disposed            = false;
 
+    private List<Pair<Style, Object>> updates = new ArrayList<>();
+    private boolean updateAll;
+    
     private ProfileActivationListener         activationListener;
 
     private Map<String, Object>               constants           = new HashMap<String, Object>();
@@ -129,12 +136,20 @@ public class ProfileObserver implements EvaluationContext {
     }
 
     @Override
-    public void update() {
+    public void update(Style style, Object item) {
         if (DebugPolicy.DEBUG_PROFILE_OBSERVER_UPDATE)
             System.out.println("Profile observer marked dirty.");
+        
+        updates.add(new Pair<>(style, item));
+        //updateAll = true;
         dirty = true;
     }
 
+    public void update() {
+        updateAll = true;
+        dirty = true;
+    }
+    
     private void perform() {
         dirty = false;
         if (DebugPolicy.DEBUG_PROFILE_OBSERVER_UPDATE)
@@ -175,12 +190,32 @@ public class ProfileObserver implements EvaluationContext {
 //                            Variables.init(e, ProfileObserver.this);
 //                        }
 
-                        for(ProfileEntry e : entries) {
-                            if (DebugPolicy.DEBUG_PROFILE_OBSERVER_PERFORM)
-                                System.out.println("Apply profile entry: " + e);
-                            e.apply(ProfileObserver.this);
+                        
+                        long t0 = System.nanoTime();
+                        
+                        if (updateAll) {
+                            for(ProfileEntry e : entries) {
+                                if (DebugPolicy.DEBUG_PROFILE_OBSERVER_PERFORM)
+                                    System.out.println("Apply profile entry: " + e);
+                                e.apply(ProfileObserver.this);
+                            }
+                            updateAll = false;
+                            updates.clear();
+                        } else {
+                            List<Pair<Style, Object>> updatesCopy = new ArrayList<>(updates);
+                            updates.clear();
+                            for (Pair<Style, Object> update : updatesCopy) {
+                                Style style = update.first;
+                                Object item = update.second;
+                                
+                                style.apply2(item, ProfileObserver.this);
+                            }
                         }
 
+
+                        long t1 = System.nanoTime();
+                        System.out.println((t1-t0) / 1e6);
+                        
                         if(dirty) {
                                sceneGraph.setPending(ProfileObserver.this);
 //                             System.err.println("setPending, dirty=true");