Java tutorial
/* * org.openmicroscopy.shoola.agents.iviewer.view.ImViewerUI * *------------------------------------------------------------------------------ * Copyright (C) 2006-2014 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.agents.imviewer.view; //Java imports import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.HierarchyBoundsAdapter; import java.awt.event.HierarchyBoundsListener; import java.awt.event.HierarchyEvent; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.swing.AbstractButton; import javax.swing.Action; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.ImageIcon; import javax.swing.JCheckBoxMenuItem; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JSeparator; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; //Third-party libraries import info.clearthought.layout.TableLayout; import com.sun.opengl.util.texture.TextureData; //Application-internal dependencies import omero.model.PlaneInfo; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.openmicroscopy.shoola.agents.imviewer.IconManager; import org.openmicroscopy.shoola.agents.imviewer.ImViewerAgent; import org.openmicroscopy.shoola.agents.imviewer.actions.ColorModelAction; import org.openmicroscopy.shoola.agents.imviewer.actions.UnitBarSizeAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ViewerAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ZoomAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ZoomGridAction; import org.openmicroscopy.shoola.agents.imviewer.browser.Browser; import org.openmicroscopy.shoola.agents.imviewer.util.ChannelColorMenuItem; import org.openmicroscopy.shoola.agents.imviewer.util.HistoryItem; import org.openmicroscopy.shoola.agents.imviewer.util.ImagePaintingFactory; import org.openmicroscopy.shoola.agents.imviewer.util.PlaneInfoComponent; import org.openmicroscopy.shoola.agents.imviewer.util.player.MoviePlayerDialog; import org.openmicroscopy.shoola.agents.metadata.view.MetadataViewer; import org.openmicroscopy.shoola.agents.util.EditorUtil; import org.openmicroscopy.shoola.env.data.model.ProjectionParam; import org.openmicroscopy.shoola.env.rnd.data.ResolutionLevel; import org.openmicroscopy.shoola.env.ui.TaskBar; import org.openmicroscopy.shoola.env.ui.TopWindow; import org.openmicroscopy.shoola.util.file.modulo.ModuloInfo; import org.openmicroscopy.shoola.util.ui.ClosableTabbedPane; import org.openmicroscopy.shoola.util.ui.ClosableTabbedPaneComponent; import org.openmicroscopy.shoola.util.ui.ColorCheckBoxMenuItem; import org.openmicroscopy.shoola.util.ui.LoadingWindow; import org.openmicroscopy.shoola.util.ui.UIUtilities; import org.openmicroscopy.shoola.util.ui.UnitsObject; import org.openmicroscopy.shoola.util.ui.lens.LensComponent; import org.openmicroscopy.shoola.util.ui.tdialog.TinyDialog; import pojos.ChannelData; import pojos.DataObject; import pojos.GroupData; import pojos.ImageData; /** * The {@link ImViewer} view. * Embeds the {@link Browser}. Also provides a menu bar, a status bar and a * panel hosting various controls. * * @author Jean-Marie Burel * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author Andrea Falconi * <a href="mailto:a.falconi@dundee.ac.uk">a.falconi@dundee.ac.uk</a> * @author Donald MacDonald * <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a> * @version 3.0 * @since OME2.2 */ class ImViewerUI extends TopWindow { /** Indicates to update the channel buttons composing the grid view. */ static final int GRID_ONLY = 0; /** Indicates to update the channel buttons composing the main view. */ static final int VIEW_ONLY = 1; /** Indicates to update the channel buttons composing the main view. */ static final int PROJECTION_ONLY = 2; /** * Indicates to update the channel buttons composing the grid view, * the projection view and the main view. */ static final int ALL_VIEW = 3; /** Indicates that only the image is displayed. */ static final int NEUTRAL = 0; /** Indicates that the image and the history are displayed. */ static final int HISTORY = 1; /** Indicates that the image and the renderer are displayed. */ static final int RENDERER = 2; /** Indicates that the image, the history and the renderer are displayed. */ static final int HISTORY_AND_RENDERER = 3; /** Number of pixels added to the height of an icon. */ private static final int ICON_EXTRA = 4; /** Indicates the percentage of the screen to use to display the viewer. */ private static final double SCREEN_RATIO = 0.9; /** The available colors for the background color of the canvas. */ private static Map<Color, String> backgrounds; static { backgrounds = new LinkedHashMap<Color, String>(); backgrounds.put(ImagePaintingFactory.DEFAULT_BACKGROUND, ImagePaintingFactory.DEFAULT_BACKGROUND_NAME); backgrounds.put(Color.WHITE, "White"); backgrounds.put(Color.BLACK, "Black"); backgrounds.put(Color.GRAY, "Grey"); backgrounds.put(Color.LIGHT_GRAY, "Light Grey"); } private static final String SCALE_BAR_TEXT = "Scale bar length (in "; /** Reference to the Control. */ private ImViewerControl controller; /** Reference to the Model. */ private ImViewerModel model; /** The status bar. */ private StatusBar statusBar; /** Lens component which will control all behavior of the lens. */ private LensComponent lens; /** The tool bar. */ private ToolBar toolBar; /** The control pane. */ private ControlPane controlPane; /** Group hosting the items of the <code>Zoom</code> menu. */ private ButtonGroup zoomingGroup; /** Group hosting the items of the <code>Color Model</code> menu. */ private ButtonGroup colorModelGroup; /** The loading window. */ private LoadingWindow loadingWindow; /** Tab pane hosting the various panel. */ private ClosableTabbedPane tabs; /** The component displaying the history. */ private HistoryUI historyUI; /** * Split component used to display the image in the top section and the * history component in the bottom one. */ private JSplitPane historySplit; /** * Split component used to display the renderer component on the left hand * side of the pane. */ private JSplitPane rendererSplit; /** * One out of the following list: * {@link #NEUTRAL}, {@link #HISTORY}, {@link #RENDERER} and * {@link #HISTORY_AND_RENDERER}. */ private int displayMode; /** Item used to control show or hide the renderer. */ private JCheckBoxMenuItem rndItem; /** Item used to control show or hide the metadata. */ private JCheckBoxMenuItem metadataItem; /** Item used to control show or hide the history. */ private JCheckBoxMenuItem historyItem; /** The dimension of the main component i.e. the tab pane. */ private Dimension restoreSize; /** Listener to the bounds of the container. */ private HierarchyBoundsAdapter boundsAdapter; /** The height of the icons in the tab pane plus 2 pixels. */ private int tabbedIconHeight; /** The menu displaying the users who viewed the image. */ private UsersPopupMenu usersMenu; /** The default insets of a split pane. */ private Insets refInsets; /** Group hosting the possible background colors. */ private ButtonGroup bgColorGroup; /** Group hosting the possible scale bar length. */ private ButtonGroup scaleBarGroup; /** The source invoking the {@link #usersMenu}. */ private Component source; /** The location where to pop up the {@link #usersMenu}. */ private Point location; /** The zoom menu. */ private JMenu zoomMenu; /** The zoom grid menu. */ private JMenu zoomGridMenu; /** Group hosting the items of the <code>ZoomGrid</code> menu. */ private ButtonGroup zoomingGridGroup; /** The panel hosting the view. */ private ClosableTabbedPaneComponent viewPanel; /** The panel hosting the view. */ private ClosableTabbedPaneComponent gridViewPanel; /** The panel hosting the view. */ private ClosableTabbedPaneComponent projectionViewPanel; /** The object displaying the plane information, one per channel. */ private Map<Integer, PlaneInfoComponent> planes; /** The central component. */ private JComponent mainComponent; /** The default index of the scale bar. */ private int defaultIndex; /** The viewer as a component. */ private JComponent component; /** The dialog displaying info about the image.*/ private TinyDialog infoDialog; /** The dialog displaying info about the image.*/ private TinyDialog channelDialog; /** The magnification factor for the big image.*/ private double bigImageMagnification; /** Item used to show or hide the unit bar. */ private JCheckBoxMenuItem unitBarItem; /** Item used to show or hide the unit bar. */ private JMenu scaleBarMenu; /** * Finds the first {@link HistoryItem} in <code>x</code>'s containment * hierarchy. * * @param x A component. * @return The parent {@link HistoryItem} or <code>null</code> if none * was found. */ private HistoryItem findParentDisplay(Object x) { while (true) { if (x instanceof HistoryItem) return (HistoryItem) x; if (x instanceof JComponent) x = ((JComponent) x).getParent(); else break; } return null; } /** * Initializes and returns a split pane, either vertical or horizontal * depending on the passed parameter. * * @param orientation The orientation of the split pane. * @return See above. */ private JSplitPane initSplitPane(int orientation) { int type; switch (orientation) { case JSplitPane.HORIZONTAL_SPLIT: case JSplitPane.VERTICAL_SPLIT: type = orientation; break; default: type = JSplitPane.HORIZONTAL_SPLIT; } JSplitPane pane = new JSplitPane(type); pane.setOneTouchExpandable(true); pane.setContinuousLayout(true); pane.setDividerLocation(-1); pane.setResizeWeight(0.0); return pane; } /** Initializes the split panes. */ private void initSplitPanes() { if (historyUI == null) historyUI = new HistoryUI(this, model, controller); //historySplit = new SplitPanel(SplitPanel.HORIZONTAL); historySplit = initSplitPane(JSplitPane.VERTICAL_SPLIT); rendererSplit = initSplitPane(JSplitPane.HORIZONTAL_SPLIT); } /** * Creates the menu bar. * * @param pref The user preferences. * @return The menu bar. */ private JMenuBar createMenuBar(ViewerPreferences pref) { zoomMenu = new JMenu("Zoom"); zoomMenu.setMnemonic(KeyEvent.VK_Z); zoomingGroup = new ButtonGroup(); //Create zoom grid menu zoomGridMenu = new JMenu("Zoom"); zoomingGridGroup = new ButtonGroup(); JMenuBar menuBar = new JMenuBar(); menuBar.add(createControlsMenu(pref)); menuBar.add(createViewMenu(pref)); if (!model.isBigImage()) menuBar.add(createZoomMenu(pref, true)); menuBar.add(createShowViewMenu()); TaskBar tb = ImViewerAgent.getRegistry().getTaskBar(); //menuBar.add(tb.getWindowsMenu()); menuBar.add(tb.getMenu(TaskBar.WINDOW_MENU)); menuBar.add(tb.getMenu(TaskBar.HELP_MENU)); return menuBar; } /** * Helper method to create the background color sub-menu. * * @param pref The user preferences. * @return See above. */ private JMenuItem createBackgroundColorSubMenu(ViewerPreferences pref) { JMenu menu = new JMenu("Background color"); bgColorGroup = new ButtonGroup(); Iterator<Entry<Color, String>> i = backgrounds.entrySet().iterator(); ColorCheckBoxMenuItem item; Color c; Color refColor = ImagePaintingFactory.DEFAULT_BACKGROUND; if (pref != null) refColor = pref.getBackgroundColor(); if (refColor == null) refColor = ImagePaintingFactory.DEFAULT_BACKGROUND; Entry<Color, String> entry; while (i.hasNext()) { entry = i.next(); c = entry.getKey(); item = new ColorCheckBoxMenuItem(c); item.setText(entry.getValue()); item.setSelected(c.equals(refColor)); bgColorGroup.add(item); menu.add(item); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ColorCheckBoxMenuItem src = (ColorCheckBoxMenuItem) e.getSource(); if (src.isSelected()) { controller.setPreferences(); if (lens != null) lens.setBackgroundColor(src.getColor()); model.getBrowser().setBackgroundColor(src.getColor()); } } }); } return menu; } /** * Helper method to create the unit bar color sub-menu. * * @param pref The user preferences. * @return See above. */ private JMenuItem createScaleBarColorSubMenu(ViewerPreferences pref) { JMenu menu = new JMenu("Scale bar/Text color"); ButtonGroup group = new ButtonGroup(); Iterator<Entry<Color, String>> i = EditorUtil.COLORS_BAR.entrySet().iterator(); ColorCheckBoxMenuItem item; Color c; Color refColor = ImagePaintingFactory.UNIT_BAR_COLOR; if (pref != null) refColor = pref.getScaleBarColor(); if (refColor == null) refColor = ImagePaintingFactory.UNIT_BAR_COLOR; Entry<Color, String> entry; while (i.hasNext()) { entry = i.next(); c = entry.getKey(); item = new ColorCheckBoxMenuItem(c); item.setText(entry.getValue()); item.setSelected(c.equals(refColor)); group.add(item); menu.add(item); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ColorCheckBoxMenuItem source = (ColorCheckBoxMenuItem) e.getSource(); if (source.isSelected()) model.getBrowser().setUnitBarColor(source.getColor()); } }); } return menu; } /** * Helper method to create the unit bar sub-menu. * * @param pref The user preferences. * @return See above. */ private JMenu createScaleBarLengthSubMenu(ViewerPreferences pref) { scaleBarMenu = new JMenu(SCALE_BAR_TEXT + model.getUnits() + ")"); scaleBarGroup = new ButtonGroup(); if (pref != null && pref.getScaleBarIndex() > 0) defaultIndex = pref.getScaleBarIndex(); UnitBarSizeAction a = (UnitBarSizeAction) controller.getAction(ImViewerControl.UNIT_BAR_ONE); JCheckBoxMenuItem item = new JCheckBoxMenuItem(a); item.setSelected(a.getIndex() == defaultIndex); scaleBarGroup.add(item); scaleBarMenu.add(item); a = (UnitBarSizeAction) controller.getAction(ImViewerControl.UNIT_BAR_TWO); item = new JCheckBoxMenuItem(a); item.setSelected(a.getIndex() == defaultIndex); scaleBarGroup.add(item); scaleBarMenu.add(item); a = (UnitBarSizeAction) controller.getAction(ImViewerControl.UNIT_BAR_FIVE); item = new JCheckBoxMenuItem(controller.getAction(ImViewerControl.UNIT_BAR_FIVE)); scaleBarGroup.add(item); item.setSelected(a.getIndex() == defaultIndex); scaleBarMenu.add(item); a = (UnitBarSizeAction) controller.getAction(ImViewerControl.UNIT_BAR_TEN); item = new JCheckBoxMenuItem(controller.getAction(ImViewerControl.UNIT_BAR_TEN)); scaleBarGroup.add(item); item.setSelected(a.getIndex() == defaultIndex); scaleBarMenu.add(item); a = (UnitBarSizeAction) controller.getAction(ImViewerControl.UNIT_BAR_TWENTY); item = new JCheckBoxMenuItem(controller.getAction(ImViewerControl.UNIT_BAR_TWENTY)); scaleBarGroup.add(item); item.setSelected(a.getIndex() == defaultIndex); scaleBarMenu.add(item); a = (UnitBarSizeAction) controller.getAction(ImViewerControl.UNIT_BAR_FIFTY); item = new JCheckBoxMenuItem(controller.getAction(ImViewerControl.UNIT_BAR_FIFTY)); scaleBarGroup.add(item); item.setSelected(a.getIndex() == defaultIndex); scaleBarMenu.add(item); a = (UnitBarSizeAction) controller.getAction(ImViewerControl.UNIT_BAR_HUNDRED); item = new JCheckBoxMenuItem(controller.getAction(ImViewerControl.UNIT_BAR_HUNDRED)); scaleBarGroup.add(item); item.setSelected(a.getIndex() == defaultIndex); scaleBarMenu.add(item); a = (UnitBarSizeAction) controller.getAction(ImViewerControl.UNIT_BAR_CUSTOM); item = new JCheckBoxMenuItem(controller.getAction(ImViewerControl.UNIT_BAR_CUSTOM)); scaleBarGroup.add(item); item.setSelected(a.getIndex() == defaultIndex); scaleBarMenu.add(item); return scaleBarMenu; } /** * Helper method to create the view menu. * * @param pref The user preferences. * @return The controls sub-menu. */ private JMenu createViewMenu(ViewerPreferences pref) { JMenu menu = new JMenu("Display"); menu.setMnemonic(KeyEvent.VK_V); unitBarItem = new JCheckBoxMenuItem(); unitBarItem.setSelected(model.isUnitBar()); unitBarItem.setAction(controller.getAction(ImViewerControl.UNIT_BAR)); menu.add(unitBarItem); menu.add(createScaleBarLengthSubMenu(pref)); menu.add(createScaleBarColorSubMenu(pref)); menu.add(new JSeparator(JSeparator.HORIZONTAL)); menu.add(createBackgroundColorSubMenu(pref)); //menu.add(new JSeparator(JSeparator.HORIZONTAL)); return menu; } /** Synchronizes the unit bar selection. */ void handleUnitBar() { unitBarItem.removeActionListener(controller.getAction(ImViewerControl.UNIT_BAR)); unitBarItem.setSelected(model.isUnitBar()); unitBarItem.setAction(controller.getAction(ImViewerControl.UNIT_BAR)); scaleBarMenu.setText(SCALE_BAR_TEXT + model.getUnits() + ")"); } /** * Helper method to create the controls menu. * * @param pref The user preferences. * @return The controls sub-menu. */ private JMenu createControlsMenu(ViewerPreferences pref) { JMenu menu = new JMenu("Controls"); menu.setMnemonic(KeyEvent.VK_C); ViewerAction action = controller.getAction(ImViewerControl.RENDERER); rndItem = new JCheckBoxMenuItem(); rndItem.setSelected(isRendererShown()); rndItem.setAction(action); rndItem.setText(action.getName()); if (pref != null) rndItem.setSelected(pref.isRenderer()); //menu.add(rndItem); action = controller.getAction(ImViewerControl.METADATA); metadataItem = new JCheckBoxMenuItem(); metadataItem.setSelected(isRendererShown()); metadataItem.setAction(action); metadataItem.setText(action.getName()); if (pref != null) metadataItem.setSelected(pref.isRenderer()); //menu.add(metadataItem); action = controller.getAction(ImViewerControl.HISTORY); historyItem = new JCheckBoxMenuItem(); historyItem.setSelected(isHistoryShown()); historyItem.setAction(action); historyItem.setText(action.getName()); if (pref != null) historyItem.setSelected(pref.isHistory()); //menu.add(historyItem); action = controller.getAction(ImViewerControl.MOVIE); JMenuItem item = new JMenuItem(action); item.setText(action.getName()); menu.add(item); action = controller.getAction(ImViewerControl.LENS); item = new JMenuItem(action); item.setText(action.getName()); menu.add(item); action = controller.getAction(ImViewerControl.MEASUREMENT_TOOL); item = new JMenuItem(action); item.setText(action.getName()); menu.add(item); menu.add(new JSeparator(JSeparator.HORIZONTAL)); //Color model colorModelGroup = new ButtonGroup(); action = controller.getAction(ImViewerControl.GREY_SCALE_MODEL); item = new JCheckBoxMenuItem(); String cm = model.getColorModel(); item.setSelected(cm.equals(ImViewer.GREY_SCALE_MODEL)); item.setAction(action); colorModelGroup.add(item); menu.add(item); action = controller.getAction(ImViewerControl.RGB_MODEL); item = new JCheckBoxMenuItem(); item.setAction(action); item.setSelected(cm.equals(ImViewer.RGB_MODEL)); colorModelGroup.add(item); menu.add(item); menu.add(new JSeparator()); action = controller.getAction(ImViewerControl.CHANNELS_ON); item = new JMenuItem(action); item.setText(action.getName()); menu.add(item); action = controller.getAction(ImViewerControl.CHANNELS_OFF); item = new JMenuItem(action); item.setText(action.getName()); menu.add(item); menu.add(new JSeparator()); action = controller.getAction(ImViewerControl.SAVE); item = new JMenuItem(action); item.setText(action.getName()); menu.add(item); action = controller.getAction(ImViewerControl.PREFERENCES); item = new JMenuItem(action); item.setText(action.getName()); //menu.add(item); return menu; } /** * Helper method to create the Zoom menu. * * @param pref The user preferences. * @param full Pass <code>true</code> to create a full menu, * <code>false</code> to create a partial menu. * @return See above. */ private JMenu createZoomMenu(ViewerPreferences pref, boolean full) { ViewerAction action; JCheckBoxMenuItem item; if (model.isBigImage()) { action = controller.getAction(ImViewerControl.ZOOM_100); item = new JCheckBoxMenuItem(); item.setAction(action); zoomMenu.add(item); action = controller.getAction(ImViewerControl.ZOOM_125); item = new JCheckBoxMenuItem(); item.setAction(action); zoomMenu.add(item); action = controller.getAction(ImViewerControl.ZOOM_150); item = new JCheckBoxMenuItem(); item.setAction(action); zoomMenu.add(item); action = controller.getAction(ImViewerControl.ZOOM_175); item = new JCheckBoxMenuItem(); item.setAction(action); zoomMenu.add(item); return zoomMenu; } action = controller.getAction(ImViewerControl.ZOOM_25); item = new JCheckBoxMenuItem(action); zoomMenu.add(item); zoomingGroup.add(item); action = controller.getAction(ImViewerControl.ZOOM_50); item = new JCheckBoxMenuItem(action); zoomMenu.add(item); zoomingGroup.add(item); action = controller.getAction(ImViewerControl.ZOOM_75); item = new JCheckBoxMenuItem(action); zoomMenu.add(item); zoomingGroup.add(item); action = controller.getAction(ImViewerControl.ZOOM_100); item = new JCheckBoxMenuItem(); item.setAction(action); zoomMenu.add(item); zoomingGroup.add(item); //if (full) { action = controller.getAction(ImViewerControl.ZOOM_125); item = new JCheckBoxMenuItem(action); zoomMenu.add(item); zoomingGroup.add(item); action = controller.getAction(ImViewerControl.ZOOM_150); item = new JCheckBoxMenuItem(action); zoomMenu.add(item); zoomingGroup.add(item); action = controller.getAction(ImViewerControl.ZOOM_175); item = new JCheckBoxMenuItem(action); zoomMenu.add(item); zoomingGroup.add(item); action = controller.getAction(ImViewerControl.ZOOM_200); item = new JCheckBoxMenuItem(action); zoomMenu.add(item); zoomingGroup.add(item); action = controller.getAction(ImViewerControl.ZOOM_225); item = new JCheckBoxMenuItem(action); zoomMenu.add(item); zoomingGroup.add(item); action = controller.getAction(ImViewerControl.ZOOM_250); item = new JCheckBoxMenuItem(action); zoomMenu.add(item); zoomingGroup.add(item); action = controller.getAction(ImViewerControl.ZOOM_275); item = new JCheckBoxMenuItem(action); zoomMenu.add(item); zoomingGroup.add(item); action = controller.getAction(ImViewerControl.ZOOM_300); item = new JCheckBoxMenuItem(action); zoomMenu.add(item); zoomingGroup.add(item); //} action = controller.getAction(ImViewerControl.ZOOM_FIT_TO_WINDOW); item = new JCheckBoxMenuItem(action); zoomMenu.add(item); zoomingGroup.add(item); int index = ZoomAction.DEFAULT_ZOOM_INDEX; double factor = ZoomAction.DEFAULT_ZOOM_FACTOR; if (pref != null) { if (pref.isFieldSelected(ViewerPreferences.ZOOM_FACTOR)) { index = pref.getZoomIndex(); factor = ZoomAction.getZoomFactor(index); } } setZoomFactor(factor, index); item = new JCheckBoxMenuItem(controller.getAction(ImViewerControl.ZOOM_GRID_25)); zoomGridMenu.add(item); zoomingGridGroup.add(item); item = new JCheckBoxMenuItem(controller.getAction(ImViewerControl.ZOOM_GRID_50)); zoomGridMenu.add(item); zoomingGridGroup.add(item); item = new JCheckBoxMenuItem(controller.getAction(ImViewerControl.ZOOM_GRID_75)); zoomGridMenu.add(item); zoomingGridGroup.add(item); item = new JCheckBoxMenuItem(controller.getAction(ImViewerControl.ZOOM_GRID_100)); zoomGridMenu.add(item); zoomingGridGroup.add(item); setGridMagnificationFactor(ZoomGridAction.DEFAULT_ZOOM_FACTOR); return zoomMenu; } /** * Helper method to create the show View menu. * * @return See above. */ private JMenu createShowViewMenu() { JMenu menu = new JMenu("View"); menu.setMnemonic(KeyEvent.VK_S); JMenuItem item = new JMenuItem(controller.getAction(ImViewerControl.TAB_GRID)); if (model.isBigImage() || (model.isLifetimeImage() && model.getModuloT() == null)) item.setEnabled(false); else item.setEnabled(model.getMaxC() > 1); menu.add(item); item = new JMenuItem(controller.getAction(ImViewerControl.TAB_PROJECTION)); item.setEnabled(model.getMaxZ() > 1 && !model.isBigImage()); menu.add(item); return menu; } /** Builds and lays out the GUI. */ private void buildGUI() { Browser browser = model.getBrowser(); int sizeX = model.getTiledImageSizeX(); int sizeY = model.getTiledImageSizeY(); browser.setComponentsSize(sizeX, sizeY); tabs = new ClosableTabbedPane(JTabbedPane.TOP, JTabbedPane.WRAP_TAB_LAYOUT); tabs.setAlignmentX(LEFT_ALIGNMENT); viewPanel = new ClosableTabbedPaneComponent(ImViewer.VIEW_INDEX, browser.getTitle(), browser.getIcon(), ""); viewPanel.setClosable(false); double[][] tl = { { TableLayout.PREFERRED, TableLayout.FILL }, { TableLayout.FILL, TableLayout.PREFERRED, TableLayout.PREFERRED } }; viewPanel.setLayout(new TableLayout(tl)); viewPanel.add(controlPane, "0, 0"); viewPanel.add(browser.getUI(), "1, 0"); viewPanel.add(controlPane.getTimeSliderPane(ImViewer.VIEW_INDEX), "1, 1"); if (model.isLifetimeImage()) { viewPanel.add(controlPane.getLifetimeSliderPane(ImViewer.VIEW_INDEX), "1, 2"); } tabbedIconHeight = browser.getIcon().getIconHeight() + ICON_EXTRA; tabs.insertTab(browser.getTitle(), browser.getIcon(), viewPanel, "", ImViewer.VIEW_INDEX); gridViewPanel = new ClosableTabbedPaneComponent(ImViewer.GRID_INDEX, browser.getGridViewTitle(), browser.getGridViewIcon(), ""); gridViewPanel.setLayout(new TableLayout(tl)); gridViewPanel.add(controlPane.buildGridComponent(), "0, 0"); gridViewPanel.add(browser.getGridView(), "1, 0"); gridViewPanel.add(controlPane.getTimeSliderPane(ImViewer.GRID_INDEX), "1, 1"); if (model.isLifetimeImage()) { gridViewPanel.add(controlPane.getLifetimeSliderPane(ImViewer.GRID_INDEX), "1, 2"); } if (model.allowSplitView() && !model.isBigImage()) { tabs.insertTab(browser.getGridViewTitle(), browser.getGridViewIcon(), gridViewPanel, "", ImViewer.GRID_INDEX); } double[][] tl2 = { { TableLayout.PREFERRED, TableLayout.FILL }, { TableLayout.PREFERRED, TableLayout.FILL, TableLayout.PREFERRED } }; projectionViewPanel = new ClosableTabbedPaneComponent(ImViewer.PROJECTION_INDEX, browser.getProjectionViewTitle(), browser.getProjectionViewIcon(), ""); projectionViewPanel.setLayout(new TableLayout(tl2)); projectionViewPanel.add(controlPane.buildProjectionToolBar(), "0, 0, 1, 0"); projectionViewPanel.add(controlPane.buildProjectionComponent(), "0, 1"); projectionViewPanel.add(browser.getProjectionView(), "1, 1"); projectionViewPanel.add(controlPane.getTimeSliderPane(ImViewer.PROJECTION_INDEX), "1, 2"); if (model.getMaxZ() > 0 && !model.isBigImage()) { tabs.insertTab(browser.getProjectionViewTitle(), browser.getProjectionViewIcon(), projectionViewPanel, "", ImViewer.PROJECTION_INDEX); } tabs.addChangeListener(controller); //mainComponent = tabs; rendererSplit.setLeftComponent(tabs); mainComponent = rendererSplit; Container container = getContentPane(); container.setLayout(new BorderLayout(0, 0)); container.add(toolBar, BorderLayout.NORTH); container.add(mainComponent, BorderLayout.CENTER); container.add(statusBar, BorderLayout.SOUTH); //attach listener to the frame border boundsAdapter = new HierarchyBoundsAdapter() { /** * Stores the size of the tab pane when the frame is resized. * @see HierarchyBoundsListener#ancestorResized(HierarchyEvent) */ public void ancestorResized(HierarchyEvent e) { if (tabs != null) restoreSize = tabs.getSize(); } }; container.addHierarchyBoundsListener(boundsAdapter); //restoreSize = new Dimension(0, 0); //layoutComponents(false); } /** * Returns the size this widget should have to display the image * before adding the split panes. * * @param w The width of the component added to the center of the * container. * @param h The height of the component added to the center of the * container. * @return See above. */ private Dimension getIdealSize(int w, int h) { Dimension sz = new Dimension(); Dimension tbDim = toolBar.getPreferredSize(); Dimension statusDim = statusBar.getPreferredSize(); Insets frameInsets = getInsets(); Insets stInsets = statusBar.getInsets(); sz.width = w + frameInsets.left + frameInsets.right + stInsets.left + stInsets.right + rendererSplit.getDividerSize(); sz.height = h + tbDim.height + statusDim.height + frameInsets.top + frameInsets.bottom + tabbedIconHeight + stInsets.top + stInsets.bottom; return sz; } /** * Adds a left and right component to the specified pane. * * @param pane The split pane to add the components to. * @param left The left component to add. * @param right The right component to add. */ private void addComponents(JSplitPane pane, JComponent left, JComponent right) { Component c = pane.getLeftComponent(); if (c != null) pane.remove(c); c = pane.getRightComponent(); if (c != null) pane.remove(c); pane.setLeftComponent(left); pane.setRightComponent(right); } /** * Lays out the components composing main panel. * * @param fromPreferences Pass <code>true</code> to indicate that the * method is invoked while setting the user * preferences, <code>false</code> otherwise. */ private void layoutComponents(boolean fromPreferences) { //initSplitPanes(); Dimension d; int diff; Container container = getContentPane(); container.removeHierarchyBoundsListener(boundsAdapter); int width = 0, height = 0; JComponent rightComponent; //int divider = 0; int vExtra = 2; int addition; switch (displayMode) { case RENDERER: rightComponent = model.getMetadataViewer().getEditorUI(); rendererSplit.setRightComponent(rightComponent); if (restoreSize == null) { rendererSplit.setResizeWeight(1.0); return; } d = model.getMetadataViewer().getIdealRendererSize(); rightComponent.setMinimumSize(d); tabs.setMinimumSize(restoreSize); height = restoreSize.height; diff = d.height - restoreSize.height; if (diff > 0) height += diff; else height += vExtra; addition = rendererSplit.getDividerSize() + 2 * (refInsets.left + refInsets.right); width = restoreSize.width + d.width; width += 4 * addition; break; case HISTORY: container.remove(mainComponent); historyUI.doGridLayout(); addComponents(historySplit, tabs, historyUI); mainComponent = historySplit; container.add(mainComponent, BorderLayout.CENTER); container.validate(); container.repaint(); height = restoreSize.height; width = restoreSize.width; d = historyUI.getIdealSize(); addition = historySplit.getDividerSize() + 2 * (refInsets.top + refInsets.bottom); height += d.height; historySplit.setResizeWeight(0.49); height += addition; break; case HISTORY_AND_RENDERER: historySplit.setResizeWeight(0.49); container.remove(mainComponent); historyUI.doGridLayout(); rightComponent = model.getMetadataViewer().getEditorUI(); addComponents(rendererSplit, tabs, rightComponent); addComponents(historySplit, rendererSplit, historyUI); mainComponent = historySplit; container.add(mainComponent, BorderLayout.CENTER); container.validate(); container.repaint(); d = model.getMetadataViewer().getIdealRendererSize(); height = restoreSize.height; diff = d.height - restoreSize.height; if (diff > 0) height += diff; else height += vExtra; addition = rendererSplit.getDividerSize() + 2 * (refInsets.left + refInsets.right); width = restoreSize.width + d.width; width += 4 * addition; d = historyUI.getPreferredSize(); addition = historySplit.getDividerSize() + 2 * (refInsets.top + refInsets.bottom); height += d.height; height += addition; break; case NEUTRAL: rightComponent = model.getMetadataViewer().getEditorUI(); rendererSplit.remove(rightComponent); if (restoreSize == null) return; width = restoreSize.width; height = restoreSize.height; break; default: } //rendererSplit.setDividerLocation(-1); //rendererSplit.setResizeWeight(1.0); //historySplit.setDividerLocation(-1); d = getIdealSize(width, height); /* Need to review that code. * Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); int w = (int) (screen.width*SCREEN_RATIO); int h = (int) (screen.height*SCREEN_RATIO); if (d.width > w || d.height > h) { setSize(width, height); } else setSize(d); */ setSize(d); setPreferredSize(d); pack(); container.addHierarchyBoundsListener(boundsAdapter); } /** Packs the window and resizes it if the screen is too small. */ private void packWindow() { pack(); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension size = getSize(); int width = (int) (screenSize.width * SCREEN_RATIO); int height = (int) (screenSize.height * SCREEN_RATIO); int w = size.width; int h = size.height; boolean reset = false; if (w > width) { reset = true; } if (h > height) { reset = true; h = height; } if (reset) { setSize(w, h); } } /** * Removes all the elements from the passed menu and button group. * * @param group The group to handle. * @param menu The menu to handle. */ private void clearZoomMenu(ButtonGroup group, JMenu menu) { menu.removeAll(); for (Enumeration<AbstractButton> e = group.getElements(); e.hasMoreElements();) group.remove(e.nextElement()); } /** * Creates a new instance. * The {@link #initialize(ImViewerControl, ImViewerModel) initialize} * method should be called straight after to link this View * to the Controller. * * @param title The window title. */ ImViewerUI(String title) { super(title); loadingWindow = new LoadingWindow(this); loadingWindow.setTitle("Opening Image Viewer..."); loadingWindow.setModal(false); defaultIndex = UnitBarSizeAction.DEFAULT_UNIT_INDEX; displayMode = NEUTRAL; bigImageMagnification = 1.0; } /** * Links this View to its Controller and Model. * * @param controller Reference to the Control. * Mustn't be <code>null</code>. * @param model Reference to the Model. * Mustn't be <code>null</code>. */ void initialize(ImViewerControl controller, ImViewerModel model) { if (controller == null) throw new NullPointerException("No control."); if (model == null) throw new NullPointerException("No model."); this.controller = controller; this.model = model; toolBar = new ToolBar(this, controller); controlPane = new ControlPane(controller, model, this); statusBar = new StatusBar(model, this); initSplitPanes(); refInsets = rendererSplit.getInsets(); planes = new HashMap<Integer, PlaneInfoComponent>(); ImageIcon icon = IconManager.getInstance().getImageIcon(IconManager.VIEWER); if (icon != null) setIconImage(icon.getImage()); setName("image viewer window"); } /** * This method should be called straight after the metadata and the * rendering settings are loaded. */ void buildComponents() { //Retrieve the preferences. ViewerPreferences pref = ImViewerFactory.getPreferences(); setJMenuBar(createMenuBar(pref)); toolBar.buildComponent(); controlPane.buildComponent(); buildGUI(); List<ChannelData> data = model.getChannelData(); ChannelData d; int index; PlaneInfoComponent comp; Iterator<ChannelData> i = data.iterator(); while (i.hasNext()) { d = i.next(); index = d.getIndex(); comp = new PlaneInfoComponent(model.getChannelColor(index)); comp.addPropertyChangeListener(PlaneInfoComponent.PLANE_INFO_PROPERTY, controller); planes.put(index, comp); } } /** * Updates UI components when a zooming factor is selected. * * @param factor The magnification factor. * @param zoomIndex The index of the selected zoomFactor. */ void setZoomFactor(double factor, int zoomIndex) { setMagnificationStatus(factor, zoomIndex); JCheckBoxMenuItem b; Enumeration e; Action a; if (zoomingGroup == null) return; for (e = zoomingGroup.getElements(); e.hasMoreElements();) { b = (JCheckBoxMenuItem) e.nextElement(); a = b.getAction(); if (a instanceof ZoomAction) { b.removeActionListener(a); b.setSelected(((ZoomAction) a).getIndex() == zoomIndex); b.setAction(a); } } controlPane.setZoomFactor(zoomIndex); } /** * Sets the magnification value in the status bar depending on the * selected tabbedPane. * * @param factor The value to set. * @param zoomIndex The index of the selected zoomFactor. */ void setMagnificationStatus(double factor, int zoomIndex) { if (statusBar == null) return; if (factor != ZoomAction.ZOOM_FIT_FACTOR) statusBar.setRigthStatus(Math.round(factor * model.getOriginalRatio() * 100) + "%"); else statusBar.setRigthStatus(ZoomAction.ZOOM_FIT_NAME); if (model.isBigImage()) { ResolutionLevel level = model.getResolutionDescription(); double f = UIUtilities.roundTwoDecimals(level.getRatio() * 100); bigImageMagnification = level.getRatio(); statusBar.setRigthStatus(f + "%"); } } /** * Returns the magnification factor for big images. * * @return See above. */ double getBigImageMagnificationFactor() { if (!model.isBigImage()) return 1.0; return bigImageMagnification; } /** * Returns the index associated to the zoom factor. * * @return See above. */ int getZoomIndex() { if (zoomingGroup == null) return ZoomAction.ZOOM_FIT_TO_WINDOW; JCheckBoxMenuItem b; Enumeration e; Action a; for (e = zoomingGroup.getElements(); e.hasMoreElements();) { b = (JCheckBoxMenuItem) e.nextElement(); a = b.getAction(); if (b.isSelected()) return ((ZoomAction) a).getIndex(); } return ZoomAction.ZOOM_FIT_TO_WINDOW; } /** * Updates UI components when a new color model is selected. * * @param key The index of the color model. */ void setColorModel(int key) { controlPane.setColorModel(); AbstractButton b; Action a; Enumeration<AbstractButton> e; for (e = colorModelGroup.getElements(); e.hasMoreElements();) { b = e.nextElement(); a = b.getAction(); if (a instanceof ColorModelAction) { b.removeActionListener(a); b.setSelected(((ColorModelAction) a).getIndex() == key); b.setAction(a); } } } /** * Updates UI components when a new z-section is selected. * * @param z The selected z-section. */ void setZSection(int z) { controlPane.setZSection(z); } /** * Updates UI components when a new timepoint is selected. * * @param t The selected timepoint. */ void setTimepoint(int t) { controlPane.setTimepoint(t); } /** * Updates UI components when a new bin is selected. * * @param bin The selected bin. */ void setBin(int t) { controlPane.setBin(t); } /** * Returns the {@link #loadingWindow}. * * @return See above. */ LoadingWindow getLoadingWindow() { return loadingWindow; } /** * Reacts to {@link ImViewer} change events. * * @param b Pass <code>true</code> to enable the UI components, * <code>false</code> otherwise. */ void onStateChange(boolean b) { model.getBrowser().onStateChange(b); if (tabs != null) { tabs.setEnabled(b); enableSliders(b); controlPane.onStateChange(b); toolBar.onStateChange(b); } } /** Sets the default text of the status bar. */ void setLeftStatus() { int n; int max = model.getMaxZ(); double d = model.getPixelsSizeZ(); UnitsObject o; String units; StringBuffer buffer = new StringBuffer(); if (model.getTabbedIndex() == ImViewer.PROJECTION_INDEX) { n = getProjectionStartZ(); int m = getProjectionEndZ(); buffer.append("Z range:" + (n + 1)); buffer.append("-" + (getProjectionEndZ() + 1)); if (d > 0 && max > 0) { o = EditorUtil.transformSize(n * d); buffer.append(" (" + UIUtilities.roundTwoDecimals(o.getValue())); buffer.append("-"); o = EditorUtil.transformSize(m * d); units = o.getUnits(); buffer.append(UIUtilities.roundTwoDecimals(o.getValue())); buffer.append(units + ")"); } buffer.append("/" + (model.getMaxZ() + 1)); controlPane.setRangeSliderToolTip(n, m); } else { n = model.getDefaultZ(); buffer.append("Z=" + (n + 1)); if (d > 0 && max > 0) { o = EditorUtil.transformSize(n * d); units = o.getUnits(); buffer.append(" (" + UIUtilities.roundTwoDecimals(o.getValue())); buffer.append(units + ")"); } buffer.append("/" + (model.getMaxZ() + 1)); } buffer.append(" T=" + (model.getRealSelectedT() + 1) + "/" + model.getRealT()); if (model.isLifetimeImage()) { int bin = model.getSelectedBin(); buffer.append(" "); buffer.append(EditorUtil.SMALL_T_VARIABLE + "=" + (bin + 1)); buffer.append("/" + (model.getMaxLifetimeBin())); //format the result ModuloInfo info = model.getModuloT(); if (info != null) { buffer.append(" ("); buffer.append(UIUtilities.roundTwoDecimals(info.getRealValue(bin))); buffer.append(info.getUnit() + ")"); } } setLeftStatus(buffer.toString()); } /** * Updates status bar. * * @param description The text to display. */ void setLeftStatus(String description) { statusBar.setLeftStatus(description); } /** * Displays the plane information. * */ void setPlaneInfoStatus() { if (model.getTabbedIndex() == ImViewer.PROJECTION_INDEX) { statusBar.setCenterStatus(new JLabel()); return; } List<Integer> indexes = model.getActiveChannels(); if (CollectionUtils.isEmpty(indexes)) { statusBar.setCenterStatus(new JLabel()); return; } int z = model.getDefaultZ(); int t = model.getRealSelectedT(); PlaneInfo info; String s, toolTipText; Map<Integer, Color> colors = model.getChannelsColorMap(); JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); Map<String, Object> details; List<String> tips; PlaneInfoComponent comp; List<ChannelData> metadata = model.getChannelData(); Iterator<ChannelData> c = metadata.iterator(); int index; List<String> notSet; while (c.hasNext()) { index = c.next().getIndex(); s = ""; toolTipText = ""; tips = new ArrayList<String>(); info = model.getPlane(z, index, t); comp = planes.get(index); if (info != null) { details = EditorUtil.transformPlaneInfo(info); notSet = (List<String>) details.get(EditorUtil.NOT_SET); comp.setColor(colors.get(index)); if (!notSet.contains(EditorUtil.DELTA_T)) { s += EditorUtil.formatTimeInSeconds((Double) details.get(EditorUtil.DELTA_T)); } if (!notSet.contains(EditorUtil.EXPOSURE_TIME)) { toolTipText += EditorUtil.EXPOSURE_TIME + ": "; toolTipText += details.get(EditorUtil.EXPOSURE_TIME); toolTipText += EditorUtil.TIME_UNIT; tips.add(toolTipText); } toolTipText = ""; toolTipText += "Stage coordinates: "; if (!notSet.contains(EditorUtil.POSITION_X)) toolTipText += "x=" + details.get(EditorUtil.POSITION_X) + " "; if (!notSet.contains(EditorUtil.POSITION_Y)) toolTipText += "y=" + details.get(EditorUtil.POSITION_Y) + " "; if (!notSet.contains(EditorUtil.POSITION_Z)) toolTipText += "z=" + details.get(EditorUtil.POSITION_Z); tips.add(toolTipText); comp.setToolTipText(UIUtilities.formatToolTipText(tips)); if (StringUtils.isEmpty(s)) s = "0s"; comp.setText(s); panel.add(comp); } } statusBar.setCenterStatus(panel); } /** * Updates the buttons' selection when a new button is selected or * deselected. * * @param index One of the following constants {@link #GRID_ONLY}, * {@link #VIEW_ONLY}, {@link #PROJECTION_ONLY} * and {@link #ALL_VIEW}. */ void setChannelsSelection(int index) { controlPane.setChannelsSelection(index); } /** * Sets the active channels in the grid view. * * @param channels The collection of channel indexes. */ void setChannelsSelection(List channels) { controlPane.setChannelsSelection(channels); } /** * Sets whether or not the tabbed pane is enabled. * * @param enabled Pass <code>true</code> to enable the component, * <code>false</code> otherwise. */ void playChannelMovie(boolean enabled) { tabs.setEnabled(enabled); } /** * Sets the color of the specified channel. * * @param index The channel index. * @param c The color to set. */ void setChannelColor(int index, Color c) { PlaneInfoComponent comp = planes.get(index); if (comp != null) comp.setColor(c); controlPane.setChannelColor(index, c); } /** Resets the defaults. */ void resetDefaults() { controlPane.resetRndSettings(); } /** Resets the UI when switching to a new rendering control. */ void switchRndControl() { controlPane.switchRndControl(); } /** Refreshes the view. */ void refresh() { resetDefaults(); model.refresh(); } /** * Sets the image in the lens to the plane image shown on the screen * depending on the selected tab pane. */ void setLensPlaneImage() { if (lens == null) return; switch (model.getTabbedIndex()) { case ImViewer.VIEW_INDEX: lens.setPlaneImage(model.getOriginalImage()); break; case ImViewer.GRID_INDEX: lens.setPlaneImage(model.getGridImage()); break; case ImViewer.PROJECTION_INDEX: BufferedImage image = model.getProjectedImage(); if (image != null) lens.setPlaneImage(image); } } /** * Creates a zoomed version of the passed image. * * @param image The image to zoom. * @return See above. * @throws Exception */ BufferedImage createZoomedLensImage(BufferedImage image) { if (lens == null) return null; try { return lens.createZoomedImage(image); } catch (Exception e) { return null; } } /** * Returns <code>true</code> if the lens is visible, <code>false</code> * otherwise. * * @return see above. */ boolean isLensVisible() { if (lens != null) return lens.isVisible(); return false; } /** * Returns <code>true</code> if the lens exists, <code>otherwise</code>. * * @return See above */ boolean hasLensImage() { return (lens != null); } /** * Sets the lens's visibility. If the lens hasn't previously created, * we first create the lens. * * @param b Pass <code>true</code> to display the lens, * <code>false</code> otherwise. * @param historyIndex The index of the tab pane. */ void setLensVisible(boolean b, int historyIndex) { boolean firstTime = false; if (lens == null) { if (b) { firstTime = true; lens = new LensComponent(this, ImViewerAgent.hasOpenGLSupport()); lens.setImageName(model.getImageName()); lens.setXYPixelMicron(model.getPixelsSizeX(), model.getPixelsSizeY()); lens.addPropertyChangeListener(LensComponent.LENS_LOCATION_PROPERTY, controller); } else return; } else { Browser browser = model.getBrowser(); JComponent c = lens.getLensUI(); browser.removeComponent(c, ImViewer.VIEW_INDEX); browser.removeComponent(c, ImViewer.GRID_INDEX); browser.removeComponent(c, ImViewer.PROJECTION_INDEX); } if (!b) { lens.setVisible(b); repaint(); return; } //depending on the previous selected tabbed pane, //we reset the location of the lens int maxX = model.getMaxX(); int maxY = model.getMaxY(); float f = 1.0f; //BufferedImage img; int index = model.getTabbedIndex(); JComponent c = lens.getLensUI(); int width = c.getWidth(); int height = c.getHeight(); Point p = lens.getLensLocation(); int lensX = p.x; int lensY = p.y; if (maxX < width || maxY < height) return; if (firstTime) { //firstTimeLensShown = false; int diffX = maxX - width; int diffY = maxY - height; lensX = diffX / 2; lensY = diffY / 2; if (lensX + width > maxX) lensX = diffX; if (lensY + height > maxY) lensY = diffY; } else { switch (historyIndex) { case ImViewer.GRID_INDEX: if (historyIndex != index) { Point point = model.getBrowser().isOnImageInGrid(lens.getLensScaledBounds()); if (point == null) { int diffX = maxX - width; int diffY = maxY - height; lensX = diffX / 2; lensY = diffY / 2; if (lensX + width > maxX) lensX = diffX; if (lensY + height > maxY) lensY = diffY; } else { double r = model.getBrowser().getRatio(); lensX = (int) (point.x / r); lensY = (int) (point.y / r); } } break; case ImViewer.PROJECTION_INDEX: case ImViewer.VIEW_INDEX: if (index == ImViewer.GRID_INDEX) { double r = model.getBrowser().getRatio(); lensX = (int) (lensX * r); lensY = (int) (lensY * r); } } } if (ImViewerAgent.hasOpenGLSupport()) { TextureData image; switch (index) { case ImViewer.VIEW_INDEX: default: f = (float) model.getZoomFactor(); image = model.getImageAsTexture(); //img = model.getOriginalImage(); break; case ImViewer.PROJECTION_INDEX: f = (float) model.getZoomFactor(); image = model.getProjectedImageAsTexture(); //img = model.getProjectedImage(); break; case ImViewer.GRID_INDEX: //img = model.getGridImage(); image = null; } if (image != null) lens.resetLensAsTexture(image, f, lensX, lensY); } else { BufferedImage img; switch (index) { case ImViewer.VIEW_INDEX: default: f = (float) model.getZoomFactor(); img = model.getOriginalImage(); break; case ImViewer.PROJECTION_INDEX: f = (float) model.getZoomFactor(); img = model.getProjectedImage(); break; case ImViewer.GRID_INDEX: img = model.getGridImage(); } if (img != null) lens.resetLens(img, f, lensX, lensY); } model.getBrowser().addComponent(c, index, true); scrollLens(); UIUtilities.setLocationRelativeTo(this, lens.getZoomWindow()); lens.setVisible(b); repaint(); } /** * Returns the <code>zoomedImage</code> from the lens component * or <code>null</code> if the lens is <code>null</code>. * * @return See above. */ BufferedImage getZoomedLensImage() { if (lens == null) return null; return lens.getZoomedImage(); } /** * Sets the lens magnification factor. * * @param factor The value to set. */ void setImageZoomFactor(float factor) { if (lens == null) return; lens.setImageZoomFactor(factor); } /** Hides the lens when the window is iconified. */ void onIconified() { if (lens == null) return; lens.setVisible(false); repaint(); } /** * Creates the menus corresponding to the passed id and brings it on screen. * * @param menuID The id of the menu. One out of the following constants: * {@link ImViewer#COLOR_PICKER_MENU}, * {@link ImViewer#CATEGORY_MENU}. */ void showMenu(int menuID) { showMenu(menuID, source, location); } /** * Creates the menus corresponding to the passed id and brings it on screen. * * @param menuID The id of the menu. One out of the following constants: * {@link ImViewer#COLOR_PICKER_MENU}, * {@link ImViewer#CATEGORY_MENU}. * @param source The component that requested the popup menu. * @param location The point at which to display the menu, relative to the * <code>component</code>'s coordinates. */ void showMenu(int menuID, Component source, Point location) { switch (menuID) { case ImViewer.COLOR_PICKER_MENU: List<ChannelData> data = model.getChannelData(); ChannelData d; JPopupMenu menu = new JPopupMenu(); ChannelColorMenuItem item; Iterator<ChannelData> i = data.iterator(); int index; while (i.hasNext()) { d = i.next(); index = d.getIndex(); item = new ChannelColorMenuItem(d.getChannelLabeling(), model.getChannelColor(index), index); menu.add(item); item.addPropertyChangeListener(controller); } menu.show(source, location.x, location.y); } } /** * Scrolls to display the lens when the user drags the lens. * * @param bounds The lens' bounds. */ void scrollToNode(Rectangle bounds) { if (lens == null) return; if (!lens.isVisible()) return; model.getBrowser().scrollTo(bounds, true); } /** Displays the lens on screen when the image is zoomed. */ void scrollLens() { if (lens == null) return; model.getBrowser().scrollTo(lens.getLensScaledBounds(), false); } /** * Selects the tab pane specified by the passed index. * * @param index The index. */ void selectTabbedPane(int index) { switch (index) { case ImViewer.VIEW_INDEX: case ImViewer.GRID_INDEX: case ImViewer.PROJECTION_INDEX: tabs.setSelectedIndex(index); break; default: return; } } /** * Sets the selected pane. * * @param index The index of the selected tab pane. */ void setSelectedPane(int index) { JMenuBar menuBar = getJMenuBar(); Component[] items = menuBar.getComponents(); Component item; int j = -1; for (int i = 0; i < items.length; i++) { item = items[i]; if (item == zoomGridMenu || item == zoomMenu) j = i; } if (j != -1) menuBar.remove(j); double f; switch (index) { case ImViewer.GRID_INDEX: if (j != -1) menuBar.add(zoomGridMenu, j); f = model.getBrowser().getGridRatio(); setMagnificationStatus(f, ZoomAction.getIndex(f)); break; case ImViewer.PROJECTION_INDEX: case ImViewer.VIEW_INDEX: default: if (j != -1) menuBar.add(zoomMenu, j); f = model.getZoomFactor(); setMagnificationStatus(f, ZoomAction.getIndex(f)); } int oldIndex = model.getTabbedIndex(); model.setTabbedIndex(index); tabs.removeChangeListener(controller); int n = tabs.getTabCount(); Component c; int tabbedIndex; for (int i = 0; i < n; i++) { c = tabs.getComponentAt(i); if (c instanceof ClosableTabbedPaneComponent) { tabbedIndex = ((ClosableTabbedPaneComponent) c).getIndex(); if (tabbedIndex == index) tabs.setSelectedIndex(i); } } tabs.addChangeListener(controller); setLeftStatus(); setPlaneInfoStatus(); model.getBrowser().setSelectedPane(index); setLensVisible(isLensVisible(), oldIndex); maximizeWindow(); } /** * Returns the color model of the pane currently selected. * * @return See above. */ String getSelectedPaneColorModel() { return controlPane.getSelectedPaneColorModel(); } /** Centers the image when the user maximized the viewer. */ void maximizeWindow() { JComponent c = model.getBrowser().getUI(); c.setBounds(c.getBounds()); } /** Invokes when the component is resized.*/ void onComponentResized() { model.getBrowser().onComponentResized(); } /** * Sets the <code>enable</code> flag of the slider used to select * the current z-section and timepoint. * * @param enable Pass <code>true</code> to enable the sliders, * <code>false</code> otherwise. */ void enableSliders(boolean enable) { if (model.isPlayingMovie()) { switch (controller.getMoviePlayer().getMovieIndex()) { case MoviePlayerDialog.ACROSS_Z: controlPane.enableZSliders(false); controlPane.enableTSliders(true); break; case MoviePlayerDialog.ACROSS_T: controlPane.enableZSliders(true); controlPane.enableTSliders(false); break; case MoviePlayerDialog.ACROSS_ZT: controlPane.enableSliders(false); break; } } else { controlPane.enableSliders(enable); } } /** * Sets the specified channel to active. * * @param index The channel's index. * @param uiIndex One of the following constants * {@link ImViewerUI#GRID_ONLY} and * {@link ImViewerUI#ALL_VIEW}. */ void setChannelActive(int index, int uiIndex) { controlPane.setChannelActive(index, uiIndex); } /** * Returns the collection of the active channels in the grid view. * * @return See above. */ List getActiveChannelsInGrid() { return controlPane.getActiveChannelsInGrid(); } /** * Adds a new item to the history. * * @param node The node to add. */ void addHistoryItem(HistoryItem node) { if (!isHistoryShown() || historyUI == null) return; historyUI.addHistoryItem(node); } /** * Returns <code>true</code> if the renderer is shown, <code>false</code> * otherwise. * * @return See above. */ boolean isRendererShown() { switch (displayMode) { case RENDERER: case HISTORY_AND_RENDERER: return true; default: return false; } } /** * Returns <code>true</code> if the history is shown, <code>false</code> * otherwise. * * @return See above. */ boolean isHistoryShown() { switch (displayMode) { case HISTORY: case HISTORY_AND_RENDERER: return true; default: return false; } } /** * Returns the {@link #restoreSize}. * * @return See above. */ Dimension geRestoreSize() { return restoreSize; } /** * Shows or hides the local history. * * @param b Pass <code>true</code> to display the history, * <code>false</code> otherwise. */ void showHistory(boolean b) { boolean rnd = isRendererShown(); if (b) { if (rnd) displayMode = HISTORY_AND_RENDERER; else displayMode = HISTORY; } else { if (rnd) displayMode = RENDERER; else displayMode = NEUTRAL; } historyItem.setSelected(isHistoryShown()); toolBar.displayHistory(); layoutComponents(false); } /** * Shows or hides the renderer. * * @param fromPreferences Pass <code>true</code> to indicate that the * method is invoked while setting the user * preferences, <code>false</code> otherwise. * @param index The index of the tab to select. */ void showRenderer(boolean fromPreferences, int index) { boolean show = !isRendererShown(); boolean b = isHistoryShown(); if (show) { if (b) displayMode = HISTORY_AND_RENDERER; else displayMode = RENDERER; } else { if (b) displayMode = HISTORY; else displayMode = NEUTRAL; } metadataItem.setSelected(isRendererShown()); rndItem.setSelected(isRendererShown()); toolBar.displayRenderer(); layoutComponents(fromPreferences); if (show) { int v = MetadataViewer.RENDERER_TAB; if (index == ImViewer.METADATA_INDEX) v = MetadataViewer.GENERAL_TAB; model.getMetadataViewer().setSelectedTab(v); } } /** * Sets the compression flag. * * @param compressionLevel One of the compression constants defined * by the model. */ void setCompressionLevel(int compressionLevel) { int oldCompression = convertCompressionLevel(); switch (compressionLevel) { case ToolBar.UNCOMPRESSED: model.setCompressionLevel(ImViewer.UNCOMPRESSED); if (lens != null) lens.resetDataBuffered(); break; case ToolBar.MEDIUM: if (lens != null && oldCompression == ToolBar.UNCOMPRESSED) lens.resetDataBuffered(); model.setCompressionLevel(ImViewer.MEDIUM); break; case ToolBar.LOW: if (lens != null && oldCompression == ToolBar.UNCOMPRESSED) lens.resetDataBuffered(); model.setCompressionLevel(ImViewer.LOW); } } /** * Returns the UI index corresponding to the current compression level. * * @return See above. */ int convertCompressionLevel() { return convertCompressionLevel(model.getCompressionLevel()); } /** * Returns the UI index corresponding to the current compression level. * * @param level The value to check. * @return See above. */ int convertCompressionLevel(int level) { switch (level) { default: case ImViewer.UNCOMPRESSED: return ToolBar.UNCOMPRESSED; case ImViewer.MEDIUM: return ToolBar.MEDIUM; case ImViewer.LOW: return ToolBar.LOW; } } /** * Returns the UI index of the currently selected compression level. * * @return See above. */ int getUICompressionLevel() { return toolBar.getUICompressionLevel(); } /** * Returns <code>true</code> if the image is compressed, * <code>false</code> otherwise. * * @return See above. */ boolean isImageCompressed() { return model.isImageCompressed(); } /** * Returns the color of the image's background. * * @return See above. */ Color getBackgroundColor() { ColorCheckBoxMenuItem b; Enumeration e; for (e = bgColorGroup.getElements(); e.hasMoreElements();) { b = (ColorCheckBoxMenuItem) e.nextElement(); if (b.isSelected()) return b.getColor(); } return null; } /** * Returns the index of the scale bar. * * @return See above. */ int getScaleBarIndex() { if (scaleBarGroup == null) return -1; JCheckBoxMenuItem item; Enumeration e; for (e = scaleBarGroup.getElements(); e.hasMoreElements();) { item = (JCheckBoxMenuItem) e.nextElement(); if (item.isSelected()) return ((UnitBarSizeAction) item.getAction()).getIndex(); } return -1; } /** Shows the list of users who viewed the image. */ void showUsersList() { if (usersMenu == null) { usersMenu = new UsersPopupMenu(model); usersMenu.addPropertyChangeListener(controller); } usersMenu.show(source, location.x, location.y); source = null; location = null; } /** * Sets the location and the source where to pop up the menu. * * @param source The source to set. * @param location The location to set. */ void setLocationAndSource(Component source, Point location) { this.source = source; this.location = location; } /** * Sets the magnification for the grid view. * * @param factor The value to set. */ void setGridMagnificationFactor(double factor) { if (model.getTabbedIndex() == ImViewer.GRID_INDEX) setMagnificationStatus(factor, ZoomAction.getIndex(factor)); JCheckBoxMenuItem b; Enumeration e; Action a; int zoomIndex = ZoomGridAction.getIndex(factor); for (e = zoomingGridGroup.getElements(); e.hasMoreElements();) { b = (JCheckBoxMenuItem) e.nextElement(); a = b.getAction(); if (a instanceof ZoomGridAction) { b.removeActionListener(a); b.setSelected(((ZoomGridAction) a).getIndex() == zoomIndex); b.setAction(a); } } controlPane.setGridMagnificationFactor((int) (factor * 10)); } /** * Adds the component specified by the passed index to the display * * @param index The index identifying the UI component. */ void showView(int index) { switch (index) { case ImViewer.VIEW_INDEX: tabs.insertClosableComponent(viewPanel); break; case ImViewer.GRID_INDEX: tabs.insertClosableComponent(gridViewPanel); break; case ImViewer.PROJECTION_INDEX: tabs.insertClosableComponent(projectionViewPanel); break; } tabs.validate(); tabs.repaint(); restoreSize = tabs.getSize(); } /** * Returns the id of the currently selected pixels. * * @return See above. */ long getPixelsID() { return model.getPixelsID(); } /** * Returns <code>true</code> if there is some rendering settings to save, * <code>false</code> otherwise. * * @return See above. */ boolean hasSettingsToPaste() { return model.hasRndToPaste(); } /** * Sets the {@link #pasteButton} enable. * * @param b Pass <code>true</code> to enable the button, <code>false</code> * otherwise. */ void enablePasteButton(boolean b) { toolBar.enablePasteButton(b); } /** * Shows the plane information. * * @param show Pass <code>true</code> to show the dialog, * <code>false</code> to hide it. * @param comp The component to show. */ void showPlaneInfoDetails(PlaneInfoComponent comp) { if (comp == null) return; if (channelDialog != null) { JComponent c = channelDialog.getCanvas(); channelDialog.closeWindow(); hideAnimation(); channelDialog = null; if (c == comp.getContent()) return; } if (infoDialog != null) { infoDialog.closeWindow(); hideAnimation(); infoDialog = null; } channelDialog = new TinyDialog(this, comp.getContent(), TinyDialog.CLOSE_ONLY); channelDialog.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (TinyDialog.CLOSED_PROPERTY.equals(evt.getPropertyName())) { channelDialog.closeWindow(); hideAnimation(); channelDialog = null; } } }); channelDialog.pack(); Point p; JPanel glass = (JPanel) getGlassPane(); if (glass.getLayout() == null) { Dimension d = channelDialog.getPreferredSize(); d = new Dimension(d.width + 20, d.height); channelDialog.setSize(d); channelDialog.setPreferredSize(d); p = new Point(0, statusBar.getPreferredSize().height); } else { p = new Point(0, 2 * statusBar.getPreferredSize().height); } //setCloseAfter(true); showJDialogAsSheet(channelDialog, p, UP_MIDDLE); } /** * Displays information about the image. * * @param comp */ void showImageInfo(JComponent comp) { if (comp == null) return; if (infoDialog != null) { infoDialog.closeWindow(); hideAnimation(); infoDialog = null; return; } if (channelDialog != null) { channelDialog.closeWindow(); hideAnimation(); channelDialog = null; } infoDialog = new TinyDialog(this, comp, TinyDialog.CLOSE_ONLY); infoDialog.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (TinyDialog.CLOSED_PROPERTY.equals(evt.getPropertyName())) { infoDialog.closeWindow(); hideAnimation(); infoDialog = null; } } }); infoDialog.pack(); Point p; JPanel glass = (JPanel) getGlassPane(); if (glass.getLayout() == null) { Dimension d = infoDialog.getPreferredSize(); d = new Dimension(d.width, d.height + 20); infoDialog.setSize(d); infoDialog.setPreferredSize(d); p = new Point(0, statusBar.getPreferredSize().height); } else { p = new Point(0, 2 * statusBar.getPreferredSize().height); } //setCloseAfter(true); showJDialogAsSheet(infoDialog, p, UP_LEFT); } /** * Returns the maximum number of z-sections. * * @return See above. */ int getMaxZ() { return model.getMaxZ(); } /** * Returns the index of the selected tab. * * @return See above. */ int getTabbedIndex() { return model.getTabbedIndex(); } /** * Returns the lower bound of the z-section to project. * * @return See above. */ int getProjectionStartZ() { return controlPane.getProjectionStartZ(); } /** * Returns the lower bound of the z-section to project. * * @return See above. */ int getProjectionEndZ() { return controlPane.getProjectionEndZ(); } /** * Returns the stepping used for the projection. * * @return See above. */ int getProjectionStepping() { return controlPane.getProjectionStepping(); } /** * Returns the type of projection. * * @return See above. */ int getProjectionType() { return controlPane.getProjectionType(); } /** * Returns a textual version of the type of projection. * * @return See above. */ String getProjectionTypeName() { return controlPane.getProjectionTypeName(); } /** * Sets to <code>true</code> if loading data, to <code>false</code> * otherwise. * * @param busy Pass <code>true</code> while loading data, * <code>false</code> otherwise. */ void setStatus(boolean busy) { toolBar.setStatus(busy); } /** Clears the history. */ void clearHistory() { if (historyUI != null) historyUI.clearHistory(); } /** * Returns the last projection parameters. * * @return See above. */ ProjectionParam getLastProjRef() { return model.getLastProjRef(); } /** * Creates an history item. * * @param ref The projection ref or <code>null</code>. */ void createHistoryItem(ProjectionParam ref) { /* 28/02 Back for Beta 4.1 if (model.isPlayingChannelMovie()) return; String title = null; if (model.getHistory() == null) title = "Initial "+ImViewer.TITLE_VIEW_INDEX; HistoryItem node = model.createHistoryItem(); if (node == null) return; if (title != null) node.setTitle(title); node.setProjectionRef(ref); node.setDefaultT(model.getDefaultT()); node.addPropertyChangeListener(controller); //add Listener to node. if (nodeListener == null) { nodeListener = new MouseAdapter() { public void mousePressed(MouseEvent evt) { HistoryItem item = findParentDisplay(evt.getSource()); try { if (item.getIndex() == ImViewer.PROJECTION_INDEX) { model.setLastProjectionRef( item.getProjectionRef()); model.setLastProjectionTime(item.getDefaultT()); } setCursor(Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR)); RndProxyDef def = item.getRndSettings(); model.resetMappingSettings(def, true); setCursor(Cursor.getPredefinedCursor( Cursor.DEFAULT_CURSOR)); resetDefaults(); showView(item.getIndex()); controller.renderXYPlane(); model.setLastRndDef(def); } catch (Exception e) {} } }; } node.addMouseListenerToComponents(nodeListener); addHistoryItem(node); */ } /** * Replaces the component in the display either icon or busy label * depending on the passed parameter. * * @param b Pass <code>true</code> to indicate the creation, * <code>false</code> to indicate that the creation is done. */ void setMeasurementLaunchingStatus(boolean b) { Action a = controller.getAction(ImViewerControl.MEASUREMENT_TOOL); a.setEnabled(!b); toolBar.setMeasurementLaunchingStatus(b); } /** * Updates the scale bar menu. * * @param index The selected index. */ void setDefaultScaleBarMenu(int index) { defaultIndex = index; } /** * Shows or hides a busy label indicating the on-going creation of the * grid image. * * @param busy Pass <code>true</code> to indicate the on-going creation, * <code>false</code> when it is finished. */ void createGridImage(boolean busy) { controlPane.createGridImage(busy); } /** * Returns the parent of the image or <code>null</code> * if no context specified. * * @return See above. */ DataObject getParentObject() { return model.getParent(); } /** * Returns the image to view. * * @return See above. */ ImageData getImage() { return model.getImage(); } /** * Returns the ID of the viewed image. * * @return See above. */ long getImageID() { return model.getImageID(); } /** * Returns <code>true</code> if the passed object is one of the * channel buttons, <code>false</code> otherwise. * * @param source The object to handle. * @return See above. */ boolean isSourceDisplayed(Object source) { return controlPane.isSourceDisplayed(source); } /** * Returns <code>true</code> if the viewer should be opened in a * separate window, <code>false</code> otherwise. * The default value is <code>true</code>. * * @return See above. */ boolean isSeparateWindow() { return model.isSeparateWindow(); } /** Builds the UI to handle overlays. */ void buildOverlays() { controlPane.buildOverlays(); } /** * Renders the image with the overlays or not. * * @param index The index of the selected channel. * @param selected Pass <code>true</code> to turn the overlay on, * <code>false</code> to turn it off. */ void renderOverlays(int index, boolean selected) { controlPane.renderOverlays(index, selected); } /** * Returns <code>true</code> if the overlays are turned on, * <code>false</code> otherwise. * * @return See above. */ boolean isOverlayActive() { return controlPane.isOverlayActive(); } /** * Returns the selected overlays if displayed otherwise returns * <code>null</code>. * * @return See above. */ Map<Long, Integer> getSelectedOverlays() { return controlPane.getSelectedOverlays(); } /** Invokes when the color model changes. */ void onColorModelChanged() { controlPane.onColorModelChanged(); } /** * Returns <code>true</code> if it is a large image, * <code>false</code> otherwise. * * @return See above. */ boolean isBigImage() { return model.isBigImage(); } /** * Returns <code>true</code> if it is a large image, * <code>false</code> otherwise. * * @return See above. */ boolean isLargePlane() { return model.isLargePlane(); } /** * Returns the view as a component. * * @return See above. */ JComponent asComponent() { if (component != null) return component; component = new JPanel(); component.setLayout(new BorderLayout(0, 0)); component.add(toolBar, BorderLayout.NORTH); component.add(mainComponent, BorderLayout.CENTER); return component; } /** * Re-attaches the viewer. * This method should only be invoked when the image has been embedded * and detached. */ void rebuild() { if (component == null) return; //component.add(mainComponent, BorderLayout.CENTER); component.add(statusBar, BorderLayout.SOUTH); Container c = getContentPane(); toolBar.setSeparateWindow(); c.setLayout(new BorderLayout(0, 0)); c.add(component, BorderLayout.CENTER); } /** Invokes when the rendering control is loaded. */ void onRndLoaded() { clearZoomMenu(zoomingGroup, zoomMenu); clearZoomMenu(zoomingGridGroup, zoomGridMenu); ViewerPreferences pref = ImViewerFactory.getPreferences(); createZoomMenu(pref, false); int index = ZoomAction.getIndex(model.getZoomFactor()); if (model.isBigImage()) index = model.getSelectedResolutionLevel(); setMagnificationStatus(model.getZoomFactor(), index); controlPane.resetZoomValues(); } /** Sets the image data.*/ void setImageData() { setTitle(model.getImageTitle()); statusBar.formatToolTip(); } /** * Returns the group the image belongs to. * * @return See above. */ GroupData getSelectedGroup() { return model.getSelectedGroup(); } /** * Updates the component displaying the channels' details after update. */ void onChannelUpdated() { controlPane.onChannelUpdated(); } /** * Sets the compression index. * * @param index */ void resetCompressionLevel(int index) { toolBar.setCompressionLevel(index); } /** * Overridden to the set the location of the {@link ImViewer}. * @see TopWindow#setOnScreen() */ public void setOnScreen() { if (model != null) { Browser browser = model.getBrowser(); Rectangle r = null; if (browser != null) { JComponent comp = browser.getUI(); Dimension size = comp.getPreferredSize(); int w = size.width; int h = size.height; ViewerPreferences pref = ImViewerFactory.getPreferences(); if (pref != null) { r = pref.getViewerBounds(); w = r.width; h = r.height; if (w <= 0) w = size.width; if (h <= 0) h = size.height; } if (pref != null) { setBounds(r.x, r.y, w, h); setVisible(true); } else packWindow(); } else packWindow(); UIUtilities.incrementRelativeToAndShow(model.getRequesterBounds(), this); } else { packWindow(); UIUtilities.incrementRelativeToAndShow(null, this); } } /** * Overridden to show or hide the glass pane. */ public void hideAnimation() { JPanel glass = (JPanel) getGlassPane(); hideAnimation(glass.getLayout() == null); } }