--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.g2d.utils;\r
+\r
+import java.awt.BasicStroke;\r
+import java.awt.Font;\r
+import java.awt.FontMetrics;\r
+import java.awt.Graphics2D;\r
+import java.awt.font.FontRenderContext;\r
+import java.awt.font.GlyphVector;\r
+import java.awt.font.LineMetrics;\r
+import java.awt.geom.Line2D;\r
+import java.text.Format;\r
+\r
+import org.simantics.scenegraph.utils.GridUtils;\r
+\r
+public class GridUtil {\r
+\r
+ public static final BasicStroke GRID_LINE_STROKE;\r
+ public static final BasicStroke RULER_LINE_STROKE;\r
+ public static final Font RULER_FONT; \r
+ public static final Font RULER_FONT_BOLD; \r
+ public static final FontRenderContext frc = new FontRenderContext(null, true, true); \r
+\r
+ static {\r
+ RULER_LINE_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE, 10.0f, null, 0.0f);\r
+ GRID_LINE_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE, 10.0f, null, 0.0f);\r
+ RULER_FONT = new Font("Tahoma", Font.PLAIN, 12);\r
+ RULER_FONT_BOLD = new Font("Tahoma", Font.BOLD, 12);\r
+ }\r
+ \r
+ public GridUtil() {\r
+ }\r
+ \r
+ public static void paintGridLines(\r
+ GridSpacing xgrid, GridSpacing ygrid, \r
+ Graphics2D g, \r
+ double xMin, double yMax, \r
+ double controlWidth, \r
+ double controlHeightForVerticalLines,\r
+ double controlHeightForHorizLines) {\r
+ \r
+ g.setStroke(GRID_LINE_STROKE);\r
+ Line2D line = new Line2D.Double();\r
+ \r
+ if (xgrid != null) {\r
+ // Vertical lines\r
+ double controlX = GridUtils.distanceToNextGridCoordScaled(xMin, xgrid.segment, xgrid.pixelsPerUnit);\r
+ \r
+ while (controlX <= controlWidth+0.1) {\r
+ line.setLine(controlX, 0, controlX, (int) (controlHeightForVerticalLines - 1));\r
+ g.draw(line);\r
+ controlX += xgrid.pixelsPerSegment;\r
+ }\r
+ }\r
+\r
+ // Horizontal lines\r
+ if (ygrid != null) {\r
+ double canvasDiff = GridUtils.distanceToNextGridCoord(yMax, ygrid.segment);\r
+ double controlY = controlHeightForHorizLines - canvasDiff * ygrid.pixelsPerUnit;\r
+ \r
+ while (controlY >= -0.1) {\r
+ line.setLine(0, controlY, (int) (controlWidth - 1), controlY);\r
+ g.draw(line); \r
+ controlY -= ygrid.pixelsPerSegment;\r
+ }\r
+ }\r
+ }\r
+ \r
+ public static void paintHorizontalRuler(\r
+ GridSpacing grid, \r
+ Graphics2D g, \r
+ double xMin, \r
+ double controlWidth, \r
+ Format labelFormat) { \r
+ g.setStroke(RULER_LINE_STROKE);\r
+ \r
+ // Draw ticks\r
+ double canvasDiff = GridUtils.distanceToNextGridCoord(xMin, grid.segment);\r
+ double canvasX = xMin + canvasDiff;\r
+ double controlX = canvasDiff * grid.pixelsPerUnit;\r
+ Line2D line = new Line2D.Double();\r
+ line.setLine(0, 3, controlWidth, 3);\r
+ g.draw(line);\r
+ \r
+ while (controlX <= controlWidth + 0.1) {\r
+ line.setLine(controlX, 3, controlX, 8);\r
+ g.draw(line);\r
+ controlX += grid.pixelsPerSegment;\r
+ }\r
+\r
+ // Labels\r
+ Font font = RULER_FONT;\r
+ g.setFont(RULER_FONT);\r
+ FontMetrics fm = g.getFontMetrics(font);\r
+\r
+ canvasDiff = GridUtils.distanceToNextGridCoord(xMin, grid.segment);\r
+ double canvasStart = canvasX = xMin + canvasDiff;\r
+ controlX = canvasDiff * grid.pixelsPerUnit;\r
+ \r
+ int i = 0;\r
+ while (controlX <= controlWidth + 0.1) {\r
+ String value = labelFormat.format( canvasX );\r
+ double labelCenter = fm.getStringBounds(value, g).getCenterX();\r
+ g.drawString(value, (float) (controlX-labelCenter), (float) 20);\r
+ controlX += grid.pixelsPerSegment;\r
+ canvasX = canvasStart + grid.segment * (++i);\r
+ }\r
+ \r
+ }\r
+ \r
+ public static void paintVerticalRuler(\r
+ GridSpacing grid, \r
+ Graphics2D g, \r
+ double yMin, \r
+ double controlHeight, \r
+ Format labelFormat) {\r
+ \r
+ g.setStroke(RULER_LINE_STROKE);\r
+ \r
+ // Draw ticks\r
+ double canvasDiff = GridUtils.distanceToNextGridCoord(yMin+grid.segment, grid.segment);\r
+ double controlY = controlHeight - canvasDiff * grid.pixelsPerUnit;\r
+ Line2D line = new Line2D.Double();\r
+ line.setLine(3, 0, 3, controlHeight);\r
+ g.draw(line);\r
+ \r
+ while (controlY >= -0.1) {\r
+ line.setLine(3, controlY, 8, controlY);\r
+ g.draw( line );\r
+ controlY -= grid.pixelsPerSegment;\r
+ }\r
+ \r
+ // Labels\r
+ g.setFont(RULER_FONT);\r
+ FontMetrics fm = g.getFontMetrics(RULER_FONT);\r
+ canvasDiff = GridUtils.distanceToNextGridCoord(yMin, grid.segment);\r
+ double canvasY = yMin + canvasDiff;\r
+ double canvasStart = canvasY;\r
+ controlY = controlHeight - canvasDiff * grid.pixelsPerUnit;\r
+ int i=0;\r
+ while (controlY >= -0.1) {\r
+ String value = labelFormat.format( canvasY );\r
+ LineMetrics lm = fm.getLineMetrics(value, g);\r
+ \r
+ g.drawString(value, (float) 13, (float) (controlY+lm.getAscent()/2)-1);\r
+ controlY -= grid.pixelsPerSegment;\r
+ canvasY = canvasStart + grid.segment * (++i);\r
+ }\r
+ }\r
+\r
+ public static void paintVerticalSlaveRuler(\r
+ GridSpacing masterGrid, \r
+ GridSpacing slaveGrid, \r
+ Graphics2D g, \r
+ double yMinMaster, double yMinSlave, \r
+ double controlHeight, \r
+ Format labelFormat) {\r
+ \r
+ g.setStroke(RULER_LINE_STROKE);\r
+ \r
+ // Draw ticks\r
+ double canvasDiff = GridUtils.distanceToNextGridCoord(yMinMaster+masterGrid.segment, masterGrid.segment);\r
+ double controlDiff = canvasDiff * masterGrid.pixelsPerUnit;\r
+ double startY = controlHeight - controlDiff;\r
+ double controlY = startY;\r
+ Line2D line = new Line2D.Double();\r
+ line.setLine(3, 0, 3, controlHeight);\r
+ g.draw(line);\r
+ \r
+ while (controlY >= -0.1) {\r
+ line.setLine(3, controlY, 8, controlY);\r
+ g.draw( line );\r
+ controlY -= masterGrid.pixelsPerSegment;\r
+ }\r
+ \r
+ // Labels\r
+ g.setFont(RULER_FONT);\r
+ FontMetrics fm = g.getFontMetrics(RULER_FONT);\r
+ canvasDiff = GridUtils.distanceToNextGridCoord(yMinMaster, masterGrid.segment);\r
+ double masterY = yMinMaster + canvasDiff;\r
+ double canvasStart = masterY;\r
+ controlY = controlHeight - canvasDiff * masterGrid.pixelsPerUnit;\r
+// double slaveGridSegment = masterGrid.pixelsPerSegment * slaveGrid.unitsPerPixel;\r
+ int i=0;\r
+ while (controlY >= -0.1) {\r
+// System.out.println("controlY="+controlY+", canvasY="+masterY);\r
+ // Convert value from master coordinates to slave \r
+ double slaveY = (masterY - yMinMaster) * masterGrid.pixelsPerUnit * slaveGrid.unitsPerPixel + yMinSlave;\r
+ if (Math.abs(slaveY) < 1e-5) slaveY=0.0;\r
+ String value = labelFormat.format( slaveY );\r
+ LineMetrics lm = fm.getLineMetrics(value, g);\r
+ \r
+ g.drawString(value, (float) 13, (float) (controlY+lm.getAscent()/2)-1);\r
+ controlY -= masterGrid.pixelsPerSegment;\r
+ masterY = canvasStart + masterGrid.segment * (++i);\r
+ }\r
+ }\r
+ \r
+ public static int getTickCount(GridSpacing grid, double yMin, double controlHeight)\r
+ {\r
+ double canvasDiff = GridUtils.distanceToNextGridCoord(yMin+grid.segment, grid.segment);\r
+ double startY = controlHeight - canvasDiff * grid.pixelsPerUnit;\r
+ double x = startY / grid.pixelsPerSegment;\r
+ return (int) Math.ceil( x );\r
+ }\r
+ \r
+ \r
+ /**\r
+ * Estimate label width, by sampling values from xMin to xMax\r
+ * using given font and format.\r
+ * \r
+ * @param xMin\r
+ * @param xMax\r
+ * @param format\r
+ * @return\r
+ */\r
+ public static double calcLabelWidth(double xMin, double xMax, Format format, GridSpacing grid)\r
+ { \r
+ double width = 0.0; \r
+ double canvasDiff = GridUtils.distanceToNextGridCoord(xMin, grid.segment);\r
+ int c = 0;\r
+ for (double x=xMin + canvasDiff; x<xMax; x+=grid.segment) {\r
+ boolean nearZero = (x < 0.000000000001) && (x > -0.000000000001);\r
+ if (nearZero) x = 0.0;\r
+ String label = format.format(x);\r
+ if (label==null || label.equals("")) continue;\r
+ GlyphVector glyphVector;\r
+ glyphVector = RULER_FONT.createGlyphVector(frc, label);\r
+ double labelWidth = glyphVector.getVisualBounds().getWidth();\r
+ width = Math.max( width, labelWidth );\r
+ if (c++ > 100) break; \r
+ }\r
+ return width * 1.05;\r
+ }\r
+ \r
+ \r
+}\r