]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/utils/GridUtil.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / utils / GridUtil.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.g2d.utils;\r
13 \r
14 import java.awt.BasicStroke;\r
15 import java.awt.Font;\r
16 import java.awt.FontMetrics;\r
17 import java.awt.Graphics2D;\r
18 import java.awt.font.FontRenderContext;\r
19 import java.awt.font.GlyphVector;\r
20 import java.awt.font.LineMetrics;\r
21 import java.awt.geom.Line2D;\r
22 import java.text.Format;\r
23 \r
24 import org.simantics.scenegraph.utils.GridUtils;\r
25 \r
26 public class GridUtil {\r
27 \r
28     public static final BasicStroke GRID_LINE_STROKE;\r
29     public static final BasicStroke RULER_LINE_STROKE;\r
30     public static final Font RULER_FONT;    \r
31     public static final Font RULER_FONT_BOLD;    \r
32         public static final FontRenderContext frc = new FontRenderContext(null, true, true);                            \r
33 \r
34     static {\r
35         RULER_LINE_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE, 10.0f, null, 0.0f);\r
36         GRID_LINE_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE, 10.0f, null, 0.0f);\r
37         RULER_FONT = new Font("Tahoma", Font.PLAIN, 12);\r
38         RULER_FONT_BOLD = new Font("Tahoma", Font.BOLD, 12);\r
39     }\r
40     \r
41     public GridUtil() {\r
42     }\r
43         \r
44     public static void paintGridLines(\r
45                 GridSpacing xgrid, GridSpacing ygrid, \r
46                 Graphics2D g, \r
47                 double xMin, double yMax, \r
48                 double controlWidth, \r
49                 double controlHeightForVerticalLines,\r
50                 double controlHeightForHorizLines) {\r
51         \r
52         g.setStroke(GRID_LINE_STROKE);\r
53         Line2D line = new Line2D.Double();\r
54         \r
55         if (xgrid != null) {\r
56                 // Vertical lines\r
57                 double controlX = GridUtils.distanceToNextGridCoordScaled(xMin, xgrid.segment, xgrid.pixelsPerUnit);\r
58         \r
59                 while (controlX <= controlWidth+0.1) {\r
60                         line.setLine(controlX, 0, controlX, (int) (controlHeightForVerticalLines - 1));\r
61                         g.draw(line);\r
62                     controlX += xgrid.pixelsPerSegment;\r
63                 }\r
64         }\r
65 \r
66         // Horizontal lines\r
67         if (ygrid != null) {\r
68                 double canvasDiff = GridUtils.distanceToNextGridCoord(yMax, ygrid.segment);\r
69                 double controlY = controlHeightForHorizLines - canvasDiff * ygrid.pixelsPerUnit;\r
70                 \r
71                 while (controlY >= -0.1) {\r
72                         line.setLine(0, controlY, (int) (controlWidth - 1), controlY);\r
73                         g.draw(line);           \r
74                     controlY -= ygrid.pixelsPerSegment;\r
75                 }\r
76         }\r
77     }\r
78     \r
79     public static void paintHorizontalRuler(\r
80                 GridSpacing grid, \r
81                 Graphics2D g, \r
82                 double xMin, \r
83                 double controlWidth,  \r
84                 Format labelFormat) {           \r
85         g.setStroke(RULER_LINE_STROKE);\r
86         \r
87         // Draw ticks\r
88         double canvasDiff = GridUtils.distanceToNextGridCoord(xMin, grid.segment);\r
89         double canvasX = xMin + canvasDiff;\r
90         double controlX = canvasDiff * grid.pixelsPerUnit;\r
91         Line2D line = new Line2D.Double();\r
92         line.setLine(0, 3, controlWidth, 3);\r
93         g.draw(line);\r
94                \r
95         while (controlX <= controlWidth + 0.1) {\r
96                 line.setLine(controlX, 3, controlX, 8);\r
97                 g.draw(line);\r
98             controlX += grid.pixelsPerSegment;\r
99         }\r
100 \r
101         // Labels\r
102         Font font = RULER_FONT;\r
103         g.setFont(RULER_FONT);\r
104         FontMetrics fm = g.getFontMetrics(font);\r
105 \r
106         canvasDiff = GridUtils.distanceToNextGridCoord(xMin, grid.segment);\r
107         double canvasStart = canvasX = xMin + canvasDiff;\r
108         controlX = canvasDiff * grid.pixelsPerUnit;\r
109                 \r
110         int i = 0;\r
111         while (controlX <= controlWidth + 0.1) {\r
112                 String value = labelFormat.format( canvasX );\r
113                 double labelCenter = fm.getStringBounds(value, g).getCenterX();\r
114                 g.drawString(value, (float) (controlX-labelCenter), (float) 20);\r
115             controlX += grid.pixelsPerSegment;\r
116             canvasX = canvasStart + grid.segment * (++i);\r
117         }\r
118         \r
119     }\r
120     \r
121     public static void paintVerticalRuler(\r
122                 GridSpacing grid, \r
123                 Graphics2D g, \r
124                 double yMin, \r
125                 double controlHeight, \r
126                 Format labelFormat) {\r
127         \r
128         g.setStroke(RULER_LINE_STROKE);\r
129         \r
130         // Draw ticks\r
131         double canvasDiff = GridUtils.distanceToNextGridCoord(yMin+grid.segment, grid.segment);\r
132         double controlY = controlHeight - canvasDiff * grid.pixelsPerUnit;\r
133         Line2D line = new Line2D.Double();\r
134         line.setLine(3, 0, 3, controlHeight);\r
135         g.draw(line);\r
136         \r
137         while (controlY >= -0.1) {\r
138                 line.setLine(3, controlY, 8, controlY);\r
139                 g.draw( line );\r
140             controlY -= grid.pixelsPerSegment;\r
141         }\r
142         \r
143         // Labels\r
144         g.setFont(RULER_FONT);\r
145         FontMetrics fm = g.getFontMetrics(RULER_FONT);\r
146         canvasDiff = GridUtils.distanceToNextGridCoord(yMin, grid.segment);\r
147         double canvasY = yMin + canvasDiff;\r
148         double canvasStart = canvasY;\r
149         controlY = controlHeight - canvasDiff * grid.pixelsPerUnit;\r
150         int i=0;\r
151         while (controlY >= -0.1) {\r
152                 String value = labelFormat.format( canvasY );\r
153                 LineMetrics lm = fm.getLineMetrics(value, g);\r
154      \r
155                 g.drawString(value, (float) 13, (float) (controlY+lm.getAscent()/2)-1);\r
156             controlY -= grid.pixelsPerSegment;\r
157             canvasY = canvasStart + grid.segment * (++i);\r
158         }\r
159     }\r
160 \r
161     public static void paintVerticalSlaveRuler(\r
162                 GridSpacing masterGrid, \r
163                 GridSpacing slaveGrid, \r
164                 Graphics2D g, \r
165                 double yMinMaster, double yMinSlave, \r
166                 double controlHeight, \r
167                 Format labelFormat) {\r
168         \r
169         g.setStroke(RULER_LINE_STROKE);\r
170         \r
171         // Draw ticks\r
172         double canvasDiff = GridUtils.distanceToNextGridCoord(yMinMaster+masterGrid.segment, masterGrid.segment);\r
173         double controlDiff = canvasDiff * masterGrid.pixelsPerUnit;\r
174         double startY = controlHeight - controlDiff;\r
175         double controlY = startY;\r
176         Line2D line = new Line2D.Double();\r
177         line.setLine(3, 0, 3, controlHeight);\r
178         g.draw(line);\r
179         \r
180         while (controlY >= -0.1) {\r
181                 line.setLine(3, controlY, 8, controlY);\r
182                 g.draw( line );\r
183             controlY -= masterGrid.pixelsPerSegment;\r
184         }\r
185         \r
186         // Labels\r
187         g.setFont(RULER_FONT);\r
188         FontMetrics fm = g.getFontMetrics(RULER_FONT);\r
189         canvasDiff = GridUtils.distanceToNextGridCoord(yMinMaster, masterGrid.segment);\r
190         double masterY = yMinMaster + canvasDiff;\r
191         double canvasStart = masterY;\r
192         controlY = controlHeight - canvasDiff * masterGrid.pixelsPerUnit;\r
193 //        double slaveGridSegment = masterGrid.pixelsPerSegment * slaveGrid.unitsPerPixel;\r
194         int i=0;\r
195         while (controlY >= -0.1) {\r
196 //            System.out.println("controlY="+controlY+", canvasY="+masterY);\r
197             // Convert value from master coordinates to slave            \r
198             double slaveY = (masterY - yMinMaster) * masterGrid.pixelsPerUnit * slaveGrid.unitsPerPixel + yMinSlave;\r
199             if (Math.abs(slaveY) < 1e-5) slaveY=0.0;\r
200                 String value = labelFormat.format( slaveY );\r
201                 LineMetrics lm = fm.getLineMetrics(value, g);\r
202      \r
203                 g.drawString(value, (float) 13, (float) (controlY+lm.getAscent()/2)-1);\r
204             controlY -= masterGrid.pixelsPerSegment;\r
205             masterY = canvasStart + masterGrid.segment * (++i);\r
206         }\r
207     }\r
208     \r
209     public static int getTickCount(GridSpacing grid, double yMin, double controlHeight)\r
210     {\r
211         double canvasDiff = GridUtils.distanceToNextGridCoord(yMin+grid.segment, grid.segment);\r
212         double startY = controlHeight - canvasDiff * grid.pixelsPerUnit;\r
213         double x = startY / grid.pixelsPerSegment;\r
214         return (int) Math.ceil( x );\r
215     }\r
216     \r
217     \r
218     /**\r
219      * Estimate label width, by sampling values from xMin to xMax\r
220      * using given font and format.\r
221      * \r
222      * @param xMin\r
223      * @param xMax\r
224      * @param format\r
225      * @return\r
226      */\r
227     public static double calcLabelWidth(double xMin, double xMax, Format format, GridSpacing grid)\r
228     { \r
229         double width = 0.0;     \r
230         double canvasDiff = GridUtils.distanceToNextGridCoord(xMin, grid.segment);\r
231         int c = 0;\r
232         for (double x=xMin + canvasDiff; x<xMax; x+=grid.segment) {\r
233                 boolean nearZero = (x < 0.000000000001) && (x > -0.000000000001);\r
234                 if (nearZero) x = 0.0;\r
235                 String label = format.format(x);\r
236                 if (label==null || label.equals("")) continue;\r
237                 GlyphVector glyphVector;\r
238                         glyphVector = RULER_FONT.createGlyphVector(frc, label);\r
239             double labelWidth = glyphVector.getVisualBounds().getWidth();\r
240             width = Math.max( width, labelWidth );\r
241             if (c++ > 100) break;            \r
242         }\r
243         return width * 1.05;\r
244     }\r
245     \r
246         \r
247 }\r