]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/connection/HighlightActionPointsAction.java
Sync git svn branch with SVN repository r33319.
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / g2d / nodes / connection / HighlightActionPointsAction.java
index 04d08e3ec155242b1b6d58fad89f62adbab6e3d7..7f7bd3cd9b99f434f16c68b6a55adfcd2ab3b357 100644 (file)
@@ -13,23 +13,23 @@ package org.simantics.scenegraph.g2d.nodes.connection;
 \r
 import java.awt.AlphaComposite;\r
 import java.awt.BasicStroke;\r
+import java.awt.Color;\r
 import java.awt.Composite;\r
 import java.awt.Graphics2D;\r
+import java.awt.Shape;\r
 import java.awt.Stroke;\r
 import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Point2D;\r
 import java.awt.geom.Rectangle2D;\r
-import java.awt.image.BufferedImage;\r
-import java.io.IOException;\r
-import java.net.URL;\r
 import java.util.ArrayList;\r
 import java.util.Collection;\r
 \r
-import javax.imageio.ImageIO;\r
-\r
 import org.simantics.diagram.connection.RouteGraph;\r
 import org.simantics.diagram.connection.RouteLineHalf;\r
 import org.simantics.diagram.connection.actions.IAction;\r
 import org.simantics.diagram.connection.rendering.IRouteGraphRenderer;\r
