package fr.mael.jiwigo.ui.browser; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.awt.print.PageFormat; import java.awt.print.Printable; import java.awt.print.PrinterException; import java.util.Hashtable; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import fr.mael.jiwigo.transverse.ImagesManagement; import fr.mael.jiwigo.transverse.util.ImagesUtil; import fr.mael.jiwigo.transverse.util.Messages; /** Copyright (c) 2010, Mael All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of jiwigo nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Mael BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * Panel qui affiche une image * @author mael * */ public class BrowserImagePanel extends JPanel implements MouseWheelListener, Printable, MouseMotionListener, MouseListener { private BufferedImage image; private double scale = 1.0; boolean flipH = false; boolean flipV = false; private int valueSlider = 16; private boolean clicked = false; private int xTopPosition; private int yTopPosition; private int xDragPosition; private int yDragPosition; private boolean drawSelection = false; private ImagesManagement imagesManagement = ImagesManagement.getInstance(); /** * Constructor * @param image the image */ public BrowserImagePanel() { this.image = imagesManagement.getCurrentBufferedImage(); this.addMouseWheelListener(this); this.addMouseMotionListener(this); this.addMouseListener(this); } /* (non-Javadoc) * @see javax.swing.JComponent#paintComponent(java.awt.Graphics) */ protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); double x = (getWidth() - scale * image.getWidth()) / 2; double y = (getHeight() - scale * image.getHeight()) / 2; AffineTransform at = AffineTransform.getTranslateInstance(x, y); if (flipV && !flipH) { at.scale(scale, -scale); at.translate(0, -getHeight() / 2); } else if (flipH && !flipV) { at.scale(-scale, scale); at.translate(-getWidth() / 2, 0); } else if (flipH && flipV) { at.scale(-scale, -scale); at.translate(-getWidth() / 2, -getHeight() / 2); } else { at.scale(scale, scale); } g2.drawRenderedImage(image, at); if (drawSelection) { // g2.drawRect(xTopPosition, yTopPosition, xDragPosition - xTopPosition, yDragPosition - yTopPosition); } } /* (non-Javadoc) * @see javax.swing.JComponent#getPreferredSize() */ public Dimension getPreferredSize() { int w = (int) (scale * image.getWidth()); int h = (int) (scale * image.getHeight()); return new Dimension(w, h); } public void rogner() { if (scale == 1.0) { //gets the dimensions of the image Double width = getSize().getWidth(); Double height = getSize().getHeight(); //get the top left corner Double xZeroImage = ((width - image.getWidth()) / 2); Double yZeroImage = ((height - image.getHeight()) / 2); //the position of the first click on the imagee //The previous positions where the ones on the panel //have to calculate the position on the image int positionX, positionY; //width and height of the clip int largeur, longueur; //if the selection begins before the beginning of the image in x //0 is taken. Otherwise the position of the click is calculated : //position on the image = position on the panel - position of the x of the image if (xTopPosition - xZeroImage.intValue() < 0) { positionX = 0; } else { positionX = xTopPosition - xZeroImage.intValue(); } //if the selection begins before the beginning of the image in y //0 is taken. Otherwise the position of the click is calculated : //position on the image = position on the panel - position of the y of the image if (yTopPosition - yZeroImage.intValue() < 0) { positionY = 0; } else { positionY = yTopPosition - yZeroImage.intValue(); } //calculates the width largeur = xDragPosition - xTopPosition; //if it goes past the image if ((positionX + largeur) > image.getWidth()) { //the width is recalculated largeur = image.getWidth() - positionX; } //calculate the height longueur = yDragPosition - yTopPosition; ////if it goes past the image if ((positionY + longueur) > image.getHeight()) { //the height is recalculated longueur = image.getHeight() - positionY; } //gets the cutted imagee image = image.getSubimage(positionX, positionY, largeur, longueur); repaint(); revalidate(); drawSelection = false; } else { JOptionPane.showMessageDialog(this, Messages.getMessage("clippingError"), Messages.getMessage("info"), JOptionPane.INFORMATION_MESSAGE); } } /** * gets the slider * @return the slider */ public JSlider getSlider() { int min = 1, max = 36, inc = 10; final JSlider slider = new JSlider(min, max, 16); slider.setMajorTickSpacing(5); slider.setMinorTickSpacing(1); slider.setPaintTicks(true); slider.setSnapToTicks(true); slider.setLabelTable(getLabelTable(min, max, inc)); slider.setPaintLabels(true); slider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { int value = slider.getValue(); valueSlider = value; scale = (value + 4) / 20.0; revalidate(); repaint(); }; }); return slider; } public void zoomIn() { scale = (++valueSlider + 4) / 20.0; revalidate(); repaint(); } public void zoomOut() { if (scale > 0) { scale = (--valueSlider + 4) / 20.0; revalidate(); repaint(); } } public void zoomNormal() { scale = 1.0; revalidate(); repaint(); } /** * Label of the slider * @param min * @param max * @param inc * @return */ private Hashtable getLabelTable(int min, int max, int inc) { Hashtable table = new Hashtable(); for (int j = min; j <= max; j += inc) { String s = String.format("%.2f", (j + 4) / 20.0); table.put(Integer.valueOf(j), new JLabel(s)); } return table; } /** * right rotation */ public void rotationDroite() { image = (ImagesUtil.rotate(image, Math.PI / 2)); revalidate(); repaint(); } /** * left rotation */ public void rotationGauche() { image = (ImagesUtil.rotate(image, -Math.PI / 2)); revalidate(); repaint(); } /** * @return the image */ public BufferedImage getImage() { return image; } /** * @param image the image to set */ public void changeImage() { this.image = imagesManagement.getCurrentBufferedImage(); revalidate(); repaint(); } /** * @return the drawSelection */ public boolean isDrawSelection() { return drawSelection; } /** * @param drawSelection the drawSelection to set */ public void setDrawSelection(boolean drawSelection) { this.drawSelection = drawSelection; } @Override public void mouseWheelMoved(MouseWheelEvent arg0) { int notches = arg0.getWheelRotation(); String message; String newline = "\n"; if (notches < 0) { zoomIn(); } else { zoomOut(); } } @Override public int print(Graphics arg0, PageFormat arg1, int arg2) throws PrinterException { if (arg2 != 0) return NO_SUCH_PAGE; Graphics2D g2 = (Graphics2D) arg0; g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); double x = (getWidth() - scale * image.getWidth()) / 2; double y = (getHeight() - scale * image.getHeight()) / 2; AffineTransform at = AffineTransform.getTranslateInstance(x, y); if (flipV && !flipH) { at.scale(scale, -scale); at.translate(0, -getHeight() / 2); } else if (flipH && !flipV) { at.scale(-scale, scale); at.translate(-getWidth() / 2, 0); } else if (flipH && flipV) { at.scale(-scale, -scale); at.translate(-getWidth() / 2, -getHeight() / 2); } else { at.scale(scale, scale); } g2.drawRenderedImage(image, at); return PAGE_EXISTS; } @Override public void mouseDragged(MouseEvent arg0) { if (clicked) { xDragPosition = arg0.getX(); yDragPosition = arg0.getY(); repaint(); revalidate(); } } @Override public void mouseMoved(MouseEvent arg0) { } public void mouseClicked(MouseEvent arg0) { } public void mouseEntered(MouseEvent arg0) { } public void mouseExited(MouseEvent arg0) { } public void mousePressed(MouseEvent arg0) { clicked = true; xTopPosition = arg0.getX(); yTopPosition = arg0.getY(); drawSelection = true; } public void mouseReleased(MouseEvent arg0) { clicked = false; } }