/* * Copyright (C) 2004 The Concord Consortium, Inc., * 10 Concord Crossing, Concord, MA 01742 * * Web Site: http://www.concord.org * Email: info@concord.org * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * END LICENSE */ package org.concord.swing.graph; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.util.EventListener; import java.util.EventObject; import java.util.Vector; import javax.swing.JComponent; public class OverlayDraw extends JComponent implements MouseListener, MouseMotionListener { public static final int MARK_RECT = 0; public static final int MARK_OVAL = 1; public static final int MARK_NO_ACTION = -1; public static final int MARK_CREATED = 0; public static final int MARK_CHANGED = 1; public static final int MARK_MOVED = 2; protected int createType = MARK_OVAL; protected Vector markList = new Vector(); protected Vector markListeners = new Vector(); protected Color markColor = Color.black; protected int markAction; protected Mark selectedMark; protected Rectangle selectedHandle; protected Point pressed; protected Component component; protected boolean creating = false; protected int handleWidth = 8; protected int handleHeight = 8; public OverlayDraw(Component component) { this.component = component; setEnabled(true); } public boolean isCreating() { return creating; } public void setCreating(boolean value) { creating = value; } public void setEnabled(boolean enabled) { Container container = component.getParent(); if (container instanceof Container) { if (enabled) { container.add(this, 0); setBounds(component.getBounds()); addMouseListener(this); addMouseMotionListener(this); } else { removeMouseListener(this); removeMouseMotionListener(this); component.setBounds(getBounds()); container.remove(this); } } } public boolean isEnabled() { Container parent = getParent(); if (parent == null) return false; Component [] components = parent.getComponents(); for (int i = 0; i < components.length; i++) if (components[i] == this) return true; return false; } public Color getColor() { return markColor; } public void setColor(Color color) { markColor = color; } public Mark findMark(Point point) { for (int i = 0; i < markList.size(); i++) { Mark mark = (Mark) markList.elementAt(i); if (mark.contains(point)) return mark; } return null; } public void setHandleSize(int w, int h) { handleWidth = w; handleHeight = h; } protected void paintComponent(Graphics g) { for (int i = 0; i < markList.size(); i++) { Mark mark = (Mark) markList.elementAt(i); mark.draw(g); } } public void mouseClicked(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { pressed = e.getPoint(); if (creating) { Mark mark = new Mark(createType, pressed); markList.addElement(mark); selectedMark = mark; creating = false; notifyMarkListeners(mark, MARK_CREATED); } else { selectedMark = findMark(pressed); if (selectedMark instanceof Mark) selectedHandle = selectedMark.findHandle(pressed); else selectedHandle = null; } if (getParent() != null) getParent().repaint(); } public void mouseReleased(MouseEvent e) { if ((selectedMark != null) && (markAction > MARK_NO_ACTION)) notifyMarkListeners(selectedMark, markAction); } public void mouseDragged(MouseEvent e) { int deltaWidth = e.getX() - pressed.x; int deltaHeight = e.getY() - pressed.y; markAction = MARK_NO_ACTION; if (selectedMark instanceof Mark) { if (selectedHandle instanceof Rectangle) { selectedMark.changeSize(deltaWidth, deltaHeight); markAction = MARK_CHANGED; } else { selectedMark.moveCenter(deltaWidth, deltaHeight); markAction = MARK_MOVED; } } pressed = e.getPoint(); if (getParent() != null) getParent().repaint(); } public void mouseMoved(MouseEvent e) { } public class Mark extends Rectangle { protected int type; protected boolean selected; protected Point center; protected int halfWidth = 25; protected int halfHeight = 25; protected Rectangle lowerRight = new Rectangle(0, 0, handleWidth, handleHeight); public Mark(int type, Point point) { this.type = type; center = new Point(point); setLocation(); } public void setLocation() { x = center.x - halfWidth; y = center.y - halfHeight; width = 2 * halfWidth; height = 2 * halfHeight; selected = true; lowerRight.setLocation((x + width) - handleWidth, (y + height) - handleHeight); } public void changeSize(int deltaWidth, int deltaHeight) { halfWidth += deltaWidth; halfHeight += deltaHeight; if (halfWidth < handleWidth) halfWidth = handleWidth; if (halfHeight < handleHeight) halfHeight = handleHeight; setLocation(); } public void moveCenter(int deltaWidth, int deltaHeight) { center.x += deltaWidth; center.y += deltaHeight; setLocation(); } public Rectangle findHandle(Point point) { if (lowerRight.contains(point)) return lowerRight; return null; } protected void draw(Graphics g) { Color saveColor = g.getColor(); g.setColor(markColor); switch (type) { case MARK_RECT: g.drawRect(x, y, width, height); break; case MARK_OVAL: g.drawOval(x, y, width, height); break; } if (selectedMark == this) { g.fillRect(lowerRight.x, lowerRight.y, handleWidth, handleHeight); } g.setColor(saveColor); } } public class MarkEvent extends EventObject { public MarkEvent(Object source) { super(source); } } public interface MarkListener extends EventListener { public void markCreated(MarkEvent e); public void markChanged(MarkEvent e); public void markMoved(MarkEvent e); } public void addMarkListener(MarkListener listener) { if (! markListeners.contains(listener)) markListeners.addElement(listener); } public void removeMarkListener(MarkListener listener) { if (markListeners.contains(listener)) markListeners.removeElement(listener); } public void notifyMarkListeners(Mark mark, int type) { for (int i = 0; i < markListeners.size(); i++) { MarkListener listener = (MarkListener) markListeners.elementAt(i); switch (type) { case MARK_CREATED: listener.markCreated(new MarkEvent(mark)); break; case MARK_CHANGED: listener.markChanged(new MarkEvent(mark)); break; case MARK_MOVED: listener.markMoved(new MarkEvent(mark)); break; } } } }