1   /****************************************************************************
2    * This demo file is part of yFiles for Java 2.14.
3    * Copyright (c) 2000-2017 by yWorks GmbH, Vor dem Kreuzberg 28,
4    * 72070 Tuebingen, Germany. All rights reserved.
5    * 
6    * yFiles demo files exhibit yFiles for Java functionalities. Any redistribution
7    * of demo files in source code or binary form, with or without
8    * modification, is not permitted.
9    * 
10   * Owners of a valid software license for a yFiles for Java version that this
11   * demo is shipped with are allowed to use the demo source code as basis
12   * for their own yFiles for Java powered applications. Use of such programs is
13   * governed by the rights and conditions as set out in the yFiles for Java
14   * license agreement.
15   * 
16   * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
17   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19   * NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21   * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   *
27   ***************************************************************************/
28  package demo.view.isometry;
29  
30  import y.base.Node;
31  import y.view.DefaultLabelConfiguration;
32  import y.view.Graph2D;
33  import y.view.NodeLabel;
34  import y.view.NodeRealizer;
35  import y.view.YLabel;
36  
37  import java.awt.Color;
38  import java.awt.Font;
39  import java.awt.Graphics2D;
40  import java.awt.Insets;
41  import java.awt.font.TextLayout;
42  import java.awt.geom.AffineTransform;
43  import java.awt.geom.Rectangle2D;
44  
45  /**
46   * A painter that paints group node labels in an isometric fashion.
47   */
48  public class GroupLabelConfiguration extends DefaultLabelConfiguration {
49  
50    /**
51     * Paints the box of the label with the height of the label and the width of its group node at the bottom of the group
52     * node.
53     */
54    public void paintBox(YLabel label, Graphics2D gfx, double x, double y, double width, double height) {
55      // Save the original graphics context and restore it at the end of the method.
56      final AffineTransform oldTransform = gfx.getTransform();
57      final Color oldColor = gfx.getColor();
58  
59      // Calculate the corners of the node in the view space.
60      final double[] corners = new double[16];
61      final Node group = ((NodeLabel) label).getNode();
62      final NodeRealizer realizer = ((Graph2D) group.getGraph()).getRealizer(group);
63      final IsometryData isometryData = IsometryRealizerFactory.getIsometryData(realizer);
64      isometryData.calculateCorners(corners);
65      IsometryData.moveTo(realizer.getX(), realizer.getY(), corners);
66  
67      // The lower corner is the anchor of the label.
68      // Note: this label configuration does not take label models into account
69      final double anchorX = corners[IsometryData.C3_X];
70      final double anchorY = corners[IsometryData.C3_Y];
71  
72      // Set the transformation from the layout space into the view space on the graphics context.
73      gfx.translate(anchorX, anchorY);
74      gfx.transform(
75          new AffineTransform(
76              new double[]{
77                  IsometryData.M_TO_VIEW_11,
78                  IsometryData.M_TO_VIEW_21,
79                  IsometryData.M_TO_VIEW_12,
80                  IsometryData.M_TO_VIEW_22}));
81      gfx.translate(-anchorX, -anchorY);
82  
83      // Calculate the box of the label in the layout space. It uses the whole width of the node.
84      final Rectangle2D.Double rect = new Rectangle2D.Double(
85          anchorX,
86          anchorY - height,
87          isometryData.getWidth(),
88          height);
89  
90      // Paint the box of the label with the transformed graphics context.
91      gfx.setColor(label.getBackgroundColor());
92      gfx.fill(rect);
93      gfx.setColor(label.getLineColor());
94      gfx.draw(rect);
95  
96      // Restore the original graphics context.
97      gfx.setTransform(oldTransform);
98      gfx.setColor(oldColor);
99    }
100 
101   /**
102    * Paints the text of the label at the lower left corner of the group node.
103    */
104   public void paintContent(YLabel label, Graphics2D gfx, double x, double y, double width, double height) {
105     // Save the original graphics context and restore it at the end of the method.
106     final AffineTransform oldTransform = gfx.getTransform();
107     final Font oldFont = gfx.getFont();
108     final Color oldColor = gfx.getColor();
109 
110     // Calculate the corners of the node in the view space.
111     final double[] corners = new double[16];
112     final Node group = ((NodeLabel) label).getNode();
113     final NodeRealizer realizer = ((Graph2D) group.getGraph()).getRealizer(group);
114     final IsometryData isometryData = IsometryRealizerFactory.getIsometryData(realizer);
115     isometryData.calculateCorners(corners);
116     IsometryData.moveTo(realizer.getX(), realizer.getY(), corners);
117 
118     // The lower corner is the anchor of the label.
119     // Note: this label configuration does not take label models into account
120     final double anchorX = corners[IsometryData.C3_X];
121     final double anchorY = corners[IsometryData.C3_Y];
122 
123     // Set the transformation from the layout space into the view space on the graphics context.
124     gfx.translate(anchorX, anchorY);
125     gfx.transform(new AffineTransform(
126         new double[]{
127             IsometryData.M_TO_VIEW_11,
128             IsometryData.M_TO_VIEW_21,
129             IsometryData.M_TO_VIEW_12,
130             IsometryData.M_TO_VIEW_22}));
131     gfx.translate(-anchorX, -anchorY);
132 
133     // Draw the label text with the transformed graphics context.
134     // It is placed on the bottom right side of the node.
135     if (label.getTextColor() != null && !"".equals(label.getText())) {
136       gfx.setFont(label.getFont());
137       gfx.setColor(label.getTextColor());
138       final Insets insets = label.getInsets() == null ? YLabel.defaultInsets : label.getInsets();
139       final float descent = new TextLayout(label.getText(), label.getFont(), gfx.getFontRenderContext()).getDescent();
140       gfx.drawString(label.getText(), (float) (anchorX + isometryData.getWidth() - label.getContentWidth() - insets.right), (float) anchorY - insets.bottom - descent);
141     }
142 
143     // Restore the original graphics context.
144     gfx.setTransform(oldTransform);
145     gfx.setFont(oldFont);
146     gfx.setColor(oldColor);
147   }
148 }
149