package com.jidesoft.swing;_x000D_
_x000D_
import javax.swing.*;_x000D_
import javax.swing.event.MouseInputAdapter;_x000D_
import javax.swing.event.MouseInputListener;_x000D_
import java.awt.*;_x000D_
import java.awt.event.MouseEvent;_x000D_
import java.awt.geom.Area;_x000D_
import java.awt.image.BufferedImage;_x000D_
_x000D_
/**_x000D_
 * Original code http://forums.java.net/jive/thread.jspa?forumID=73&threadID=14674 under "Do whatever you want with this_x000D_
 * code" license_x000D_
 */_x000D_
@SuppressWarnings("serial")_x000D_
public class ScrollPaneOverview extends JComponent {_x000D_
    _x000D_
    private static final int MAX_SIZE = 400;_x000D_
    private static final int MAX_SCALE = 20;_x000D_
_x000D_
    private Component _owner;_x000D_
    private JScrollPane _scrollPane;_x000D_
    private Component _viewComponent;_x000D_
_x000D_
    protected JPopupMenu _popupMenu;_x000D_
_x000D_
    private BufferedImage _image;_x000D_
    private Rectangle _startRectangle;_x000D_
    private Rectangle _rectangle;_x000D_
    private Point _startPoint;_x000D_
    private double _scale;_x000D_
    private int xOffset;_x000D_
    private int yOffset;_x000D_
_x000D_
    private Color _selectionBorder = Color.BLACK;_x000D_
_x000D_
    public ScrollPaneOverview(JScrollPane scrollPane, Component owner) {_x000D_
        _scrollPane = scrollPane;_x000D_
        _owner = owner;_x000D_
        _image = null;_x000D_
        _startRectangle = null;_x000D_
        _rectangle = null;_x000D_
        _startPoint = null;_x000D_
        _scale = 0.0;_x000D_
_x000D_
        setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));_x000D_
        setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));_x000D_
        MouseInputListener mil = new MouseInputAdapter() {_x000D_
            // A new approach suggested by thomas.bierhance@sdm.de_x000D_
_x000D_
            @Override_x000D_
            public void mousePressed(MouseEvent e) {_x000D_
                if (_startPoint != null) {_x000D_
                    Point newPoint = e.getPoint();_x000D_
                    int deltaX = (int) ((newPoint.x - _startPoint.x) / _scale);_x000D_
                    int deltaY = (int) ((newPoint.y - _startPoint.y) / _scale);_x000D_
                    scroll(deltaX, deltaY);_x000D_
                }_x000D_
                _startPoint = null;_x000D_
                _startRectangle = _rectangle;_x000D_
            }_x000D_
_x000D_
            @Override_x000D_
            public void mouseMoved(MouseEvent e) {_x000D_
                if (_startPoint == null) {_x000D_
                    _startPoint = new Point(_rectangle.x + _rectangle.width / 2, _rectangle.y + _rectangle.height / 2);_x000D_
                }_x000D_
                Point newPoint = e.getPoint();_x000D_
                moveRectangle(newPoint.x - _startPoint.x, newPoint.y - _startPoint.y);_x000D_
            }_x000D_
        };_x000D_
        addMouseListener(mil);_x000D_
        addMouseMotionListener(mil);_x000D_
        _popupMenu = new JPopupMenu();_x000D_
        _popupMenu.setLayout(new BorderLayout());_x000D_
        _popupMenu.add(this, BorderLayout.CENTER);_x000D_
    }_x000D_
_x000D_
    public void setSelectionBorderColor(Color selectionBorder) {_x000D_
        _selectionBorder = selectionBorder;_x000D_
    }_x000D_
