File "Resizing.java"
Full Path: /home/analogde/www/Ebook/Informatique/JAVA/Code/Resizing.java
File size: 6.16 KB
MIME-type: text/x-c++
Charset: utf-8
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
public class Resizing extends JPanel {
Rectangle[] rects;
public void setRect(Rectangle r, int x, int y) {
r.setLocation(x, y);
repaint();
}
public void resizeRect(Rectangle r, int[] changes) {
int x = r.x + changes[0];
int y = r.y + changes[1];
int w = r.width + changes[2] - changes[0];
int h = r.height + changes[3] - changes[1];
r.setFrame(x, y, w, h);
repaint();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
if(rects == null)
initRects();
g2.setPaint(Color.blue);
for(int j = 0; j < rects.length; j++)
g2.draw(rects[j]);
}
private void initRects() {
int w = getWidth();
int h = getHeight();
rects = new Rectangle[2];
rects[0] = new Rectangle(w/3, h/8, w/3, h*3/8);
rects[1] = new Rectangle(w/2, h*3/4, w/3, h/16);
}
public static void main(String[] args) {
Resizing resizing = new Resizing();
RectangleController controller =
new RectangleController(resizing, new Resizer());
resizing.addMouseListener(controller);
resizing.addMouseMotionListener(controller);
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(resizing);
f.setSize(500,400);
f.setLocation(200,200);
f.setVisible(true);
}
}
class RectangleController extends MouseInputAdapter {
Resizing resizeComponent;
Resizer resizer;
Rectangle selectedRect;
Point offset = new Point();
boolean resizing = false;
boolean dragging = false;
public RectangleController(Resizing rc, Resizer r) {
resizeComponent = rc;
resizer = r;
}
public void mousePressed(MouseEvent e) {
Point p = e.getPoint();
Rectangle[] rects = resizeComponent.rects;
// Are we selecting a rectangle side to resize?
for(int j = 0; j < rects.length; j++) {
if(resizer.isSideSelected(p, rects[j])) {
resizing = true;
selectedRect = resizer.rect;
break;
}
}
// or, are we selecting a rectangle to drag?
if(!resizing) {
for(int j = 0; j < rects.length; j++) {
if(rects[j].contains(p)) {
offset.x = p.x - rects[j].x;
offset.y = p.y - rects[j].y;
selectedRect = rects[j];
dragging = true;
break;
}
}
}
}
public void mouseReleased(MouseEvent e) {
resizing = false;
dragging = false;
resizer.reset();
}
public void mouseDragged(MouseEvent e) {
Point p = e.getPoint();
if(resizing) {
int[] deltas = resizer.getResizeData(p);
resizeComponent.resizeRect(selectedRect, deltas);
} else if(dragging) {
int x = p.x - offset.x;
int y = p.y - offset.y;
resizeComponent.setRect(selectedRect, x, y);
}
}
}
class Resizer {
Rectangle rect;
int selectedIndex = -1;
final int PROXIMITY = 3;
// PathIterator travels clockwise.
final int TOP = 0;
final int RIGHT = 1;
final int BOTTOM = 2;
final int LEFT = 3;
public boolean isSideSelected(Point p, Rectangle r) {
rect = r;
PathIterator pit = r.getPathIterator(null);
double[] coords = new double[6];
int side = 0;
Point2D.Double start = new Point2D.Double();
boolean haveLine = false;
while(!pit.isDone()) {
int type = pit.currentSegment(coords);
switch(type) {
case PathIterator.SEG_MOVETO:
start.x = coords[0];
start.y = coords[1];
break;
case PathIterator.SEG_LINETO:
haveLine = true;
break;
case PathIterator.SEG_CLOSE:
haveLine = false;
break;
default:
System.out.println("Unexpected type: " + type);
}
if(haveLine) {
if(isCloseToLine(p, start, coords[0], coords[1])) {
selectedIndex = side;
break;
}
start.x = coords[0];
start.y = coords[1];
side++;
}
pit.next();
}
return selectedIndex != -1;
}
private boolean isCloseToLine(Point p, Point2D.Double start,
double endX, double endY) {
boolean isClose = false;
boolean isAdjacent = false;
if(start.x == endX) {
isClose = Math.abs(p.x-start.x) <= PROXIMITY;
isAdjacent = (start.y < p.y && p.y < endY) ||
(endY < p.y && p.y < start.y);
}
else if(start.y == endY) {
isClose = Math.abs(p.y-start.y) <= PROXIMITY;
isAdjacent = (start.x < p.x && p.x < endX) ||
(endX < p.x && p.x < start.x);
}
return isClose & isAdjacent;
}
public int[] getResizeData(Point p) {
// [x, y, width, height]
int[] changes = new int[4];
switch(selectedIndex) {
case TOP:
changes[1] = p.y - rect.y;
break;
case LEFT:
changes[0] = p.x - rect.x;
break;
case BOTTOM:
changes[3] = p.y - (rect.y + rect.height);
break;
case RIGHT:
changes[2] = p.x - (rect.x + rect.width);
break;
}
return changes;
}
public void reset() {
rect = null;
selectedIndex = -1;
}
}