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