_x000D_
    public Color getSelectionBorder() {_x000D_
        return _selectionBorder;_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    protected void paintComponent(Graphics g) {_x000D_
        if (_image == null || _rectangle == null)_x000D_
            return;_x000D_
        Graphics2D g2d = (Graphics2D) g;_x000D_
        Insets insets = getInsets();_x000D_
        int xOffset = insets.left;_x000D_
        int yOffset = insets.top;_x000D_
_x000D_
        g.setColor(_scrollPane.getViewport().getView().getBackground());_x000D_
        g.fillRect(0, 0, getWidth(), getHeight());_x000D_
        g.drawImage(_image, xOffset, yOffset, null);_x000D_
_x000D_
        int availableWidth = getWidth() - insets.left - insets.right;_x000D_
        int availableHeight = getHeight() - insets.top - insets.bottom;_x000D_
        Area area = new Area(new Rectangle(xOffset, yOffset, availableWidth, availableHeight));_x000D_
        area.subtract(new Area(_rectangle));_x000D_
        g.setColor(new Color(255, 255, 255, 128));_x000D_
        g2d.fill(area);_x000D_
_x000D_
        Color oldcolor = g.getColor();_x000D_
        g.setColor(_selectionBorder);_x000D_
        g.drawRect(_rectangle.x, _rectangle.y, _rectangle.width, _rectangle.height);_x000D_
_x000D_
        g.setColor(oldcolor);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public Dimension getPreferredSize() {_x000D_
        if (_image == null || _rectangle == null)_x000D_
            return new Dimension();_x000D_
        Insets insets = getInsets();_x000D_
        return new Dimension(_image.getWidth(null) + insets.left + insets.right, _image.getHeight(null) + insets.top + insets.bottom);_x000D_
    }_x000D_
_x000D_
    public void display() {_x000D_
        _viewComponent = _scrollPane.getViewport().getView();_x000D_
        if (_viewComponent == null) {_x000D_
            return;_x000D_
        }_x000D_
_x000D_
        int maxSize = Math.max(MAX_SIZE, Math.max(_scrollPane.getWidth(), _scrollPane.getHeight()) / 2);_x000D_
_x000D_
        int width = Math.min(_viewComponent.getWidth(), _scrollPane.getViewport().getWidth() * MAX_SCALE);_x000D_
        if (width <= 0) {_x000D_
            return;_x000D_
        }_x000D_
        int height = Math.min(_viewComponent.getHeight(), _scrollPane.getViewport().getHeight() * MAX_SCALE);_x000D_
        if (height <= 0) {_x000D_
            return;_x000D_
        }_x000D_
        double scaleX = (double) maxSize / width;_x000D_
        double scaleY = (double) maxSize / height;_x000D_
_x000D_
        _scale = Math.max(1.0 / MAX_SCALE, Math.min(scaleX, scaleY));_x000D_
_x000D_
        _image = new BufferedImage((int) (width * _scale), (int) (height * _scale), BufferedImage.TYPE_INT_RGB);_x000D_
        Graphics2D g = _image.createGraphics();_x000D_
_x000D_
        // If the view is larger than the max scale allows only the the top left most part will now be painted_x000D_
        // One solution would be paint only the part around the current position, but I can't get it to paint - Walter Laan._x000D_
        // note that without limiting the scale, the width/height will become zero (illegal for BufferedImage)_x000D_
        // See CornerScrollerVisualTest in the test folder_x000D_
        _x000D_
//        g.setColor(_viewComponent.getBackground());_x000D_
//        g.fillRect(0, 0, _viewComponent.getWidth(), _viewComponent.getHeight());_x000D_
//        Point viewPosition = _scrollPane.getViewport().getViewPosition();_x000D_
//        xOffset = Math.max(0, viewPosition.x - (width / 2)); _x000D_
//        yOffset = Math.max(0, viewPosition.y - (height / 2)); _x000D_
//        g.translate(-xOffset, -yOffset);_x000D_
//        g.setClip(0, 0, width, height);_x000D_
        _x000D_
        g.scale(_scale, _scale);_x000D_
        g.setClip(xOffset, yOffset, width, height);_x000D_
        /// {{{ Qian Qian 10/72007_x000D_
        boolean wasDoubleBuffered = _viewComponent.isDoubleBuffered();_x000D_
        try {_x000D_
            if (_viewComponent instanceof JComponent) {_x000D_
                ((JComponent) _viewComponent).setDoubleBuffered(false);_x000D_
            }_x000D_
            _viewComponent.paint(g);_x000D_
        }_x000D_
        finally {_x000D_
            if (_viewComponent instanceof JComponent) {_x000D_
                ((JComponent) _viewComponent).setDoubleBuffered(wasDoubleBuffered);_x000D_
            }_x000D_
            g.dispose();_x000D_
        }_x000D_
        /// QianQian 10/7/2007 }}}_x000D_
        _startRectangle = _scrollPane.getViewport().getViewRect();_x000D_
        Insets insets = getInsets();_x000D_
        _startRectangle.x = (int) (_scale * _startRectangle.x + insets.left);_x000D_
        _startRectangle.y = (int) (_scale * _startRectangle.y + insets.right);_x000D_
        _startRectangle.width *= _scale;_x000D_
        _startRectangle.height *= _scale;_x000D_
        _rectangle = _startRectangle;_x000D_
        Point centerPoint = new Point(_rectangle.x + _rectangle.width / 2, _rectangle.y + _rectangle.height / 2);_x000D_
        showPopup(-centerPoint.x, -centerPoint.y, _owner);_x000D_
    }_x000D_
_x000D_
    /**_x000D_
     * Show popup at designated location._x000D_
     * <p/>_x000D_
     * You could override this method to show the popup in different location._x000D_
     *_x000D_
     * @param x the x axis pixel_x000D_
     * @param y the y axis pixel_x000D_
     * @param owner the owner of the popup_x000D_
     */_x000D_
    protected void showPopup(int x, int y, Component owner) {_x000D_
        _popupMenu.show(owner, x, y);_x000D_
    }_x000D_
_x000D_
    private void moveRectangle(int aDeltaX, int aDeltaY) {_x000D_
        if (_startRectangle == null)_x000D_
            return;_x000D_
        Insets insets = getInsets();_x000D_
        Rectangle newRect = new Rectangle(_startRectangle);_x000D_
        newRect.x += aDeltaX;_x000D_
        newRect.y += aDeltaY;_x000D_
        newRect.x = Math.min(Math.max(newRect.x, insets.left), getWidth() - insets.right - newRect.width);_x000D_
        newRect.y = Math.min(Math.max(newRect.y, insets.right), getHeight() - insets.bottom - newRect.height);_x000D_
        Rectangle clip = new Rectangle();_x000D_
        Rectangle.union(_rectangle, newRect, clip);_x000D_
        clip.grow(2, 2);_x000D_
        _rectangle = newRect;_x000D_
        paintImmediately(clip);_x000D_
    }_x000D_
_x000D_
    private void scroll(int aDeltaX, int aDeltaY) {_x000D_
        JComponent component = (JComponent) _scrollPane.getViewport().getView();_x000D_
        Rectangle rect = component.getVisibleRect();_x000D_
        rect.x += xOffset + aDeltaX;_x000D_
        rect.y += yOffset + aDeltaY;_x000D_
        component.scrollRectToVisible(rect);_x000D_
        _popupMenu.setVisible(false);_x000D_
    }_x000D_
}_x000D_

//        g.fillRect(0, 0, _viewComponent.getWidth(), _viewComponent.getHeight());_x000D_
package com.jidesoft.swing;_x000D_
_x000D_
import javax.swing.*;_x000D_
import javax.swing.event.MouseInputAdapter;_x000D_
import javax.swing.event.MouseInputListener;_x000D_
import java.awt.*;_x000D_
import java.awt.event.MouseEvent;_x000D_
import java.awt.geom.Area;_x000D_
import java.awt.image.BufferedImage;_x000D_
_x000D_
/**_x000D_
 * Original code http://forums.java.net/jive/thread.jspa?forumID=73&threadID=14674 under "Do whatever you want with this_x000D_
 * code" license_x000D_
 */_x000D_
@SuppressWarnings("serial")_x000D_
public class ScrollPaneOverview extends JComponent {_x000D_
    _x000D_
    private static final int MAX_SIZE = 400;_x000D_
    private static final int MAX_SCALE = 20;_x000D_
_x000D_
    private Component _owner;_x000D_
    private JScrollPane _scrollPane;_x000D_
    private Component _viewComponent;_x000D_
_x000D_
    protected JPopupMenu _popupMenu;_x000D_
_x000D_
    private BufferedImage _image;_x000D_
    private Rectangle _startRectangle;_x000D_
    private Rectangle _rectangle;_x000D_
    private Point _startPoint;_x000D_
    private double _scale;_x000D_
    private int xOffset;_x000D_
    private int yOffset;_x000D_
_x000D_
    private Color _selectionBorder = Color.BLACK;_x000D_
_x000D_
    public ScrollPaneOverview(JScrollPane scrollPane, Component owner) {_x000D_
        _scrollPane = scrollPane;_x000D_
        _owner = owner;_x000D_
        _image = null;_x000D_
        _startRectangle = null;_x000D_
        _rectangle = null;_x000D_
        _startPoint = null;_x000D_
        _scale = 0.0;_x000D_
_x000D_
        setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));_x000D_
        setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));_x000D_
        MouseInputListener mil = new MouseInputAdapter() {_x000D_
            // A new approach suggested by thomas.bierhance@sdm.de_x000D_
_x000D_
            @Override_x000D_
            public void mousePressed(MouseEvent e) {_x000D_
                if (_startPoint != null) {_x000D_
                    Point newPoint = e.getPoint();_x000D_
                    int deltaX = (int) ((newPoint.x - _startPoint.x) / _scale);_x000D_
                    int deltaY = (int) ((newPoint.y - _startPoint.y) / _scale);_x000D_
                    scroll(deltaX, deltaY);_x000D_
                }_x000D_
                _startPoint = null;_x000D_
                _startRectangle = _rectangle;_x000D_
            }_x000D_
_x000D_
            @Override_x000D_
            public void mouseMoved(MouseEvent e) {_x000D_
                if (_startPoint == null) {_x000D_
                    _startPoint = new Point(_rectangle.x + _rectangle.width / 2, _rectangle.y + _rectangle.height / 2);_x000D_
                }_x000D_
                Point newPoint = e.getPoint();_x000D_
                moveRectangle(newPoint.x - _startPoint.x, newPoint.y - _startPoint.y);_x000D_
            }_x000D_
        };_x000D_
        addMouseListener(mil);_x000D_
        addMouseMotionListener(mil);_x000D_
        _popupMenu = new JPopupMenu();_x000D_
        _popupMenu.setLayout(new BorderLayout());_x000D_
        _popupMenu.add(this, BorderLayout.CENTER);_x000D_
    }_x000D_
