001: /*
002: * $Id: JGraphEditorRuler.java,v 1.1.1.1 2005/08/04 11:21:58 gaudenz Exp $
003: * Copyright (c) 2001-2005, Gaudenz Alder
004: *
005: * All rights reserved.
006: *
007: * See LICENSE file for license details. If you are unable to locate
008: * this file please contact info (at) jgraph (dot) com.
009: */
010: package com.jgraph.editor.factory;
011:
012: import java.awt.Color;
013: import java.awt.Dimension;
014: import java.awt.Font;
015: import java.awt.Graphics;
016: import java.awt.Point;
017: import java.awt.Rectangle;
018: import java.awt.event.MouseEvent;
019: import java.awt.event.MouseMotionListener;
020: import java.awt.geom.Point2D;
021: import java.beans.PropertyChangeEvent;
022: import java.beans.PropertyChangeListener;
023: import java.text.NumberFormat;
024:
025: import javax.swing.JComponent;
026:
027: import org.jgraph.JGraph;
028:
029: /**
030: * Component that displays a ruler for a JGraph component.
031: */
032: public class JGraphEditorRuler extends JComponent implements
033: MouseMotionListener, PropertyChangeListener {
034:
035: /**
036: * Defines the constants for horizontal and vertical orientation.
037: */
038: public static int ORIENTATION_HORIZONTAL = 0,
039: ORIENTATION_VERTICAL = 1;
040:
041: /**
042: * Internal constant used to describe the screen resolution (DPI). Default
043: * is 72.
044: */
045: protected static int INCH = 72;
046:
047: /**
048: * Holds the shared number formatter.
049: *
050: * @see NumberFormat#getInstance()
051: */
052: public static final NumberFormat numberFormat = NumberFormat
053: .getInstance();
054:
055: /**
056: * Configuers the number format.
057: */
058: static {
059: numberFormat.setMaximumFractionDigits(2);
060: }
061:
062: /**
063: * Defines the inactive background border. Default is a not-so-dark gray.
064: */
065: protected Color inactiveBackground = new Color(170, 170, 170);
066:
067: /**
068: * Specifies the orientation.
069: */
070: protected int orientation = ORIENTATION_HORIZONTAL;
071:
072: /**
073: * Specified that start and length of the active region, ie the region to
074: * paint with the background border. This is used for example to indicate
075: * the printable region of a graph.
076: */
077: protected int activeoffset, activelength;
078:
079: /**
080: * Specifies the scale for the metrics. Default is
081: * {@link JGraphEditorDiagramPane#DEFAULT_PAGESCALE}.
082: */
083: protected double scale = JGraphEditorDiagramPane.DEFAULT_PAGESCALE;
084:
085: /**
086: * Specifies the unit system. Default is
087: * {@link JGraphEditorDiagramPane#DEFAULT_ISMETRIC}.
088: */
089: protected boolean isMetric = JGraphEditorDiagramPane.DEFAULT_ISMETRIC;
090:
091: /**
092: * Specifies height or width of the ruler. Default is 15 pixels.
093: */
094: protected int rulerSize = 15;
095:
096: /**
097: * Reference to the attached graph.
098: */
099: protected JGraph graph;
100:
101: /**
102: * Holds the current and first mouse point.
103: */
104: protected Point drag, mouse = new Point();
105:
106: /**
107: * Parameters to control the display.
108: */
109: protected double increment, units;
110:
111: /**
112: * Constructs a new ruler for the specified graph and orientation.
113: *
114: * @param graph
115: * The graph to create the ruler for.
116: * @param orientation
117: * The orientation to use for the ruler.
118: */
119: public JGraphEditorRuler(JGraph graph, int orientation) {
120: this .orientation = orientation;
121: this .graph = graph;
122: updateIncrementAndUnits();
123: graph.addMouseMotionListener(this );
124: graph.addPropertyChangeListener(this );
125: }
126:
127: /**
128: * Sets the start of the active region in pixels.
129: *
130: * @param offset
131: * The start of the active region.
132: */
133: public void setActiveOffset(int offset) {
134: activeoffset = (int) (offset * scale);
135: }
136:
137: /**
138: * Sets the length of the active region in pixels.
139: *
140: * @param length
141: * The length of the active region.
142: */
143: public void setActiveLength(int length) {
144: activelength = (int) (length * scale);
145: }
146:
147: /**
148: * Returns true if the ruler uses metric units.
149: *
150: * @return Returns if the ruler is metric.
151: */
152: public boolean isMetric() {
153: return isMetric;
154: }
155:
156: /**
157: * Sets if the ruler uses metric units.
158: *
159: * @param isMetric
160: * Whether to use metric units.
161: */
162: public void setMetric(boolean isMetric) {
163: this .isMetric = isMetric;
164: updateIncrementAndUnits();
165: repaint();
166: }
167:
168: /**
169: * Returns the ruler's horizontal or vertical size.
170: *
171: * @return Returns the rulerSize.
172: */
173: public int getRulerSize() {
174: return rulerSize;
175: }
176:
177: /**
178: * Sets the ruler's horizontal or vertical size.
179: *
180: * @param rulerSize
181: * The rulerSize to set.
182: */
183: public void setRulerSize(int rulerSize) {
184: this .rulerSize = rulerSize;
185: }
186:
187: /**
188: * Returns the preferred size by replacing the respective component of the
189: * graph's preferred size with {@link #rulerSize}.
190: *
191: * @return Returns the preferred size for the ruler.
192: */
193: public Dimension getPreferredSize() {
194: Dimension dim = graph.getPreferredSize();
195: if (orientation == ORIENTATION_VERTICAL)
196: dim.width = rulerSize;
197: else
198: dim.height = rulerSize;
199: return dim;
200: }
201:
202: /*
203: * (non-Javadoc)
204: */
205: public void mouseMoved(MouseEvent e) {
206: if (drag != null) {
207: Point old = drag;
208: drag = null;
209: repaint(old.x, old.y);
210: }
211: Point old = mouse;
212: mouse = e.getPoint();
213: repaint(old.x, old.y);
214: repaint(mouse.x, mouse.y);
215: }
216:
217: /*
218: * (non-Javadoc)
219: */
220: public void mouseDragged(MouseEvent e) {
221: Point old = drag;
222: drag = e.getPoint();
223: if (old != null)
224: repaint(old.x, old.y);
225: repaint(drag.x, drag.y);
226: }
227:
228: /*
229: * (non-Javadoc)
230: */
231: public void propertyChange(PropertyChangeEvent event) {
232: String changeName = event.getPropertyName();
233: if (changeName.equals(JGraph.SCALE_PROPERTY))
234: repaint();
235: }
236:
237: /**
238: * Updates the local variables used for painting based on the current scale
239: * and unit system.
240: */
241: protected void updateIncrementAndUnits() {
242: if (isMetric) {
243: units = INCH / 2.54; // 2.54 dots per centimeter
244: units *= graph.getScale() * scale;
245: increment = units;
246: } else {
247: units = INCH;
248: units *= graph.getScale() * scale;
249: increment = units / 2;
250: }
251: }
252:
253: /**
254: * Repaints the ruler between the specified 0 and x or y depending on the
255: * orientation.
256: *
257: * @param x
258: * The endpoint for repainting a horizontal ruler.
259: * @param y
260: * The endpoint for repainting a vertical ruler.
261: */
262: public void repaint(int x, int y) {
263: if (orientation == ORIENTATION_VERTICAL)
264: repaint(0, y, rulerSize, 1);
265: else
266: repaint(x, 0, 1, rulerSize);
267: }
268:
269: /**
270: * Paints the ruler.
271: *
272: * @param g
273: * The graphics to paint the ruler to.
274: */
275: public void paintComponent(Graphics g) {
276: revalidate();
277: updateIncrementAndUnits();
278: Rectangle drawHere = g.getClipBounds();
279:
280: // Fills clipping area with background.
281: if (activelength > 0 && inactiveBackground != null)
282: g.setColor(inactiveBackground);
283: else
284: g.setColor(getBackground());
285: g.fillRect(drawHere.x, drawHere.y, drawHere.width,
286: drawHere.height);
287:
288: // Draws the active region.
289: Point2D p = graph.toScreen(new Point2D.Double(activeoffset,
290: activelength));
291: g.setColor(getBackground());
292: if (orientation == ORIENTATION_VERTICAL)
293: g.fillRect(drawHere.x, (int) p.getX(), drawHere.width,
294: (int) p.getY());
295: else
296: g.fillRect((int) p.getX(), drawHere.y, (int) p.getY(),
297: drawHere.height);
298:
299: // Do the ruler labels in a small font that'buttonSelect black.
300: g.setFont(new Font("SansSerif", Font.PLAIN, 8));
301: g.setColor(Color.black);
302:
303: // Some vars we need.
304: double end = 0;
305: double start = 0;
306: int tickLength = 0;
307: String text = null;
308:
309: // Uses clipping bounds to calculate first tick and last tick
310: // location.
311: if (orientation == ORIENTATION_VERTICAL) {
312: start = Math.floor(drawHere.y / increment) * increment;
313: end = Math.ceil((drawHere.y + drawHere.height) / increment)
314: * increment;
315: } else {
316: start = Math.floor(drawHere.x / increment) * increment;
317: end = Math.ceil((drawHere.x + drawHere.width) / increment)
318: * increment;
319: }
320:
321: // Makes a special case of 0 to display the number
322: // within the rule and draw a units label.
323: if (start == 0) {
324: text = Integer.toString(0) + (isMetric ? " cm" : " in");
325: tickLength = 10;
326: if (orientation == ORIENTATION_VERTICAL) {
327: g.drawLine(rulerSize - 1, 0,
328: rulerSize - tickLength - 1, 0);
329: g.drawString(text, 1, 11);
330: } else {
331: g.drawLine(0, rulerSize - 1, 0, rulerSize - tickLength
332: - 1);
333: g.drawString(text, 2, 11);
334: }
335: text = null;
336: start = increment;
337: }
338:
339: // Ticks and labels
340: for (double i = start; i < end; i += increment) {
341: if (units == 0)
342: units = 1;
343: tickLength = 10;
344: // VW make relative to scaling factor
345: text = numberFormat.format(i / units);
346: if (tickLength != 0) {
347: if (orientation == ORIENTATION_VERTICAL) {
348: g.drawLine(rulerSize - 1, (int) i, rulerSize
349: - tickLength - 1, (int) i);
350: if (text != null)
351: g.drawString(text, 0, (int) i + 9);
352: } else {
353: g.drawLine((int) i, rulerSize - 1, (int) i,
354: rulerSize - tickLength - 1);
355: if (text != null)
356: g.drawString(text, (int) i + 2, 11);
357: }
358: }
359: }
360:
361: // Draw Mouseposition
362: g.setColor(Color.green);
363: if (orientation == ORIENTATION_VERTICAL)
364: g.drawLine(rulerSize - 1, mouse.y, rulerSize - tickLength
365: - 1, mouse.y);
366: else
367: g.drawLine(mouse.x, rulerSize - 1, mouse.x, rulerSize
368: - tickLength - 1);
369: if (drag != null)
370: if (orientation == ORIENTATION_VERTICAL)
371: g.drawLine(rulerSize - 1, drag.y, rulerSize
372: - tickLength - 1, drag.y);
373: else
374: g.drawLine(drag.x, rulerSize - 1, drag.x, rulerSize
375: - tickLength - 1);
376: }
377:
378: }
|