import java.awt.*;
import java.awt.event.*;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.ComponentAdapter;
import java.net.URL;

import javax.swing.*;

/**
 * ImageDisplay is a test program for DoubleHeadedScrollbar.
 * It displays an image with a horizontal DoubleHeadedScrollbar
 * and a vertical normal scrollbar.  The user can pan around as usual,
 * or use the double-headed thumb to magnify the image.
 */
public class ImageDisplay extends JComponent {
    // UI components
    private JComponent imageComponent;
    private JScrollBar vertical;
    private JScrollBar horizontal;
    
    // image being displayed
    private Image image;
    
    // image dimensions in pixels
    private int width, height;
    
    // part of image currently visible in the imageComponent,
    // in pixel coordinates
    private int x1;
    private int x2;
    private int y1;
    private int y2;
    
    /**
     * Make an ImageDisplay.
     * @param img Image to display
     */
    public ImageDisplay(Image img) {
        // save image 
        this.image = img;        
        width = image.getWidth(null);
        height = image.getHeight(null);

        // create the image-display component
        imageComponent = new JComponent() {
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Dimension size = getSize();            
                g.drawImage(image, 
                            0, 0, size.width, size.height, 
                            x1, y1, x2, y2, null);       
            }
        };
        imageComponent.setPreferredSize(new Dimension(width/2, height/2));
        
        // create the scrollbars
        horizontal = new DoubleHeadedScrollbar(0, 50, 0, 100);
        vertical = new JScrollBar(JScrollBar.VERTICAL, 0, 50, 0, 100);
        updateFrom(horizontal);
        
        // listen to the scrollbars for changes
        AdjustmentListener listener = new AdjustmentListener() {
            public void adjustmentValueChanged(AdjustmentEvent e) {
                JScrollBar scrollbar = (JScrollBar)e.getSource();
                updateFrom(scrollbar);
            }
        };        
        horizontal.addAdjustmentListener(listener);
        vertical.addAdjustmentListener(listener);
        
        // lay out the image and the scrollbars.
        setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();

        c.gridx = 0;
        c.gridy = 0;
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 1;
        c.weighty = 1;
        add(imageComponent, c);

        c.gridx = 1;
        c.gridy = 0;
        c.fill = GridBagConstraints.VERTICAL;
        c.weightx = 0;
        c.weighty = 1;
        add(vertical, c);

        c.gridx = 0;
        c.gridy = 1;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1;
        c.weighty = 0;
        add(horizontal, c);        
    }

    // Called when one of the scrollbars is manipulated.
    // Pans and magnifies the image as appropriate.
    private void updateFrom(JScrollBar scrollbar) {
        // first, copy the visible extent to the other scrollbar
        ((scrollbar == horizontal) ? vertical : horizontal)
            .setVisibleAmount (scrollbar.getVisibleAmount());

        double xRange = horizontal.getMaximum() - horizontal.getMinimum();
        x1 = (int) Math.round(horizontal.getValue() * width / xRange);
        x2 = x1 + (int) Math.round(horizontal.getVisibleAmount() * width / xRange);

        double yRange = vertical.getMaximum() - vertical.getMinimum();
        y1 = (int) Math.round(vertical.getValue() * height / yRange);
        y2 = y1 + (int) Math.round(vertical.getVisibleAmount() * height / yRange);
        
        repaint();
    }

    /**
     * Main method.  Pops up a window displaying an ImageDisplay on
     * a sample image.
     * @param args command line arguments; ignored.
     */
    public static void main(String[] args) {
        // uncomment the following code to use the 
        // local platform's look-and-feel
//         try {
//             String lookAndFeel = UIManager.getSystemLookAndFeelClassName();
//             UIManager.setLookAndFeel (lookAndFeel);
//         } catch (Exception e) {
//             e.printStackTrace();
//         }

        final JFrame f = new JFrame("Double-Headed Scrollbar");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container c = f.getContentPane();

        URL url = ImageDisplay.class.getResource("Stephansdom.jpg");            
        Image img = new ImageIcon(url).getImage();            
        c.add(new ImageDisplay(img), BorderLayout.CENTER);
        
        f.pack();
        f.show();
    }
}