_x000D_
    public void setSelectionBorderColor(Color selectionBorder) {_x000D_
        _selectionBorder = selectionBorder;_x000D_
    }_x000D_
_x000D_
    public Color getSelectionBorder() {_x000D_
        return _selectionBorder;_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    protected void paintComponent(Graphics g) {_x000D_
        if (_image == null || _rectangle == null)_x000D_
            return;_x000D_
        Graphics2D g2d = (Graphics2D) g;_x000D_
        Insets insets = getInsets();_x000D_
        int xOffset = insets.left;_x000D_
        int yOffset = insets.top;_x000D_
_x000D_
        g.setColor(_scrollPane.getViewport().getView().getBackground());_x000D_
        g.fillRect(0, 0, getWidth(), getHeight());_x000D_
        g.drawImage(_image, xOffset, yOffset, null);_x000D_
_x000D_
        int availableWidth = getWidth() - insets.left - insets.right;_x000D_
        int availableHeight = getHeight() - insets.top - insets.bottom;_x000D_
        Area area = new Area(new Rectangle(xOffset, yOffset, availableWidth, availableHeight));_x000D_
        area.subtract(new Area(_rectangle));_x000D_
        g.setColor(new Color(255, 255, 255, 128));_x000D_
        g2d.fill(area);_x000D_
_x000D_
        Color oldcolor = g.getColor();_x000D_
        g.setColor(_selectionBorder);_x000D_
        g.drawRect(_rectangle.x, _rectangle.y, _rectangle.width, _rectangle.height);_x000D_
_x000D_
        g.setColor(oldcolor);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public Dimension getPreferredSize() {_x000D_
        if (_image == null || _rectangle == null)_x000D_
            return new Dimension();_x000D_
        Insets insets = getInsets();_x000D_
        return new Dimension(_image.getWidth(null) + insets.left + insets.right, _image.getHeight(null) + insets.top + insets.bottom);_x000D_
    }_x000D_
_x000D_
    public void display() {_x000D_
        _viewComponent = _scrollPane.getViewport().getView();_x000D_
        if (_viewComponent == null) {_x000D_
            return;_x000D_
        }_x000D_
_x000D_
        int maxSize = Math.max(MAX_SIZE, Math.max(_scrollPane.getWidth(), _scrollPane.getHeight()) / 2);_x000D_
_x000D_
        int width = Math.min(_viewComponent.getWidth(), _scrollPane.getViewport().getWidth() * MAX_SCALE);_x000D_
        if (width <= 0) {_x000D_
            return;_x000D_
        }_x000D_
        int height = Math.min(_viewComponent.getHeight(), _scrollPane.getViewport().getHeight() * MAX_SCALE);_x000D_
        if (height <= 0) {_x000D_
            return;_x000D_
        }_x000D_
        double scaleX = (double) maxSize / width;_x000D_
        double scaleY = (double) maxSize / height;_x000D_
_x000D_
        _scale = Math.max(1.0 / MAX_SCALE, Math.min(scaleX, scaleY));_x000D_
_x000D_
        _image = new BufferedImage((int) (width * _scale), (int) (height * _scale), BufferedImage.TYPE_INT_RGB);_x000D_
        Graphics2D g = _image.createGraphics();_x000D_
_x000D_
        // If the view is larger than the max scale allows only the the top left most part will now be painted_x000D_
        // One solution would be paint only the part around the current position, but I can't get it to paint - Walter Laan._x000D_
        // note that without limiting the scale, the width/height will become zero (illegal for BufferedImage)_x000D_
        // See CornerScrollerVisualTest in the test folder_x000D_
        _x000D_
//        g.setColor(_viewComponent.getBackground());_x000D_
//        g.fillRect(0, 0,<SUF>
//        Point viewPosition = _scrollPane.getViewport().getViewPosition();_x000D_
//        xOffset = Math.max(0, viewPosition.x - (width / 2)); _x000D_
//        yOffset = Math.max(0, viewPosition.y - (height / 2)); _x000D_
//        g.translate(-xOffset, -yOffset);_x000D_
//        g.setClip(0, 0, width, height);_x000D_
        _x000D_
        g.scale(_scale, _scale);_x000D_
        g.setClip(xOffset, yOffset, width, height);_x000D_
        /// {{{ Qian Qian 10/72007_x000D_
        boolean wasDoubleBuffered = _viewComponent.isDoubleBuffered();_x000D_
        try {_x000D_
            if (_viewComponent instanceof JComponent) {_x000D_
                ((JComponent) _viewComponent).setDoubleBuffered(false);_x000D_
            }_x000D_
            _viewComponent.paint(g);_x000D_
        }_x000D_
        finally {_x000D_
            if (_viewComponent instanceof JComponent) {_x000D_
                ((JComponent) _viewComponent).setDoubleBuffered(wasDoubleBuffered);_x000D_
            }_x000D_
            g.dispose();_x000D_
        }_x000D_
        /// QianQian 10/7/2007 }}}_x000D_
        _startRectangle = _scrollPane.getViewport().getViewRect();_x000D_
        Insets insets = getInsets();_x000D_
        _startRectangle.x = (int) (_scale * _startRectangle.x + insets.left);_x000D_
        _startRectangle.y = (int) (_scale * _startRectangle.y + insets.right);_x000D_
        _startRectangle.width *= _scale;_x000D_
        _startRectangle.height *= _scale;_x000D_
        _rectangle = _startRectangle;_x000D_
        Point centerPoint = new Point(_rectangle.x + _rectangle.width / 2, _rectangle.y + _rectangle.height / 2);_x000D_
        showPopup(-centerPoint.x, -centerPoint.y, _owner);_x000D_
    }_x000D_
_x000D_
    /**_x000D_
     * Show popup at designated location._x000D_
     * <p/>_x000D_
     * You could override this method to show the popup in different location._x000D_
     *_x000D_
     * @param x the x axis pixel_x000D_
     * @param y the y axis pixel_x000D_
     * @param owner the owner of the popup_x000D_
     */_x000D_
    protected void showPopup(int x, int y, Component owner) {_x000D_
        _popupMenu.show(owner, x, y);_x000D_
    }_x000D_
_x000D_
    private void moveRectangle(int aDeltaX, int aDeltaY) {_x000D_
        if (_startRectangle == null)_x000D_
            return;_x000D_
        Insets insets = getInsets();_x000D_
        Rectangle newRect = new Rectangle(_startRectangle);_x000D_
        newRect.x += aDeltaX;_x000D_
        newRect.y += aDeltaY;_x000D_
        newRect.x = Math.min(Math.max(newRect.x, insets.left), getWidth() - insets.right - newRect.width);_x000D_
        newRect.y = Math.min(Math.max(newRect.y, insets.right), getHeight() - insets.bottom - newRect.height);_x000D_
        Rectangle clip = new Rectangle();_x000D_
        Rectangle.union(_rectangle, newRect, clip);_x000D_
        clip.grow(2, 2);_x000D_
        _rectangle = newRect;_x000D_
        paintImmediately(clip);_x000D_
    }_x000D_
_x000D_
    private void scroll(int aDeltaX, int aDeltaY) {_x000D_
        JComponent component = (JComponent) _scrollPane.getViewport().getView();_x000D_
        Rectangle rect = component.getVisibleRect();_x000D_
        rect.x += xOffset + aDeltaX;_x000D_
        rect.y += yOffset + aDeltaY;_x000D_
        component.scrollRectToVisible(rect);_x000D_
        _popupMenu.setVisible(false);_x000D_
    }_x000D_
}_x000D_
