package jas2.plot;
import jas2.util.ColorMenu;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.LineBorder;
import javax.swing.colorchooser.ColorSelectionModel;
import javax.swing.colorchooser.DefaultColorSelectionModel;
/**
* Base class for any object that can be moved around using handles
*/
public abstract class MovableObject extends PlotComponent implements HasPopupItems, JASPlotMouseListener
{
public MovableObject(String prefix)
{
this.prefix = prefix;
super.setBorder(border);
}
protected String getPrefix()
{
return prefix;
}
public void setMovableObjectBounds(int p1, int p2, int p3, int p4)
{
super.setBounds(p1, p2, p3, p4);
hasBeenMoved = true;
hasBeenResized = true;
}
public void setMovableObjectBounds(Rectangle r)
{
super.setBounds(r);
hasBeenMoved = true;
hasBeenResized = true;
}
public void setBorder(Border newBorder)
{
Border oldBorder = super.getBorder();
if (oldBorder instanceof CompoundBorder) oldBorder = ((CompoundBorder) oldBorder).getOutsideBorder();
super.setBorder(newBorder == null ? oldBorder : new CompoundBorder(oldBorder,newBorder));
}
public int getBorderType()
{
return getBorderType(getInsideBorder());
}
public Border getInsideBorder()
{
Border oldBorder = super.getBorder();
if (oldBorder instanceof CompoundBorder) return ((CompoundBorder) oldBorder).getInsideBorder();
if (oldBorder instanceof HandleBorder) return null;
return oldBorder;
}
public void modifyPopupMenu(JPopupMenu menu, Component source)
{
menu.add(new BorderMenu(prefix));
ColorSelectionModel cm = new DefaultColorSelectionModel()
{
public Color getSelectedColor()
{
if (!isPaintingBackground()) return null;
return getBackground();
}
public void setSelectedColor(Color c)
{
setBackground(c);
}
};
menu.add(new BackgroundColorMenu(prefix,cm));
}
final void showHandles()
{
handlesVisible = true;
paintBorder(getGraphics());
saveCursor = getCursor();
currentCursor = Cursor.DEFAULT_CURSOR;
}
final void hideHandles()
{
handlesVisible = false;
setCursor(saveCursor);
Component p = getParent(); // Parent can be null when window is closing
if (p != null) p.repaint(); // Since we may overlap our siblings
}
public final void mouseEventNotify(final MouseEvent me)
{
if (handlesVisible)
{
if (me.getID() == MouseEvent.MOUSE_ENTERED)
{
saveCursor = getCursor();
}
else if (me.getID() == MouseEvent.MOUSE_EXITED)
{
setCursor(saveCursor);
}
else if (me.getID() == MouseEvent.MOUSE_PRESSED)
{
// What happens when the mouse is pressed depends on where it is
// It either starts some sort of resize or a move
if (currentCursor == Cursor.MOVE_CURSOR)
{
dragOffset = me.getPoint();
}
else
{
}
}
else if (me.getID() == MouseEvent.MOUSE_RELEASED)
{
dragOffset = null;
}
}
}
final void mouseMotionEventNotify(final MouseEvent me)
{
if (!handlesVisible) return;
if (me.getID() == MouseEvent.MOUSE_DRAGGED)
{
if (currentCursor == Cursor.MOVE_CURSOR)
{
Point p = me.getPoint();
Point x = getLocation();
p.translate(x.x,x.y);
if (dragOffset != null) p.translate(-dragOffset.x,-dragOffset.y);
setLocation(p);
hasBeenMoved = true;
}
else
{
final Rectangle b = getBounds();
final Point p = me.getPoint();
if (currentCursor == Cursor.E_RESIZE_CURSOR)
{
b.width = p.x;
}
else if (currentCursor == Cursor.W_RESIZE_CURSOR)
{
b.width -= p.x;
b.x += p.x;
}
else if (currentCursor == Cursor.N_RESIZE_CURSOR)
{
b.height -= p.y;
b.y += p.y;
}
else if (currentCursor == Cursor.S_RESIZE_CURSOR)
{
b.height = p.y;
}
else if (currentCursor == Cursor.NE_RESIZE_CURSOR)
{
// code from N:
b.height -= p.y;
b.y += p.y;
// code from E:
b.width = p.x;
}
else if (currentCursor == Cursor.NW_RESIZE_CURSOR)
{
// code from N:
b.height -= p.y;
b.y += p.y;
// code from W:
b.width -= p.x;
b.x += p.x;
}
else if (currentCursor == Cursor.SE_RESIZE_CURSOR)
{
// code from S:
b.height = p.y;
// code from E:
b.width = p.x;
}
else if (currentCursor == Cursor.SW_RESIZE_CURSOR)
{
// code from S:
b.height = p.y;
// code from W:
b.width -= p.x;
b.x += p.x;
}
else return;
hasBeenResized = true;
setBounds(b);
validate();
}
}
else if (me.getID() == MouseEvent.MOUSE_MOVED)
{
currentCursor = border.getCursor(getBounds(),me.getPoint());
((Component) me.getSource()).setCursor(Cursor.getPredefinedCursor(currentCursor));
}
}
public boolean hasBeenResized() {
return hasBeenResized;
}
public boolean hasBeenMoved() {
return hasBeenMoved;
}
public void restoreDefaultLayout() {
hasBeenResized = false;
hasBeenMoved = false;
}
public boolean hasDefaultLayout() {
return ! hasBeenMoved() && ! hasBeenResized();
}
// Are these methods really needed?
public void resizeMovableObject(int w, int h) {
hasBeenResized = true;
this.setSize(w,h);
}
public void moveMovableObject(int x, int y) {
hasBeenMoved = true;
this.setLocation(x,y);
}
/**
* Clicking on a movable object will by default cause its handles to appear.
*/
private String prefix; // Prefix for popup menu items
private boolean hasBeenResized = false;
private boolean hasBeenMoved = false;
private int currentCursor;
private Point dragOffset;
private Cursor saveCursor;
private boolean handlesVisible;
private static final HandleBorder border = new HandleBorder(Color.blue);
final private static class HandleBorder extends AbstractBorder
{
private Color lineColor;
/**
* Creates a handle border with the specified color and a
* @param color the color for the border
*/
HandleBorder(Color color)
{
lineColor = color;
}
/**
* Paints the border for the specified component with the
* specified position and size.
* @param c the component for which this border is being painted
* @param g the paint graphics
* @param x the x position of the painted border
* @param y the y position of the painted border
* @param width the width of the painted border
* @param height the height of the painted border
*/
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
{
if (((MovableObject) c).handlesVisible && !PrintHelper.isPrinting())
{
Color oldColor = g.getColor();
int xx = x+thick2;
int yy = y+thick2;
int ww = width-thickness;
int hh = height-thickness;
Rectangle[] h = getHandles(xx,yy,ww,hh);
g.setColor(lineColor);
g.drawRect(xx, yy, ww,hh);
for (int i=0; i= thick2 - extra ||
p.y <= thick2 + extra && p.y >= thick2 - extra ||
p.x >= b.width - thick2 - extra && p.x <= b.width - thick2 + extra ||
p.y >= b.height - thick2 - extra && p.y <= b.height - thick2 + extra)
{
return Cursor.MOVE_CURSOR;
}
return Cursor.DEFAULT_CURSOR;
}
/**
* Returns the insets of the border.
* @param c the component for which this border insets value applies
*/
public Insets getBorderInsets(Component c)
{
return insets;
}
/**
* Returns the color of the border.
*/
public Color getLineColor()
{
return lineColor;
}
/**
* Returns whether or not the border is opaque.
*/
public boolean isBorderOpaque() { return false; }
private final static int thickness = 5;
private final static Insets insets = new Insets(thickness, thickness, thickness, thickness);
private final static int thick2 = thickness/2;
private static Handle[] handles;
static
{
handles = new Handle[8];
for (int i=0; i= 0) super.print(g);
}
catch (SecurityException x) {}
}
/**
* An array containing an expanded selection of colors.
*/
public final static Color[] bgcolors =
{
null, Color.pink,
Color.orange, Color.yellow,
Color.green, Color.cyan,
new Color(164, 207, 255), new Color(225, 170, 255),
new Color(255, 170, 210)
};
/**
* An array containing names of the expanded selection of colors.
*
* @see ColorMenu#EXTENDED_COLORS
*/
public final static String[] bgnames =
{
"default", "pink",
"light orange", "yellow",
"light green", "cyan",
"sky blue", "violet",
"light magenta"
};
private final class BackgroundColorMenu extends ColorMenu
{
BackgroundColorMenu(String prefix, ColorSelectionModel cm)
{
super(prefix+" Background",cm,bgcolors,bgnames);
}
}
private final class BorderMenu extends JMenu
{
BorderMenu(String prefix)
{
super(prefix+" Border");
addItem("None", NONE);
addItem("Bevel In", BEVEL_IN);
addItem("Bevel Out", BEVEL_OUT);
addItem("Ethched", ETCHED);
addItem("Shadow", SHADOW);
ColorSelectionModel cm = new DefaultColorSelectionModel()
{
public Color getSelectedColor()
{
Border oldBorder = MovableObject.this.getBorder();
if (oldBorder instanceof CompoundBorder)
{
oldBorder = ((CompoundBorder) oldBorder).getInsideBorder();
}
if (oldBorder instanceof LineBorder)
{
return ((LineBorder) oldBorder).getLineColor();
}
return null;
}
public void setSelectedColor(Color c)
{
MovableObject.this.setBorder(BorderFactory.createLineBorder(c));
}
};
this.add(new ColorMenu("Line",cm,false));
}
private void addItem(String name, final int btype)
{
JMenuItem i = new JRadioButtonMenuItem(name);
add(i);
i.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
setBorderType(btype);
}
});
i.setSelected(getBorderType() == btype);
}
}
}
Ads help maintain this website.