/*
Violet - A program for editing UML diagrams.
Copyright (C) 2007 Cay S. Horstmann (http://horstmann.com)
Alexandre de Pellegrin (http://alexdp.free.fr);
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.horstmann.violet.workspace.sidebar;
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.Area;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputAdapter;
import javax.swing.event.MouseInputListener;
public class ScrollPaneNavigatorPanel extends JPanel
{
private static final double MAX_SIZE = 200;
private JScrollPane theScrollPane;
private JComponent theComponent;
private BufferedImage theImage;
private Rectangle theStartRectangle;
private Rectangle theRectangle;
private Point theStartPoint;
private double theScale;
public ScrollPaneNavigatorPanel(JScrollPane aScrollPane)
{
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
theScrollPane = aScrollPane;
theComponent = (JComponent) theScrollPane.getViewport().getView();
theImage = null;
theStartRectangle = null;
theRectangle = null;
theStartPoint = null;
theScale = 0.0;
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
MouseInputListener mil = new MouseInputAdapter()
{
public void mousePressed(MouseEvent e)
{
theStartPoint = e.getPoint();
}
public void mouseReleased(MouseEvent e)
{
if (theStartPoint != null)
{
Point newPoint = e.getPoint();
int deltaX = (int) ((newPoint.x - theStartPoint.x) / theScale);
int deltaY = (int) ((newPoint.y - theStartPoint.y) / theScale);
scroll(deltaX, deltaY);
}
theStartPoint = null;
theStartRectangle = theRectangle;
}
public void mouseDragged(MouseEvent e)
{
if (theStartPoint == null) return;
Point newPoint = e.getPoint();
moveRectangle(newPoint.x - theStartPoint.x, newPoint.y - theStartPoint.y);
}
};
addMouseListener(mil);
addMouseMotionListener(mil);
// thePopupMenu = new JPopupMenu();
// thePopupMenu.setLayout(new BorderLayout());
// thePopupMenu.add(this, BorderLayout.CENTER);
// thePopupMenu.setBorder(BorderFactory.createLineBorder(Color.BLACK));
setLayout(new BorderLayout());
theScrollPane.addComponentListener(new ComponentAdapter()
{
public void componentResized(ComponentEvent arg0)
{
display();
}
});
}
protected void paintComponent(Graphics g1D)
{
if (theImage == null || theRectangle == null) return;
Graphics2D g = (Graphics2D) g1D;
Insets insets = getInsets();
int xOffset = insets.left;
int yOffset = insets.top;
int availableWidth = getWidth() - insets.left - insets.right;
int availableHeight = getHeight() - insets.top - insets.bottom;
g.drawImage(theImage, xOffset, yOffset, null);
Color tmpColor = g.getColor();
Area area = new Area(new Rectangle(xOffset, yOffset, availableWidth, availableHeight));
area.subtract(new Area(theRectangle));
g.setColor(new Color(255, 255, 255, 128));
g.fill(area);
g.setColor(Color.BLACK);
g.draw(theRectangle);
g.setColor(tmpColor);
}
public Dimension getPreferredSize()
{
if (theImage == null || theRectangle == null) return new Dimension();
Insets insets = getInsets();
return new Dimension(theImage.getWidth(null) + insets.left + insets.right, theImage.getHeight(null) + insets.top
+ insets.bottom);
}
private void display()
{
double compWidth = theComponent.getWidth();
double compHeight = theComponent.getHeight();
double scaleX = MAX_SIZE / compWidth;
double scaleY = MAX_SIZE / compHeight;
theScale = Math.min(scaleX, scaleY);
theImage = new BufferedImage((int) (theComponent.getWidth() * theScale), (int) (theComponent.getHeight() * theScale),
BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g = theImage.createGraphics();
g.scale(theScale, theScale);
theComponent.paint(g);
theStartRectangle = theComponent.getVisibleRect();
Insets insets = getInsets();
theStartRectangle.x = (int) (theScale * theStartRectangle.x + insets.left);
theStartRectangle.y = (int) (theScale * theStartRectangle.y + insets.right);
theStartRectangle.width *= theScale;
theStartRectangle.height *= theScale;
theRectangle = theStartRectangle;
// Dimension pref = thePopupMenu.getPreferredSize();
//
// thePopupMenu.show(theButton,
// (theButton.getWidth() - pref.width) / 2,
// (theButton.getHeight() - pref.height) / 2);
repaint();
try
{
Robot robot = new Robot();
Point centerPoint = new Point(theRectangle.x + theRectangle.width / 2, theRectangle.y + theRectangle.height / 2);
SwingUtilities.convertPointToScreen(centerPoint, this);
robot.mouseMove(centerPoint.x, centerPoint.y);
}
catch (AWTException e)
{
e.printStackTrace();
}
}
private void moveRectangle(int aDeltaX, int aDeltaY)
{
if (theStartRectangle == null) return;
Insets insets = getInsets();
Rectangle newRect = new Rectangle(theStartRectangle);
newRect.x += aDeltaX;
newRect.y += aDeltaY;
newRect.x = Math.min(Math.max(newRect.x, insets.left), getWidth() - insets.right - newRect.width);
newRect.y = Math.min(Math.max(newRect.y, insets.right), getHeight() - insets.bottom - newRect.height);
Rectangle clip = new Rectangle();
Rectangle.union(theRectangle, newRect, clip);
clip.grow(2, 2);
theRectangle = newRect;
paintImmediately(clip);
}
private void scroll(int aDeltaX, int aDeltaY)
{
JComponent component = (JComponent) theScrollPane.getViewport().getView();
Rectangle rect = component.getVisibleRect();
rect.x += aDeltaX;
rect.y += aDeltaY;
component.scrollRectToVisible(rect);
// thePopupMenu.setVisible(false);
}
// public static void main(String[] args) {
// EventQueue.invokeLater(new Runnable() {
// public void run() {
// try {
// JFrame frame = new JFrame(ScrollPaneBidule.class.getName());
// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// URL imageURL = new URL("http://www.aboutstonehenge.info/images/education/stonehenge-wallpaper-1.jpg");
// JLabel label = new JLabel(new ImageIcon(ImageIO.read(imageURL)));
// JScrollPane scrollPane = new JScrollPane(label);
// new ScrollPaneBidule(scrollPane);
// frame.setContentPane(scrollPane);
// frame.pack();
// frame.setVisible(true);
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// });
// }
}