+import org.simantics.scenegraph.utils.Quality;\r
+import org.simantics.scenegraph.utils.QualityHints;\r
 \r
 /**\r
  * @author Tuukka Lehtonen\r
@@ -67,26 +67,25 @@ public class HighlightActionPointsAction implements IAction {
         }\r
     }\r
 \r
-    static BufferedImage                cross;\r
-    static BufferedImage                cut;\r
+    private static final Shape          CROSS_SHAPE             = ActionShapes.CROSS_SHAPE;\r
+    private static final Shape          SCISSOR_SHAPE           = ActionShapes.transformShape(ActionShapes.SCISSOR_SHAPE, 1, 1, 0, 0, -Math.PI/2);\r
 \r
-    static {\r
-        cross = safeReadImage("cross.png");\r
-        cut = safeReadImage("cut.png");\r
-    }\r
+    private static final Color          CROSS_COLOR             = new Color(0xe4, 0x40, 0x61);\r
+    private static final Color          SCISSOR_COLOR           = new Color(20, 20, 20);\r
 \r
     public static final Stroke          STROKE                  = new BasicStroke(0.1f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);\r
-    public static final AlphaComposite  COMPOSITE               = AlphaComposite.SrcOver.derive(0.6f);\r
+    public static final AlphaComposite  NO_HIT_COMPOSITE        = AlphaComposite.SrcOver.derive(0.8f);\r
+    public static final AlphaComposite  HIT_COMPOSITE           = AlphaComposite.SrcOver.derive(0.2f);\r
 \r
     public static final double          DEGENERATED_LINE_LENGTH = 1;\r
-    public static final double          CUT_DIST_FROM_END       = 0.5;\r
+    public static final double          CUT_DIST_FROM_END       = 0.75;\r
 \r
     RouteGraph                          rg;\r
 \r
     transient Collection<RouteLineHalf> lhs                     = new ArrayList<RouteLineHalf>();\r
     transient AffineTransform           transform               = new AffineTransform();\r
-    transient AffineTransform           transform2              = new AffineTransform();\r
     transient Rectangle2D               rect                    = new Rectangle2D.Double();\r
+    transient Point2D                   point                   = new Point2D.Double();\r
 \r
     public HighlightActionPointsAction(RouteGraph rg) {\r
         this.rg = rg;\r
@@ -98,94 +97,73 @@ public class HighlightActionPointsAction implements IAction {
 \r
     @Override\r
     public void render(Graphics2D g, IRouteGraphRenderer renderer, double mouseX, double mouseY) {\r
-        // Cannot perform cut or delete segment actions on connections between 2\r
-        // terminals.\r
+        // Cannot perform cut or delete segment actions\r
+        // on connections between 2 terminals.\r
         boolean simpleConnection = (rg.isSimpleConnection() || rg.getTerminals().size() <= 2);\r
         boolean branchedConnection = rg.getTerminals().size() > 2;\r
+        if (!branchedConnection || simpleConnection)\r
+            return;\r
+\r
+        AffineTransform preTr = g.getTransform();\r
+        double realViewScale = 1.0 / getScale(preTr);\r
+        //System.out.println(realViewScale);\r
+        // Don't render any of the actions if they could not be seen anyway.\r
+        if (realViewScale > 0.7)\r
+            return;\r
 \r
         lhs.clear();\r
         rg.getLineHalves(lhs);\r
 \r
-        AffineTransform preTr = g.getTransform();\r
-        double viewScale = 1.0 / getScale(preTr);\r
-        transform2.setToScale(viewScale, viewScale);\r
+        Pick pick = pickAction(rg, lhs, preTr, mouseX, mouseY);\r
+\r
         Composite originalComposite = g.getComposite();\r
-        g.setComposite(COMPOSITE);\r
+        Composite basicComposite = pick.action != null ? HIT_COMPOSITE : NO_HIT_COMPOSITE;\r
+        g.setComposite(basicComposite);\r
 \r
-        Pick pick = pickAction(rg, lhs, preTr, mouseX, mouseY);\r
+        // Always render these in high quality because otherwise the shapes\r
+        // will render with ugly artifacts when zoom level is a bit higher.\r
+        QualityHints origQualityHints = QualityHints.getQuality(g);\r
+        QualityHints.getHints(Quality.HIGH).setQuality(g);\r
 \r
+        // Render line removal markers\r
         if (!simpleConnection) {\r
-            double crossW = cross.getWidth()*viewScale*.5;\r
-            double crossH = cross.getHeight()*viewScale*.5;\r
-\r
-            // Render line removal markers\r
+            g.setPaint(CROSS_COLOR);\r
             for (RouteLineHalf lh : lhs) {\r
-//                if (lh.getLine().getLength() < DEGENERATED_LINE_LENGTH)\r
-//                    continue;\r
-//                if (!lh.getLine().isTransient())\r
-//                    continue;\r
-                if (lh.getLine().getTerminal() == null)\r
+                if (removeLocation(lh, point) == null)\r
                     continue;\r
-                double x = lh.getLink().getX();\r
-                double y = lh.getLink().getY();\r
-                if (lh.getLine().isHorizontal()) {\r
-                    x = (lh.getLine().getBegin().getX() + lh.getLine().getEnd().getX()) * .5;\r
-                } else {\r
-                    y = (lh.getLine().getBegin().getY() + lh.getLine().getEnd().getY()) * .5;\r
-                }\r
-\r
                 boolean hit = pick.matches(Action.REMOVE, lh);\r
-\r
                 if (hit)\r
                     g.setComposite(originalComposite);\r
-                transform.setToTranslation(x-crossW, y-crossH);\r
-                g.transform(transform);\r
-                g.drawImage(cross, transform2, null);\r
+                g.translate(point.getX(), point.getY());\r
+                g.fill(CROSS_SHAPE);\r
                 g.setTransform(preTr);\r
                 if (hit)\r
-                    g.setComposite(COMPOSITE);\r
+                    g.setComposite(basicComposite);\r
             }\r
         }\r
 \r
         // Render reconnection markers if the connection is branched.\r
         if (branchedConnection) {\r
-            double cutW = cut.getWidth()*viewScale*.5;\r
-            double cutH = cut.getHeight()*viewScale*.5;\r
-\r
-            final double dist = CUT_DIST_FROM_END;\r
+            g.setPaint(SCISSOR_COLOR);\r
             for (RouteLineHalf lh : lhs) {\r
-                if (lh.getLine().getLength() < DEGENERATED_LINE_LENGTH*3)\r
+                if (reconnectLocation(lh, point) == null)\r
                     continue;\r
-                double x = lh.getLink().getX();\r
-                double y = lh.getLink().getY();\r
-                if (lh.getLine().isHorizontal()) {\r
-                    if (lh.getLink() == lh.getLine().getBegin())\r
-                        x += dist*2;\r
-                    else\r
-                        x -= dist*2;\r
-                } else {\r
-                    if (lh.getLink() == lh.getLine().getBegin())\r
-                        y += dist*2;\r
-                    else\r
-                        y -= dist*2;\r
-                }\r
-\r
                 boolean hit = pick.matches(Action.RECONNECT, lh);\r
-\r
                 if (hit)\r
                     g.setComposite(originalComposite);\r
-                transform.setToTranslation(x-cutW, y-cutH);\r
-                if (!lh.getLine().isHorizontal()) {\r
-                    transform.rotate(Math.PI/2, cutW, cutH);\r
-                }\r
+                transform.setToTranslation(point.getX(), point.getY());\r
+                if (!lh.getLine().isHorizontal())\r
+                    transform.rotate(Math.PI/2);\r
+                transform.translate(0, 0.35);\r
                 g.transform(transform);\r
-                g.drawImage(cut, transform2, null);\r
+                g.fill(SCISSOR_SHAPE);\r
                 g.setTransform(preTr);\r
                 if (hit)\r
-                    g.setComposite(COMPOSITE);\r
+                    g.setComposite(basicComposite);\r
             }\r
         }\r
 \r
+        origQualityHints.setQuality(g);\r
         g.setComposite(originalComposite);\r
     }\r
 \r
@@ -205,35 +183,23 @@ public class HighlightActionPointsAction implements IAction {
         if (!branchedConnection || simpleConnection || viewTr == null)\r
             return Pick.MISS;\r
 \r
-        lhs.clear();\r
-        rg.getLineHalves(lhs);\r
+        double viewScale = 1.0 / getScale(viewTr);\r
+        if (viewScale > 0.7)\r
+            return Pick.MISS;\r
 \r
+        double nearest = Double.MAX_VALUE;\r
         RouteLineHalf selected = null;\r
         Action selectedAction = null;\r
-        double nearest = Double.MAX_VALUE;\r
-        double viewScale = 1.0 / getScale(viewTr);\r
 \r
+        // Pick line removal markers\r
         if (!simpleConnection) {\r
-            double crossW = cross.getWidth()*viewScale*.5;\r
-            double crossH = cross.getHeight()*viewScale*.5;\r
-\r
-            // Render line removal markers\r
+            double s = ActionShapes.CROSS_WIDTH * 0.25;\r
             for (RouteLineHalf lh : lhs) {\r
-//                if (lh.getLine().getLength() < DEGENERATED_LINE_LENGTH)\r
-//                    continue;\r
-//                if (!lh.getLine().isTransient())\r
-//                    continue;\r
-                if (lh.getLine().getTerminal() == null)\r
+                if (removeLocation(lh, point) == null)\r
                     continue;\r
-                double x = lh.getLink().getX();\r
-                double y = lh.getLink().getY();\r
-                if (lh.getLine().isHorizontal()) {\r
-                    x = (lh.getLine().getBegin().getX() + lh.getLine().getEnd().getX()) * .5;\r
-                } else {\r
-                    y = (lh.getLine().getBegin().getY() + lh.getLine().getEnd().getY()) * .5;\r
-                }\r
-\r
-                rect.setFrameFromCenter(x, y, x-crossW, y-crossH);\r
+                double x = point.getX();\r
+                double y = point.getY();\r
+                rect.setFrameFromCenter(x, y, x-s, y-s);\r
                 boolean hit = rect.contains(mouseX, mouseY);\r
                 if (hit) {\r
                     double distSq = distSq(x, y, mouseX, mouseY);\r
@@ -246,35 +212,21 @@ public class HighlightActionPointsAction implements IAction {
             }\r
         }\r
 \r
-        // Render reconnection markers if the connection is branched.\r
+        // Pick reconnection markers if the connection is branched.\r
         if (branchedConnection) {\r
-            double cutW = cut.getWidth()*viewScale*.5;\r
-            double cutH = cut.getHeight()*viewScale*.5;\r
-\r
-            final double dist = CUT_DIST_FROM_END;\r
+            double w = ActionShapes.SCISSOR_HEIGHT * 0.4;\r
+            double h = ActionShapes.SCISSOR_WIDTH * 0.3;\r
             for (RouteLineHalf lh : lhs) {\r
-                if (lh.getLine().getLength() < DEGENERATED_LINE_LENGTH*3)\r
+                if (reconnectLocation(lh, point) == null)\r
                     continue;\r
-                double x = lh.getLink().getX();\r
-                double y = lh.getLink().getY();\r
-                if (lh.getLine().isHorizontal()) {\r
-                    if (lh.getLink() == lh.getLine().getBegin())\r
-                        x += dist*2;\r
-                    else\r
-                        x -= dist*2;\r
-                } else {\r
-                    if (lh.getLink() == lh.getLine().getBegin())\r
-                        y += dist*2;\r
-                    else\r
-                        y -= dist*2;\r
-                }\r
-\r
-                rect.setFrameFromCenter(x, y, x-cutW, y-cutH);\r
+                double x = point.getX();\r
+                double y = point.getY();\r
+                rect.setFrameFromCenter(x, y, x-w, y-h);\r
                 boolean hit = rect.contains(mouseX, mouseY);\r
                 if (hit) {\r
                     double distSq = distSq(x, y, mouseX, mouseY);\r
                     if (distSq < nearest) {\r
-                        nearest = dist;\r
+                        nearest = distSq;\r
                         selected = lh;\r
                         selectedAction = Action.RECONNECT;\r
                     }\r
@@ -285,6 +237,43 @@ public class HighlightActionPointsAction implements IAction {
         return selected == null ? Pick.MISS : new Pick(selectedAction, selected);\r
     }\r
 \r
+    private static Point2D removeLocation(RouteLineHalf lh, Point2D p) {\r
+        if (lh.getLine().getTerminal() == null)\r
+            return null;\r
+\r
+        double x = lh.getLink().getX();\r
+        double y = lh.getLink().getY();\r
+        if (lh.getLine().isHorizontal()) {\r
+            x = (lh.getLine().getBegin().getX() + lh.getLine().getEnd().getX()) * .5;\r
+        } else {\r
+            y = (lh.getLine().getBegin().getY() + lh.getLine().getEnd().getY()) * .5;\r
+        }\r
+        p.setLocation(x, y);\r
+        return p;\r
+    }\r
+\r
+    private static Point2D reconnectLocation(RouteLineHalf lh, Point2D p) {\r
+        if (lh.getLine().getLength() < DEGENERATED_LINE_LENGTH*3)\r
+            return null;\r
+\r
+        final double dist = CUT_DIST_FROM_END;\r
+        double x = lh.getLink().getX();\r
+        double y = lh.getLink().getY();\r
+        if (lh.getLine().isHorizontal()) {\r
+            if (lh.getLink() == lh.getLine().getBegin())\r
+                x += dist*2;\r
+            else\r
+                x -= dist*2;\r
+        } else {\r
+            if (lh.getLink() == lh.getLine().getBegin())\r
+                y += dist*2;\r
+            else\r
+                y -= dist*2;\r
+        }\r
+        p.setLocation(x, y);\r
+        return p;\r
+    }\r
+\r
     private static double distSq(double x1, double y1, double x2, double y2) {\r
         double dx = x2 - x1;\r
         double dy = y2 - y1;\r
@@ -301,13 +290,4 @@ public class HighlightActionPointsAction implements IAction {
         return Math.sqrt(Math.abs(m00*m11 - m10*m01));\r
     }\r
 \r
-    private static BufferedImage safeReadImage(String name) {\r
-        try {\r
-            URL url = HighlightActionPointsAction.class.getResource(name);\r
-            return ImageIO.read(url);\r
-        } catch (IOException e) {\r
-            return null;\r
-        }\r
-    }\r
-\r
 }\r