f@0: /* f@0: CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool f@0: f@0: Copyright (C) 2002 Cay S. Horstmann (http://horstmann.com) f@0: Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) f@0: f@0: This program is free software: you can redistribute it and/or modify f@0: it under the terms of the GNU General Public License as published by f@0: the Free Software Foundation, either version 3 of the License, or f@0: (at your option) any later version. f@0: f@0: This program is distributed in the hope that it will be useful, f@0: but WITHOUT ANY WARRANTY; without even the implied warranty of f@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the f@0: GNU General Public License for more details. f@0: f@0: You should have received a copy of the GNU General Public License f@0: along with this program. If not, see . f@0: */ f@0: f@0: package uk.ac.qmul.eecs.ccmi.gui; f@0: f@0: import java.awt.Color; f@0: import java.awt.Graphics2D; f@0: import java.awt.Stroke; f@0: import java.awt.geom.Line2D; f@0: import java.awt.geom.Point2D; f@0: import java.awt.geom.Rectangle2D; f@0: import java.awt.geom.RectangularShape; f@0: f@0: /** f@0: A grid to which nodes can be "snapped". The f@0: snapping operation moves a point to the nearest grid point. f@0: */ f@0: public class Grid f@0: { f@0: /** f@0: Constructs a grid with no grid points. f@0: */ f@0: public Grid() f@0: { f@0: setGrid(0, 0); f@0: } f@0: f@0: /** f@0: Sets the grid point distances in x- and y-direction f@0: @param x the grid point distance in x-direction f@0: @param y the grid point distance in y-direction f@0: */ f@0: public void setGrid(double x, double y) f@0: { f@0: gridx = x; f@0: gridy = y; f@0: } f@0: f@0: /** f@0: Draws this grid inside a rectangle. f@0: @param g2 the graphics context f@0: @param bounds the bounding rectangle f@0: */ f@0: public void draw(Graphics2D g2, Rectangle2D bounds) f@0: { f@0: Color PALE_BLUE = new Color(0.9F, 0.8F, 0.9F); f@0: Color oldColor = g2.getColor(); f@0: g2.setColor(PALE_BLUE); f@0: Stroke oldStroke = g2.getStroke(); f@0: for (double x = bounds.getX(); x < bounds.getMaxX(); x += gridx) f@0: g2.draw(new Line2D.Double(x, bounds.getY(), x, bounds.getMaxY())); f@0: for (double y = bounds.getY(); y < bounds.getMaxY(); y += gridy) f@0: g2.draw(new Line2D.Double(bounds.getX(), y, bounds.getMaxX(), y)); f@0: g2.setStroke(oldStroke); f@0: g2.setColor(oldColor); f@0: } f@0: f@0: /** f@0: Snaps a point to the nearest grid point f@0: @param p the point to snap. After the call, the f@0: coordinates of p are changed so that p falls on the grid. f@0: */ f@0: public void snap(Point2D p) f@0: { f@0: double x; f@0: if (gridx == 0) f@0: x = p.getX(); f@0: else f@0: x = Math.round(p.getX() / gridx) * gridx; f@0: double y; f@0: if (gridy == 0) f@0: y = p.getY(); f@0: else f@0: y = Math.round(p.getY() / gridy) * gridy; f@0: f@0: p.setLocation(x, y); f@0: } f@0: f@0: /** f@0: Snaps a rectangle to the nearest grid points f@0: @param r the rectangle to snap. After the call, the f@0: coordinates of r are changed so that all of its corners f@0: falls on the grid. f@0: */ f@0: public void snap(RectangularShape r) f@0: { f@0: double x; f@0: double w; f@0: w = r.getWidth(); f@0: if (gridx == 0) f@0: { f@0: x = r.getX(); f@0: } f@0: else f@0: { f@0: x = Math.round(r.getX() / gridx) * gridx; f@0: // w = Math.ceil(r.getWidth() / (2 * gridx)) * (2 * gridx); f@0: } f@0: double y; f@0: double h; f@0: h = r.getHeight(); f@0: if (gridy == 0) f@0: { f@0: y = r.getY(); f@0: } f@0: else f@0: { f@0: y = Math.round(r.getY() / gridy) * gridy; f@0: // h = Math.ceil(r.getHeight() / (2 * gridy)) * (2 * gridy); f@0: } f@0: f@0: r.setFrame(x, y, w, h); f@0: } f@0: f@0: private double gridx; f@0: private double gridy; f@0: }