/* * org.openmicroscopy.shoola.util.ui.lens.lensComponent.java * *------------------------------------------------------------------------------ * Copyright (C) 2006-2016 University of Dundee. All rights reserved. * * * 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.util.ui.lens; //Java imports import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.List; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.filechooser.FileFilter; import omero.model.Length; import omero.model.enums.UnitsLength; import org.openmicroscopy.shoola.util.filter.file.BMPFilter; import org.openmicroscopy.shoola.util.filter.file.CustomizedFileFilter; import org.openmicroscopy.shoola.util.filter.file.JPEGFilter; import org.openmicroscopy.shoola.util.filter.file.PNGFilter; import org.openmicroscopy.shoola.util.filter.file.TIFFFilter; import org.openmicroscopy.shoola.util.image.geom.Factory; import org.openmicroscopy.shoola.util.image.io.Encoder; import org.openmicroscopy.shoola.util.image.io.TIFFEncoder; import org.openmicroscopy.shoola.util.image.io.WriterImage; import org.openmicroscopy.shoola.util.ui.IconManager; import org.openmicroscopy.shoola.util.ui.MessageBox; import org.openmicroscopy.shoola.util.ui.NotificationDialog; import org.openmicroscopy.shoola.util.ui.UIUtilities; import org.openmicroscopy.shoola.util.ui.component.AbstractComponent; import org.openmicroscopy.shoola.util.ui.filechooser.FileChooser; /** * The Lens Component is the main component of the lens accessible from outside * of the lens Package. * * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author Donald MacDonald      * <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a> * @version 3.0 * <small> * (<b>Internal version:</b> $Revision: $Date: $) * </small> * @since OME2.2 */ public class LensComponent extends AbstractComponent { /** Bound property indicating that the location of the lens has changed. */ public static final String LENS_LOCATION_PROPERTY = "lensLocation"; /** Default width of a lens */ public final static int LENS_DEFAULT_WIDTH = 50; /** Default the zoom factor.*/ public final static float DEFAULT_ZOOM = 2.0f; /** The collection of supported formats.*/ private static final List<FileFilter> FILTERS; static { FILTERS = new ArrayList<FileFilter>(); FILTERS.add(new BMPFilter()); FILTERS.add(new JPEGFilter()); FILTERS.add(new PNGFilter()); FILTERS.add(new TIFFFilter()); } /** Reference to the lens object which will render onto the image canvas */ private LensUI lens; /** Menu object which hold the pop-up and menu items. */ private LensMenu menu; /** * Reference to the lensController which will modify the position and * properties of the lens and the zoomWindow. */ private LensController lensController; /** Shows the current zoomed image specified by the lens. */ private ZoomWindow zoomWindow; /** Holds the properties of the lens, x,y, width height. */ private LensModel lensModel; /** * Displays in pixels if <code>true</code>, in microns otherwise. * * @param b See above. */ void setDisplayInPixels(boolean b) { zoomWindow.setDisplayInPixels(b); zoomWindow.setLensXY(lens.getX(), lens.getY()); zoomWindow.setLensWidthHeight(lens.getWidth(), lens.getHeight()); } /** * Sets the lens Size to a value described in LensAction. * * @param width The width of the lens. * @param height The height of the lens. */ void setLensSize(int width, int height) { lensController.setLensSize(width, height); } /** * Indicates the location of the lens. Fires a property change to notify * listeners of the new bounds. */ void updateLensLocation() { Rectangle bounds = lensModel.getLensScaledBounds(); firePropertyChange(LENS_LOCATION_PROPERTY, null, bounds); zoomWindow.paintImage(); } /** Selects the menu item if the size corresponds to a predefined size. */ void updateLensSize() { int w = lensModel.getWidth(); int h = lensModel.getHeight(); int index = LensAction.sizeToIndex(w, h); menu.setSelectedSize(index); zoomWindow.setSelectedSize(index); } /** * Sets the magnification factor for the lens. * * @param zoomFactor The magnification factor. */ public void setZoomFactor(float zoomFactor) { lensController.setZoomFactor(zoomFactor); int index = ZoomAction.factorToIndex(zoomFactor); menu.setZoomIndex(index); zoomWindow.setZoomIndex(index); } /** * Magnifies the image. * * @param tick The number of "clicks" the mouse wheel was rotated. */ void lensMouseWheelMoved(int tick) { float zoomFactor = lensModel.getZoomFactor(); zoomFactor -= 0.1f*tick; zoomFactor = Math.round(zoomFactor*10)/10.0f; if (zoomFactor < LensModel.MINIMUM_ZOOM) zoomFactor = LensModel.MINIMUM_ZOOM; if (zoomFactor > LensModel.MAXIMUM_ZOOM) zoomFactor = LensModel.MAXIMUM_ZOOM; setZoomFactor(zoomFactor); } /** * Creates a new instance which is the container for the lens * infrastructure. * * @param parent The parent of the Dialog. */ public LensComponent(JFrame parent, int lensWidth, int lensHeight) { lensModel = new LensModel(null); zoomWindow = new ZoomWindow(parent, this, lensModel); lens = new LensUI(this, lensWidth, lensHeight); lensController = new LensController(lensModel, lens, zoomWindow); lensModel.setWidth(lensWidth); lensModel.setHeight(lensHeight); lensModel.setImageZoomFactor(ZoomAction.ZOOMx2+1); lens.addController(lensController); lens.setLensColour(lensModel.getLensPreferredColour()); menu = new LensMenu(this); lens.setPopupMenu(menu.getPopupMenu()); zoomWindow.setJMenuBar(menu.getMenubar()); setZoomFactor(DEFAULT_ZOOM); } /** * Creates a new instance which is the container for the lens * infrastructure. * * @param parent The parent of the Dialog. */ public LensComponent(JFrame parent) { this(parent, LENS_DEFAULT_WIDTH, LENS_DEFAULT_WIDTH); } /** Saves the image as <code>JPEG</code>, <code>PNG</code> etc.*/ void saveAs() { FileChooser d = new FileChooser((JFrame) zoomWindow.getParent(), FileChooser.SAVE, SaveAction.NAME, SaveAction.DESCRIPTION, FILTERS, false, true); d.setSelectedFile(UIUtilities.removeFileExtension( lensModel.getImageName())); d.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (! (evt.getSource() instanceof FileChooser)) return; FileChooser fileChooser = (FileChooser) evt.getSource(); String name = evt.getPropertyName(); if (FileChooser.APPROVE_SELECTION_PROPERTY.equals(name)) { File[] files = (File[]) evt.getNewValue(); File file = files[0]; FileFilter filter = fileChooser.getSelectedFilter(); String format = ""; if (filter instanceof CustomizedFileFilter) { format = ((CustomizedFileFilter) filter).getExtension(); } // check if file is allowed. If not, add extension. if (!filter.accept(file)) { String filePath = file.getAbsolutePath(); filePath = filePath + "." + format; file = new File(filePath); } // if file exists, get user to confirm. Otherwise exit! JFrame frame = (JFrame) zoomWindow.getParent(); if (file.exists()) { String title = "File Exists"; String message = "An image with the same name" + "already exists. Do you want to overwrite it?"; MessageBox msg = new MessageBox(frame, title, message); int option = msg.centerMsgBox(); if (option != MessageBox.YES_OPTION) return; } NotificationDialog dialog; //Now save the image BufferedImage image = getZoomedImage(); IconManager icons = IconManager.getInstance(); try { if (TIFFFilter.TIF.equals(format)) { Encoder encoder = new TIFFEncoder( Factory.createImage(image), new DataOutputStream( new FileOutputStream(file))); WriterImage.saveImage(encoder); } else WriterImage.saveImage(file, image, format); } catch (Exception e) { dialog = new NotificationDialog( frame, SaveAction.NAME, "An error occurred while saving the image.", icons.getIcon(IconManager.ERROR_32)); dialog.pack(); UIUtilities.centerAndShow(dialog); return; } dialog = new NotificationDialog( frame, SaveAction.NAME, "The image has been successfully saved in\n"+ file.getParent(), icons.getIcon(IconManager.INFO_32)); dialog.pack(); UIUtilities.centerAndShow(dialog); } } }); UIUtilities.centerAndShow(d); } /** * Sets the colour of the lens to better contrast with the * background of the image. */ public void setLensPreferredColour() { lens.setLensColour(lensModel.getLensPreferredColour()); } /** Hides the lens and the control dialog. */ public void zoomWindowClosed() { zoomWindow.setVisible(false); lens.setVisible(false); } /** * Sets the mapping from pixel size to microns along the x and y axis. * * @param x mapping in x axis. * @param y mapping in y axis. */ public void setXYPixelMicron(Length x, Length y) { zoomWindow.setXYPixelMicron(x, y); menu.setMicronsMenuEnabled(!x.getUnit().equals(UnitsLength.PIXEL) && !y.getUnit().equals(UnitsLength.PIXEL)); } /** * Sets the plane image of the lens to a new image. * * @param img new Image. */ public void setPlaneImage(BufferedImage img) { lensModel.setPlaneImage(img); zoomWindow.paintImage(); } /** * Sets the visibility of the lens, and ZoomWindowUI. * * @param makeVisible The value to set. * */ public void setVisible(boolean makeVisible) { lens.setVisible(makeVisible); zoomWindow.setVisible(makeVisible); } /** * Sets the image zoom factor. The image in the viewer has been zoomed by * this number. * * @param imageZoomFactor The amount of zooming that has occurred on the * image. */ public void setImageZoomFactor(float imageZoomFactor) { /* if (imageZoomFactor < LensModel.MINIMUM_ZOOM) imageZoomFactor = LensModel.MINIMUM_ZOOM; if (imageZoomFactor > LensModel.MAXIMUM_ZOOM) imageZoomFactor = LensModel.MAXIMUM_ZOOM; */ lensModel.setImageZoomFactor(imageZoomFactor); lens.setImageZoomFactor(); } /** * Sets the location of the lens on the canvas. * * @param x The x-coordinate. * @param y The y-coordinate. */ public void setLensLocation(int x, int y) { lensController.setLensLocation(x, y); } /** * Returns the zoomed image. * * @return See above. */ public BufferedImage getZoomedImage() { return lensModel.getZoomedImage(); } /** * Returns the lens UI. * * @return See above. */ public JComponent getLensUI() { return lens; } /** * Returns <code>true</code> if the lens and zoomWindow are visible, * <code>false</code> otherwise. * * @return See above. */ public boolean isVisible() { return (lens.isVisible() && zoomWindow.isVisible()); } /** * Sets the location of the lens to point. * * @param loc The value to set. */ public void setLensLocation(Point loc) { setLensLocation(loc.x, loc.y); } /** * Returns the scaled image size, takes into account the zoom factor of the * image viewer. * * @return size of lens, scaled by image zoom factor. */ public Dimension getLensScaledSize() { return lensModel.getLensScaledSize(); } /** * Gets the scaled image location, takes into account the zoom factor of the * image viewer. * * @return location of lens, scaled by image zoom factor. */ public Point getLensScaledLocation() { return lensModel.getLensScaledLocation(); } /** * Sets the colour of the lens border to the colour specified. * * @param color The color to set. */ public void setLensColour(Color color) { if (color == null) return; lens.setLensColour(color); } /** * Returns the bounds of the scaled image size, takes into account the zoom * factor of the image viewer. * * @return See above. */ public Rectangle getLensScaledBounds() { return lensModel.getLensScaledBounds(); } /** * Gets the image location. * * @return The location of lens. */ public Point getLensLocation() { return lensModel.getLensLocation(); } /** * Returns the view of the zoom window. * * @return See above. */ public Component getZoomWindow() { return zoomWindow; } /** * Returns a zoomed image of the passed image. * * @param image The image to zoom. * @return See above. */ public BufferedImage createZoomedImage(BufferedImage image) { if (image == null) return null; return lensModel.createZoomedImage(image); } /** * Sets the image to be magnified and the location of the lens. * * @param image The image to magnify. * @param f The amount of zooming that has occurred on the image. * @param x The x-coordinate of the lens. * @param y The y-coordinate of the lens. */ public void resetLens(BufferedImage image, float f, int x, int y) { lensModel.setImageZoomFactor(f); lensModel.setPlaneImage(image); lensModel.setLensLocation(x, y); //from ZoomFactor lens.setImageZoomFactor(); //from PlaneImage lensController.setLensLocation(x, y); setLensSize(lensModel.getWidth(), lensModel.getHeight()); zoomWindow.paintImage(); if (!zoomWindow.isVisible()) zoomWindow.setSize(ZoomWindow.DEFAULT_SIZE); } /** Indicates to reset the zoomed buffer to <code>null</code>*/ public void resetDataBuffered() { lensModel.resetDataBuffer(); } /** * Sets the background color. * * @param color The color to set */ public void setBackgroundColor(Color color) { lensModel.setBackgroundColor(color); zoomWindow.updateBackgroundColor(); } /** * Sets the name of the image. * * @param imageName The name of the image. */ public void setImageName(String imageName) { lensModel.setImageName(imageName); } }