1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
\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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.g2d.utils;
\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
24 import org.simantics.scenegraph.utils.GridUtils;
\r
26 public class GridUtil {
\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
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
44 public static void paintGridLines(
\r
45 GridSpacing xgrid, GridSpacing ygrid,
\r
47 double xMin, double yMax,
\r
48 double controlWidth,
\r
49 double controlHeightForVerticalLines,
\r
50 double controlHeightForHorizLines) {
\r
52 g.setStroke(GRID_LINE_STROKE);
\r
53 Line2D line = new Line2D.Double();
\r
55 if (xgrid != null) {
\r
57 double controlX = GridUtils.distanceToNextGridCoordScaled(xMin, xgrid.segment, xgrid.pixelsPerUnit);
\r
59 while (controlX <= controlWidth+0.1) {
\r
60 line.setLine(controlX, 0, controlX, (int) (controlHeightForVerticalLines - 1));
\r
62 controlX += xgrid.pixelsPerSegment;
\r
67 if (ygrid != null) {
\r
68 double canvasDiff = GridUtils.distanceToNextGridCoord(yMax, ygrid.segment);
\r
69 double controlY = controlHeightForHorizLines - canvasDiff * ygrid.pixelsPerUnit;
\r
71 while (controlY >= -0.1) {
\r
72 line.setLine(0, controlY, (int) (controlWidth - 1), controlY);
\r
74 controlY -= ygrid.pixelsPerSegment;
\r
79 public static void paintHorizontalRuler(
\r
83 double controlWidth,
\r
84 Format labelFormat) {
\r
85 g.setStroke(RULER_LINE_STROKE);
\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
95 while (controlX <= controlWidth + 0.1) {
\r
96 line.setLine(controlX, 3, controlX, 8);
\r
98 controlX += grid.pixelsPerSegment;
\r
102 Font font = RULER_FONT;
\r
103 g.setFont(RULER_FONT);
\r
104 FontMetrics fm = g.getFontMetrics(font);
\r
106 canvasDiff = GridUtils.distanceToNextGridCoord(xMin, grid.segment);
\r
107 double canvasStart = canvasX = xMin + canvasDiff;
\r
108 controlX = canvasDiff * grid.pixelsPerUnit;
\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
121 public static void paintVerticalRuler(
\r
125 double controlHeight,
\r
126 Format labelFormat) {
\r
128 g.setStroke(RULER_LINE_STROKE);
\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
137 while (controlY >= -0.1) {
\r
138 line.setLine(3, controlY, 8, controlY);
\r
140 controlY -= grid.pixelsPerSegment;
\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
151 while (controlY >= -0.1) {
\r
152 String value = labelFormat.format( canvasY );
\r
153 LineMetrics lm = fm.getLineMetrics(value, g);
\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
161 public static void paintVerticalSlaveRuler(
\r
162 GridSpacing masterGrid,
\r
163 GridSpacing slaveGrid,
\r
165 double yMinMaster, double yMinSlave,
\r
166 double controlHeight,
\r
167 Format labelFormat) {
\r
169 g.setStroke(RULER_LINE_STROKE);
\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
180 while (controlY >= -0.1) {
\r
181 line.setLine(3, controlY, 8, controlY);
\r
183 controlY -= masterGrid.pixelsPerSegment;
\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
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
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
209 public static int getTickCount(GridSpacing grid, double yMin, double controlHeight)
\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
219 * Estimate label width, by sampling values from xMin to xMax
\r
220 * using given font and format.
\r
227 public static double calcLabelWidth(double xMin, double xMax, Format format, GridSpacing grid)
\r
229 double width = 0.0;
\r
230 double canvasDiff = GridUtils.distanceToNextGridCoord(xMin, grid.segment);
\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
243 return width * 1.05;
\r