/* *------------------------------------------------------------------------------ * 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.agents.imviewer.view; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFormattedTextField; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSlider; import javax.swing.JSpinner; import javax.swing.JToggleButton; import javax.swing.JToolBar; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import info.clearthought.layout.TableLayout; import org.jdesktop.swingx.JXBusyLabel; import org.openmicroscopy.shoola.agents.imviewer.IconManager; import org.openmicroscopy.shoola.agents.imviewer.actions.ColorModelAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ColorPickerAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ViewerAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ZoomAction; import org.openmicroscopy.shoola.agents.util.EditorUtil; import org.openmicroscopy.shoola.agents.util.ui.ChannelButton; import org.openmicroscopy.shoola.env.data.model.ProjectionParam; import org.openmicroscopy.shoola.util.ui.UIUtilities; import org.openmicroscopy.shoola.util.ui.slider.OneKnobSlider; import org.openmicroscopy.shoola.util.ui.slider.TwoKnobsSlider; import omero.gateway.model.ChannelData; /** * Presents variable 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 ControlPane extends JPanel implements ActionListener, ChangeListener, MouseWheelListener, PropertyChangeListener { /** Identifies the T sliders.*/ private static final int T = 0; /** Identifies the Z sliders.*/ private static final int Z = 1; /** Identifies the lifetime sliders.*/ private static final int BIN = 2; /** The default size of the busy label. */ private static final Dimension DIMENSION = new Dimension(16, 16); /** The description of a z-sections selection slider. */ private static final String Z_SLIDER_DESCRIPTION = "Select a z-section."; /** The description of a timepoint selection slider. */ private static final String T_SLIDER_DESCRIPTION = "Select a timepoint."; /** The description of a bin selection slider. */ private static final String LITEIME_SLIDER_DESCRIPTION = "Select a bin."; /** The description of a magnification selection slider. */ private static final String RATIO_SLIDER_DESCRIPTION = "Select the " + "magnification factor of an image composing " + "the grid."; /** The description of a magnification selection slider. */ private static final String ZOOM_SLIDER_DESCRIPTION = "Select the " + "magnification factor of the image."; /** The description of a z-sections selection slider. */ private static final String PROJECTION_SLIDER_DESCRIPTION = "Select the interval of z-sections to project."; /** The tipString of the {@link #zSlider}. */ private static final String Z_SLIDER_TIPSTRING = "Z"; /** The tipString of the {@link #tSlider}. */ private static final String T_SLIDER_TIPSTRING = "T"; /** The maximum height of a magnification slider. */ private static final int SLIDER_HEIGHT = 100; /** Action command id. */ private static final int FREQUENCY = 0; /** Action command id. */ private static final int TYPE = 1; /** Default text describing the compression check box. */ private static final String PROJECTION_DESCRIPTION = "Select the type of projection."; /** The value after which no ticks are displayed. */ private static final int MAX_NO_TICKS = 10; /** Dimension of the box between the channel buttons. */ private static final Dimension VBOX = new Dimension(1, 10); /** Reference to the Control. */ private ImViewerControl controller; /** Reference to the Model. */ private ImViewerModel model; /** Reference to the View. */ private ImViewerUI view; /** Slider to select the lifetime bin. */ private OneKnobSlider lifetimeSlider; /** Slider to select the lifetime bin. */ private OneKnobSlider lifetimeSliderGrid; /** Slider to select the z-section. */ private OneKnobSlider zSlider; /** Slider to select the time-point. */ private OneKnobSlider tSlider; /** Slider to select the z-section. */ private OneKnobSlider zSliderGrid; /** Slider to select the time-point. */ private OneKnobSlider tSliderGrid; /** Slider to select the time-point. */ private OneKnobSlider tSliderProjection; /** Slider to select the z-sections interval to project. */ private TwoKnobsSlider projectionRange; /** Slider to set the magnification factor of an image of the grid. */ private OneKnobSlider gridRatioSlider; /** Slider to set the magnification factor of the image. */ private OneKnobSlider ratioSlider; /** Slider to set the magnification factor of the image. */ private OneKnobSlider projectionRatioSlider; /** One {@link ChannelButton} per channel. */ private List<ChannelButton> channelButtons; /** One {@link ChannelButton} per channel. */ private List<ChannelButton> channelButtonsGrid; /** One {@link ChannelButton} per channel. */ private List<ChannelButton> channelButtonsProjection; /** One {@link ChannelButton} per channel. */ private List<ChannelButton> overlayButtons; /** Button to play movie across channel. */ private JButton channelMovieButton; /** Button to select the color model. */ private JButton colorModelButton; /** Button to select the color model. */ private JButton colorModelButtonGrid; /** Button to select the color model. */ private JButton colorModelButtonProjection; /** Button to bring up the color picker. */ private JButton colorPickerButton; /** Button to paint some textual information on top of the grid image. */ private JToggleButton textVisibleButton; /** Button to play movie across T. */ private JButton playTMovie; /** Button to play movie across lifetime bin. */ private JButton playLifetimeMovie; /** Button to play movie across lifetime bin. */ private JButton playLifetimeMovieGrid; /** Button to play movie across T displayed in the split view. */ private JButton playTMovieGrid; /** Button to play movie across T. */ private JButton playZMovie; /** Button to play movie across T displayed in the split view. */ private JButton playZMovieGrid; /** Button to project the displayed image. */ private JButton projectionProject; /** The type of supported projections. */ private JComboBox projectionTypesBox; /** The type of projection. */ private Map<Integer, Integer> projectionTypes; /** Sets the stepping for the mapping. */ private JSpinner projectionFrequency; /** Busy indicating that the images composing the grid are retrieved. */ private JXBusyLabel gridImageLabel; /** Helper reference. */ private IconManager icons; /** The controls. */ private JPanel controls; /** The Box to turn on or off the overlays.*/ private JCheckBox overlays; /** The listener attached to the overlays. */ private ActionListener overlaysListener; /** Button to reset the zoom level to <code>1</code>.*/ private JButton resetZoom; /** * Sets the selected plane. * * @param z The selected z-section. * @param t The selected time-point. */ private void setSelectedXYPlane(int z, int t) { int bin = -1; if (model.isLifetimeImage()) bin = lifetimeSlider.getValue(); controller.setSelectedXYPlane(z, t, bin); } /** * Handles the event when the wheel is moved over the {@link #zSlider} * or {@link #zSliderGrid}. * * @param e The event to handle. */ private void mouseWheelMovedZ(MouseWheelEvent e) { boolean up = true; if (e.getWheelRotation() > 0) up = false; if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) { int v = model.getDefaultZ()-e.getWheelRotation(); if (up) { if (v <= model.getMaxZ()) setSelectedXYPlane(v, model.getRealSelectedT()); } else { //moving down if (v >= 0) setSelectedXYPlane(v, model.getRealSelectedT()); } } } /** * Handles the event when the wheel is moved over the {@link #tSlider} * or {@link #tSliderGrid}. * * @param e The event to handle. */ private void mouseWheelMovedT(MouseWheelEvent e) { boolean up = true; if (e.getWheelRotation() > 0) up = false; if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) { int v = model.getRealSelectedT()-e.getWheelRotation(); if (up) { if (v <= model.getRealT()) setSelectedXYPlane(model.getDefaultZ(), v); } else { //moving down if (v >= 0) setSelectedXYPlane(model.getDefaultZ(), v); } } } /** * Handles the event when the wheel is moved over the * {@link #lifetimeSlider}. * * @param e The event to handle. */ private void mouseWheelMovedLifetime(MouseWheelEvent e) { boolean up = true; if (e.getWheelRotation() > 0) up = false; if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) { int v = model.getRealSelectedT()-e.getWheelRotation(); if (up) { if (v <= model.getMaxLifetimeBin()) setSelectedXYPlane(model.getDefaultZ(), model.getDefaultT()); } else { //moving down if (v >= 0) setSelectedXYPlane(model.getDefaultZ(), model.getDefaultT()); } } } /** * Returns the description of the current color model. * * @param model The color model. * @return See above. */ private String getColorModelDescription(String model) { if (ImViewer.GREY_SCALE_MODEL.equals(model)) return ColorModelAction.DESCRIPTION_GREY_SCALE; else if (ImViewer.RGB_MODEL.equals(model)) return ColorModelAction.DESCRIPTION_RGB; return null; } /** * Returns the icon corresponding to the current color model. * * @param model The color model. * @return See above. */ private Icon getColorModelIcon(String model) { if (ImViewer.GREY_SCALE_MODEL.equals(model)) return icons.getIcon(IconManager.GRAYSCALE); else if (ImViewer.RGB_MODEL.equals(model)) return icons.getIcon(IconManager.RGB); return null; } /** * Returns the color model corresponding to the icon hosted by the * passed button. * * @param button The button to handle. * @return */ private String getColorModelFromIcon(JButton button) { if (button == null) return null; Icon icon = button.getIcon(); if (icons.getIcon(IconManager.GRAYSCALE).equals(icon)) return ImViewer.GREY_SCALE_MODEL; return ImViewer.RGB_MODEL; } /** Initializes the components composing the display. */ private void initComponents() { channelButtons = new ArrayList<ChannelButton>(); channelButtonsGrid = new ArrayList<ChannelButton>(); channelButtonsProjection = new ArrayList<ChannelButton>(); projectionRange = new TwoKnobsSlider(0, 1, 0, 1); projectionRange.setOrientation(TwoKnobsSlider.VERTICAL); projectionRange.setEnabled(false); projectionRange.setToolTipText(PROJECTION_SLIDER_DESCRIPTION); zSlider = new OneKnobSlider(OneKnobSlider.VERTICAL, 0, 1, 0); zSlider.setEnabled(false); tSlider = new OneKnobSlider(OneKnobSlider.HORIZONTAL, 0, 1, 0); tSlider.setEnabled(false); zSliderGrid = new OneKnobSlider(OneKnobSlider.VERTICAL, 0, 1, 0); zSliderGrid.setEnabled(false); tSliderGrid = new OneKnobSlider(OneKnobSlider.HORIZONTAL, 0, 1, 0); tSliderGrid.setEnabled(false); tSliderProjection = new OneKnobSlider(OneKnobSlider.HORIZONTAL, 0, 1, 0); tSliderProjection.setEnabled(false); lifetimeSlider = new OneKnobSlider(OneKnobSlider.HORIZONTAL, 0, 1, 0); lifetimeSlider.setEnabled(false); lifetimeSliderGrid = new OneKnobSlider(OneKnobSlider.HORIZONTAL, 0, 1, 0); lifetimeSliderGrid.setEnabled(false); IconManager icons = IconManager.getInstance(); gridRatioSlider = new OneKnobSlider(OneKnobSlider.VERTICAL, 1, 10, 5); gridRatioSlider.setEnabled(true); gridRatioSlider.setShowArrows(true); gridRatioSlider.setToolTipText(RATIO_SLIDER_DESCRIPTION); gridRatioSlider.setArrowsImageIcon( icons.getImageIcon(IconManager.RATIO_MAX), icons.getImageIcon(IconManager.RATIO_MIN)); ratioSlider = new OneKnobSlider(OneKnobSlider.VERTICAL, ZoomAction.MIN_ZOOM_INDEX, ZoomAction.MAX_ZOOM_INDEX, ZoomAction.DEFAULT_ZOOM_INDEX); ratioSlider.setEnabled(true); ratioSlider.setShowArrows(true); ratioSlider.setToolTipText(ZOOM_SLIDER_DESCRIPTION); ratioSlider.setArrowsImageIcon( icons.getImageIcon(IconManager.RATIO_MAX), icons.getImageIcon(IconManager.RATIO_MIN), icons.getImageIcon(IconManager.RATIO_MAX_DISABLED), icons.getImageIcon(IconManager.RATIO_MIN_DISABLED)); resetZoom = new JButton(icons.getImageIcon(IconManager.ZOOM_FIT)); resetZoom.setVisible(false); UIUtilities.unifiedButtonLookAndFeel(resetZoom); projectionRatioSlider = new OneKnobSlider(OneKnobSlider.VERTICAL, ZoomAction.MIN_ZOOM_INDEX, ZoomAction.MAX_ZOOM_INDEX, ZoomAction.DEFAULT_ZOOM_INDEX); projectionRatioSlider.setEnabled(true); projectionRatioSlider.setShowArrows(true); projectionRatioSlider.setToolTipText(ZOOM_SLIDER_DESCRIPTION); projectionRatioSlider.setArrowsImageIcon( icons.getImageIcon(IconManager.RATIO_MAX), icons.getImageIcon(IconManager.RATIO_MIN)); channelMovieButton = new JButton( controller.getAction(ImViewerControl.CHANNEL_MOVIE)); UIUtilities.unifiedButtonLookAndFeel(channelMovieButton); colorModelButton = new JButton(); UIUtilities.unifiedButtonLookAndFeel(colorModelButton); colorModelButton.addActionListener(controller); colorModelButtonGrid = new JButton(); UIUtilities.unifiedButtonLookAndFeel(colorModelButtonGrid); colorModelButtonGrid.addActionListener(controller); colorModelButtonProjection = new JButton(); UIUtilities.unifiedButtonLookAndFeel(colorModelButtonProjection); colorModelButtonProjection.addActionListener(controller); ViewerAction a = controller.getAction(ImViewerControl.COLOR_PICKER); colorPickerButton = new JButton(a); colorPickerButton.addMouseListener((ColorPickerAction) a); UIUtilities.unifiedButtonLookAndFeel(colorPickerButton); textVisibleButton = new JToggleButton(); textVisibleButton.setSelected(model.isTextVisible()); textVisibleButton.setAction( controller.getAction(ImViewerControl.TEXT_VISIBLE)); playTMovie = new JButton( controller.getAction(ImViewerControl.PLAY_MOVIE_T)); UIUtilities.unifiedButtonLookAndFeel(playTMovie); playTMovieGrid = new JButton( controller.getAction(ImViewerControl.PLAY_MOVIE_T)); UIUtilities.unifiedButtonLookAndFeel(playTMovieGrid); playZMovie = new JButton( controller.getAction(ImViewerControl.PLAY_MOVIE_Z)); UIUtilities.unifiedButtonLookAndFeel(playZMovie); playZMovieGrid = new JButton( controller.getAction(ImViewerControl.PLAY_MOVIE_Z)); UIUtilities.unifiedButtonLookAndFeel(playZMovieGrid); projectionProject = new JButton( controller.getAction(ImViewerControl.PROJECTION_PROJECT)); projectionFrequency = new JSpinner(new SpinnerNumberModel(1, 1, 1, 1)); JComponent comp = projectionFrequency.getEditor(); if (comp instanceof JSpinner.NumberEditor) { JFormattedTextField field = ((JSpinner.NumberEditor) comp).getTextField(); field.addActionListener(this); field.setActionCommand(""+FREQUENCY); } String[] names = new String[ProjectionParam.PROJECTIONS.size()]; int index = 0; Entry<Integer, String> entry; Iterator<Entry<Integer, String>> i = ProjectionParam.PROJECTIONS.entrySet().iterator(); projectionTypes = new HashMap<Integer, Integer>(); int j; while (i.hasNext()) { entry = i.next(); j = entry.getKey(); projectionTypes.put(index, j); names[index] = entry.getValue(); index++; } projectionTypesBox = new JComboBox(names); projectionTypesBox.setBackground(getBackground()); projectionTypesBox.setToolTipText(PROJECTION_DESCRIPTION); projectionTypesBox.setActionCommand(""+TYPE); projectionTypesBox.addActionListener(this); playLifetimeMovie = new JButton( controller.getAction(ImViewerControl.PLAY_LIFETIME_MOVIE)); UIUtilities.unifiedButtonLookAndFeel(playLifetimeMovie); playLifetimeMovieGrid = new JButton( controller.getAction(ImViewerControl.PLAY_LIFETIME_MOVIE)); UIUtilities.unifiedButtonLookAndFeel(playLifetimeMovieGrid); Icon icon = textVisibleButton.getIcon(); Dimension d = DIMENSION; if (icon != null) { d = new Dimension(icon.getIconWidth(), icon.getIconHeight()); } gridImageLabel = new JXBusyLabel(d); gridImageLabel.setVisible(false); controls = new JPanel(); double size[][] = {{TableLayout.PREFERRED}, {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, SLIDER_HEIGHT, TableLayout.PREFERRED, TableLayout.PREFERRED}}; controls.setLayout(new TableLayout(size)); } /** * Attaches listener to the passed slider and sets the default values. * * @param slider The slider to handle. * @param max The maximum value. * @param v The default value. * @param toolTip The text displayed in the tool tip. * @param endLabel The text displayed in the tool tip when * slider changes value, as well as the label shown at * the end of the text. */ private void initSlider(OneKnobSlider slider, int max, int v, String toolTip, String endLabel) { slider.setVisible(max != 0); slider.setMaximum(max); slider.setValue(v); slider.addChangeListener(this); slider.addMouseWheelListener(this); slider.setToolTipText(toolTip); slider.setEndLabel(endLabel); slider.setShowEndLabel(true); slider.setShowTipLabel(true); if (max > 1 && max <= MAX_NO_TICKS) { slider.setPaintTicks(true); slider.setMajorTickSpacing(1); } } /** * Sets the tool tip of the specified slider. * * @param v The selected z-section, timepoint, bin, etc. * @param slider The slider to handle. * @ */ private void setSliderToolTip(int v, OneKnobSlider slider, int index) { String tip = ""; switch (index) { case T: tip = "T="+(v+1)+"/"+model.getRealT(); break; case Z: tip = "Z="+(v+1)+"/"+(model.getMaxZ()+1); break; case BIN: tip = "t="+(v+1)+"/"+model.getMaxLifetimeBin(); } slider.setToolTipText(tip); } /** * Initializes the value of the components displaying the currently selected * z-section and time-point. */ private void initializeValues() { int maxZ = model.getMaxZ(); int maxT = model.getRealT(); projectionRange.setValues(maxZ+1, 1, maxZ+1, 1, 1, maxZ+1); projectionRange.addPropertyChangeListener(this); projectionRange.addMouseWheelListener(this); projectionRange.setToolTipText(PROJECTION_SLIDER_DESCRIPTION); setRangeSliderToolTip(0, maxZ); initSlider(tSliderProjection, maxT-1, model.getRealSelectedT(), T_SLIDER_DESCRIPTION, T_SLIDER_TIPSTRING); setSliderToolTip(model.getRealSelectedT(), tSliderProjection, T); initSlider(zSlider, maxZ, model.getDefaultZ(), Z_SLIDER_DESCRIPTION, Z_SLIDER_TIPSTRING); initSlider(zSliderGrid, maxZ, model.getDefaultZ(), Z_SLIDER_DESCRIPTION, Z_SLIDER_TIPSTRING); setSliderToolTip(model.getDefaultZ(), zSlider, Z); setSliderToolTip(model.getDefaultZ(), zSliderGrid, Z); initSlider(tSlider, maxT-1, model.getRealSelectedT(), T_SLIDER_DESCRIPTION, T_SLIDER_TIPSTRING); initSlider(tSliderGrid, maxT-1, model.getRealSelectedT(), T_SLIDER_DESCRIPTION, T_SLIDER_TIPSTRING); setSliderToolTip(model.getRealSelectedT(), tSlider, T); setSliderToolTip(model.getRealSelectedT(), tSliderGrid, T); if (model.isBigImage()) { ratioSlider.addPropertyChangeListener(this); ratioSlider.setMaximum(model.getResolutionLevels()-1); ratioSlider.setValue(model.getSelectedResolutionLevel()); resetZoom.addActionListener( controller.getZoomActionFromLevels( model.getResolutionLevels()-1)); resetZoom.setToolTipText("Reset to full size."); resetZoom.setText(""); } ratioSlider.addChangeListener(this); gridRatioSlider.addChangeListener(this); projectionRatioSlider.addChangeListener(this); playTMovie.setVisible(maxT > 1); playTMovieGrid.setVisible(maxT > 1); playZMovie.setVisible(maxZ != 0); playZMovieGrid.setVisible(maxZ != 0); colorModelButton.setIcon(getColorModelIcon(model.getColorModel())); colorModelButton.setToolTipText( getColorModelDescription(model.getColorModel())); colorModelButtonGrid.setIcon(getColorModelIcon(model.getColorModel())); colorModelButtonGrid.setToolTipText( getColorModelDescription(model.getColorModel())); colorModelButtonProjection.setIcon( getColorModelIcon(model.getColorModel())); colorModelButtonProjection.setToolTipText( getColorModelDescription(model.getColorModel())); SpinnerNumberModel m = (SpinnerNumberModel) projectionFrequency.getModel(); m.setMaximum(view.getMaxZ()+1); projectionFrequency.addChangeListener(this); //Lifetime for now int maxBin = model.getMaxLifetimeBin(); initSlider(lifetimeSlider, maxBin-1, model.getSelectedBin(), LITEIME_SLIDER_DESCRIPTION, EditorUtil.SMALL_T_VARIABLE); setSliderToolTip(model.getSelectedBin(), lifetimeSlider, BIN); lifetimeSlider.setPaintTicks(false); initSlider(lifetimeSliderGrid, maxBin-1, model.getSelectedBin(), LITEIME_SLIDER_DESCRIPTION, EditorUtil.SMALL_T_VARIABLE); setSliderToolTip(model.getSelectedBin(), lifetimeSliderGrid, BIN); playLifetimeMovie.setVisible(maxBin > 1); playLifetimeMovie.setEnabled(maxBin > 1); playLifetimeMovieGrid.setVisible(maxBin > 1); playLifetimeMovieGrid.setEnabled(maxBin > 1); if (model.isBigImage()) resetZoom.setVisible(true); } /** * Helper method to create a panel hosting the passed slider. * * @param slider The slider to host. * @return See above. */ private JPanel layoutSlider(JComponent slider) { JPanel pane = new JPanel(); pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); pane.add(slider); return pane; } /** * Builds a tool bar hosting the passed button. * * @param button The button to add. * @return See above */ private JToolBar createButtonToolBar(JComponent button) { JToolBar bar = new JToolBar(); bar.setFloatable(false); bar.setRollover(true); bar.setBorder(null); bar.add(button); return bar; } /** * Helper method to create a panel hosting the passed slider. * * @return See above. */ private JPanel createZSliderPane() { JPanel pane = new JPanel(); double[][] tl = {{TableLayout.FILL}, {TableLayout.FILL, TableLayout.PREFERRED}}; pane.setLayout(new TableLayout(tl)); pane.add(zSlider, "0, 0"); pane.add(createButtonToolBar(playZMovie), "0, 1"); JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(pane); return p; } /** * Helper method to create a panel hosting the passed slider. * * @return See above. */ private JPanel createZGridSliderPane() { JPanel pane = new JPanel(); double[][] tl = {{TableLayout.FILL}, {TableLayout.FILL, TableLayout.PREFERRED}}; pane.setLayout(new TableLayout(tl)); pane.add(zSliderGrid, "0, 0"); pane.add(createButtonToolBar(playZMovieGrid), "0, 1"); JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(pane); return p; } /** * Builds the tool bar displayed on the left side of the image. * * @return See above. */ private JComponent buildToolBar() { if (!model.isLifetimeImage() || model.getModuloT() != null) { JToolBar bar = createBar(); bar.add(colorModelButton); bar.add(Box.createRigidArea(VBOX)); bar.add(colorPickerButton); return bar; } return colorModelButton; } /** * Builds the tool bar displayed on the left side of the grid view. * * @return See above. */ private JToolBar buildGridBar() { JToolBar bar = createBar(); bar.add(gridImageLabel); bar.add(Box.createRigidArea(VBOX)); bar.add(colorModelButtonGrid); return bar; } /** * Creates a tool bar. * * @return See above. */ private JToolBar createBar() { JToolBar bar = new JToolBar(JToolBar.VERTICAL); bar.setFloatable(false); bar.setRollover(true); bar.setBorder(null); return bar; } /** * Builds the tool bar displayed on the left side of the projection view. * * @return See above. */ private JToolBar buildProjectionBar() { JToolBar bar = new JToolBar(JToolBar.VERTICAL); bar.setFloatable(false); bar.setRollover(true); bar.setBorder(null); bar.add(colorModelButtonProjection); return bar; } /** * Creates a UI component hosting the {@link ChannelButton}s. * * @return See above. */ private JPanel createChannelsPane() { JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS)); ChannelButton button; Dimension d; int w = 0, h = 0; if (!model.isLifetimeImage() || model.getModuloT() != null) { p.add(Box.createRigidArea(VBOX)); channelButtons = createChannelButtons(); Iterator<ChannelButton> i = channelButtons.iterator(); while (i.hasNext()) { button = i.next(); d = button.getPreferredSize(); if (d.width > w) w = d.width; if (d.height > h) h = d.height; button.addPropertyChangeListener(controller); p.add(button); p.add(Box.createRigidArea(VBOX)); } } controls.add(Box.createVerticalStrut(20), "0, 0"); int k = 1; controls.add(buildToolBar(), "0, "+k+", CENTER, CENTER"); k++; if (channelButtons.size() > ImViewer.MAX_CHANNELS) { JScrollPane sp = new JScrollPane(p); d = new Dimension(2*w, h*ImViewer.MAX_CHANNELS); sp.setPreferredSize(d); controls.add(sp, "0, "+k+", RIGHT, CENTER"); } else controls.add(p, "0, "+k); k++; if (!model.isLifetimeImage() || model.getModuloT() != null) { controls.add(createButtonToolBar(channelMovieButton), "0, "+k+", CENTER, CENTER"); } k++; controls.add(ratioSlider, "0, "+k+", CENTER, CENTER"); k++; controls.add(resetZoom, "0, "+k+", CENTER, CENTER"); return UIUtilities.buildComponentPanel(controls); } /** Builds and lays out the UI. */ private void buildGUI() { setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); add(createChannelsPane()); add(createZSliderPane()); } /** * Sets the value of the specified slider when a propertyChange has been * fired. * * @param slider The slider to update. * @param v The selected value. */ private void updateSlider(JSlider slider, int v) { slider.removeChangeListener(this); slider.setValue(v); slider.addChangeListener(this); } /** * Sets the maximum value of the slider. * * @param slider The slider to handle. * @param max The maximum value to set. */ private void setSliderMax(JSlider slider, int max) { slider.removeChangeListener(this); slider.setMaximum(max); slider.addChangeListener(this); } /** * Creates a new instance. * * @param controller Reference to the Control. Mustn't be <code>null</code>. * @param model Reference to the Model. Mustn't be <code>null</code>. * @param view Reference to the View. Mustn't be <code>null</code>. */ ControlPane(ImViewerControl controller, ImViewerModel model, ImViewerUI view) { if (controller == null) throw new NullPointerException("No control."); if (model == null) throw new NullPointerException("No model."); if (view == null) throw new NullPointerException("No view."); this.controller = controller; this.model = model; this.view = view; icons = IconManager.getInstance(); initComponents(); } /** * Creates a collection of <code>ChannelButton</code>s. * * @return See above. */ List<ChannelButton> createChannelButtons() { List<ChannelButton> channelButtons = new ArrayList<ChannelButton>(); List<ChannelData> data = model.getChannelData(); ChannelButton button; ChannelData d; Dimension dim; Dimension dimMax = ChannelButton.DEFAULT_MIN_SIZE; Iterator<ChannelData> i = data.iterator(); int k; while (i.hasNext()) { d = i.next(); k = d.getIndex(); button = new ChannelButton(d.getChannelLabeling(), model.getChannelColor(k), k, model.isChannelActive(k)); channelButtons.add(button); dim = button.getPreferredSize(); if (dim.width > dimMax.width) dimMax = new Dimension(dim.width, dimMax.height); } Iterator<ChannelButton> j = channelButtons.iterator(); while (j.hasNext()) j.next().setPreferredSize(dimMax); return channelButtons; } /** * This method should be called straight after the metadata and the * rendering settings are loaded. */ void buildComponent() { initializeValues(); buildGUI(); } /** * Builds the control panel displayed in the grid view. * * @return See above. */ JPanel buildGridComponent() { if (model.getModuloT() == null && model.isLifetimeImage()) return new JPanel(); JPanel p = createZGridSliderPane(); JPanel buttons = new JPanel(); buttons.setLayout(new BoxLayout(buttons, BoxLayout.Y_AXIS)); ChannelButton button; buttons.add(Box.createRigidArea(VBOX)); channelButtonsGrid = createChannelButtons(); Iterator<ChannelButton> i = channelButtonsGrid.iterator(); Dimension d; int w = 0, h = 0; while (i.hasNext()) { button = i.next(); d = button.getPreferredSize(); if (d.width > w) w = d.width; if (d.height > h) h = d.height; buttons.add(button); buttons.add(Box.createRigidArea(VBOX)); button.addPropertyChangeListener(controller); } JPanel controls = new JPanel(); double size[][] = {{TableLayout.PREFERRED}, {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, SLIDER_HEIGHT}}; controls.setLayout(new TableLayout(size)); controls.add(Box.createVerticalStrut(10), "0, 0"); JToolBar bar = buildGridBar(); bar.add(Box.createRigidArea(VBOX)); controls.add(bar, "0, 1, CENTER, CENTER"); controls.add(createButtonToolBar(textVisibleButton), "0, 2, " + "CENTER, CENTER"); if (channelButtonsGrid.size() > ImViewer.MAX_CHANNELS) { JScrollPane sp = new JScrollPane(buttons); d = new Dimension(2*w, h*ImViewer.MAX_CHANNELS); sp.setPreferredSize(d); controls.add(sp, "0, 3, RIGHT, CENTER"); } else controls.add(buttons, "0, 3"); controls.add(gridRatioSlider, "0, 4, CENTER, CENTER"); JPanel content = new JPanel(); content.setLayout(new BoxLayout(content, BoxLayout.X_AXIS)); content.add(UIUtilities.buildComponentPanel(controls)); content.add(p); return content; } /** * Builds the component hosting controls for projection. * * @return See above */ JPanel buildProjectionToolBar() { JPanel bar = new JPanel(); bar.setBorder(null); bar.add(new JLabel("Intensity: ")); bar.add(projectionTypesBox); bar.add(new JLabel(" Every n-th slice: ")); bar.add(projectionFrequency); bar.add(Box.createRigidArea(VBOX)); bar.add(projectionProject); JPanel projectionBar = new JPanel(); projectionBar.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); projectionBar.add(bar); return projectionBar; } /** * Builds the component hosting the controls to manage the projected image. * * @return See above. */ JPanel buildProjectionComponent() { if (model.getModuloT() == null && model.isLifetimeImage()) return new JPanel(); JPanel p = layoutSlider(projectionRange); JPanel buttons = new JPanel(); buttons.setLayout(new BoxLayout(buttons, BoxLayout.Y_AXIS)); ChannelButton button; buttons.add(Box.createRigidArea(VBOX)); channelButtonsProjection = createChannelButtons(); Iterator<ChannelButton> i = channelButtonsProjection.iterator(); int w = 0, h = 0; Dimension d; while (i.hasNext()) { button = i.next(); d = button.getPreferredSize(); if (d.width > w) w = d.width; if (d.height > h) h = d.height; buttons.add(button); buttons.add(Box.createRigidArea(VBOX)); button.addPropertyChangeListener(controller); } JPanel controls = new JPanel(); double size[][] = {{TableLayout.PREFERRED}, {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, SLIDER_HEIGHT}}; controls.setLayout(new TableLayout(size)); controls.add(Box.createVerticalStrut(20), "0, 0"); int k = 1; controls.add(buildProjectionBar(), "0, "+k+", CENTER, CENTER"); k++; if (channelButtonsProjection.size() > ImViewer.MAX_CHANNELS) { JScrollPane sp = new JScrollPane(buttons); d = new Dimension(2*w, h*ImViewer.MAX_CHANNELS); sp.setPreferredSize(d); controls.add(sp, "0, "+k+", RIGHT, CENTER"); } else controls.add(buttons, "0, "+k+", CENTER, CENTER"); k++; controls.add(projectionRatioSlider, "0, "+k+", CENTER, CENTER"); JPanel content = new JPanel(); content.setLayout(new BoxLayout(content, BoxLayout.X_AXIS)); content.add(UIUtilities.buildComponentPanel(controls)); content.add(p); return content; } /** * Updates UI components when a new timepoint is selected. * * @param t The selected timepoint. */ void setTimepoint(int t) { setSliderToolTip(t, tSlider, T); setSliderToolTip(t, tSliderGrid, T); updateSlider(tSlider, t); updateSlider(tSliderGrid, t); updateSlider(tSliderProjection, t); } /** * Updates UI components when a new bin is selected. * * @param v The selected bin. */ void setBin(int v) { if (lifetimeSlider == null) return; setSliderToolTip(v, lifetimeSlider, BIN); updateSlider(lifetimeSlider, v); setSliderToolTip(v, lifetimeSliderGrid, BIN); updateSlider(lifetimeSliderGrid, v); } /** * Updates UI components when a new z-section is selected. * * @param z The selected z-section. */ void setZSection(int z) { setSliderToolTip(z, zSlider, Z); setSliderToolTip(z, zSliderGrid, Z); updateSlider(zSlider, z); updateSlider(zSliderGrid, z); } /** Updates UI components when a new color model is selected. */ void setColorModel() { boolean gs = (model.getColorModel().equals(ImViewer.GREY_SCALE_MODEL)); Iterator<ChannelButton> i = channelButtons.iterator(); ChannelButton button; while (i.hasNext()) { button = i.next(); button.setSelected( model.isChannelActive(button.getChannelIndex())); } i = channelButtonsGrid.iterator(); while (i.hasNext()) { button = i.next(); if (!gs) button.setSelected( model.isChannelActive(button.getChannelIndex())); } i = channelButtonsProjection.iterator(); while (i.hasNext()) { button = i.next(); button.setSelected( model.isChannelActive(button.getChannelIndex())); } colorModelButton.setIcon(getColorModelIcon(model.getColorModel())); colorModelButton.setToolTipText(getColorModelDescription( model.getColorModel())); colorModelButtonGrid.setIcon(getColorModelIcon(model.getColorModel())); colorModelButtonGrid.setToolTipText(getColorModelDescription( model.getColorModel())); colorModelButtonProjection.setIcon( getColorModelIcon(model.getColorModel())); colorModelButtonProjection.setToolTipText(getColorModelDescription( model.getColorModel())); } /** * Sets the selected channels in the grid view. * * @param channels Collection of channels to set. */ void setChannelsSelection(List channels) { Iterator<ChannelButton> i = channelButtonsGrid.iterator(); ChannelButton button; int index; while (i.hasNext()) { button = i.next(); index = button.getChannelIndex(); button.setSelected(channels.contains(index)); } } /** * Updates the {@link ChannelButton}s when a new one is selected or * deselected. * * @param index One of the following constants {@link ImViewerUI#GRID_ONLY}, * {@link ImViewerUI#VIEW_ONLY} and * {@link ImViewerUI#ALL_VIEW}. */ void setChannelsSelection(int index) { Iterator<ChannelButton> i; ChannelButton button; switch (index) { case ImViewerUI.GRID_ONLY: i = channelButtonsGrid.iterator(); while (i.hasNext()) { button = i.next(); button.setSelected( model.isChannelActive(button.getChannelIndex())); } break; case ImViewerUI.VIEW_ONLY: i = channelButtons.iterator(); while (i.hasNext()) { button = i.next(); button.setSelected( model.isChannelActive(button.getChannelIndex())); } break; case ImViewerUI.PROJECTION_ONLY: i = channelButtonsProjection.iterator(); while (i.hasNext()) { button = i.next(); button.setSelected( model.isChannelActive(button.getChannelIndex())); } break; case ImViewerUI.ALL_VIEW: i = channelButtons.iterator(); while (i.hasNext()) { button = i.next(); button.setSelected( model.isChannelActive(button.getChannelIndex())); } i = channelButtonsGrid.iterator(); while (i.hasNext()) { button = i.next(); button.setSelected( model.isChannelActive(button.getChannelIndex())); } i = channelButtonsProjection.iterator(); while (i.hasNext()) { button = i.next(); button.setSelected( model.isChannelActive(button.getChannelIndex())); } } } /** * Sets the color of selected channel. * * @param index The channel index. * @param c The color to set. */ void setChannelColor(int index, Color c) { Iterator<ChannelButton> i = channelButtons.iterator(); ChannelButton button; while (i.hasNext()) { button = i.next(); if (index == button.getChannelIndex()) button.setColor(c); } i = channelButtonsGrid.iterator(); while (i.hasNext()) { button = i.next(); if (index == button.getChannelIndex()) button.setColor(c); } i = channelButtonsProjection.iterator(); while (i.hasNext()) { button = i.next(); if (index == button.getChannelIndex()) button.setColor(c); } } /** Resets the rendering settings. */ void resetRndSettings() { Iterator<ChannelButton> i = channelButtons.iterator(); ChannelButton button; int index; while (i.hasNext()) { button = i.next(); index = button.getChannelIndex(); button.setSelected(model.isChannelActive(index)); button.setColor(model.getChannelColor(index)); } i = channelButtonsGrid.iterator(); while (i.hasNext()) { button = i.next(); index = button.getChannelIndex(); button.setSelected(model.isChannelActive(index)); button.setColor(model.getChannelColor(index)); } i = channelButtonsProjection.iterator(); while (i.hasNext()) { button = i.next(); index = button.getChannelIndex(); button.setSelected(model.isChannelActive(index)); button.setColor(model.getChannelColor(index)); } Icon icon = getColorModelIcon(model.getColorModel()); String tip = getColorModelDescription(model.getColorModel()); colorModelButton.setIcon(icon); colorModelButton.setToolTipText(tip); colorModelButtonGrid.setIcon(icon); colorModelButtonGrid.setToolTipText(tip); colorModelButtonProjection.setIcon(icon); colorModelButtonProjection.setToolTipText(tip); setZSection(model.getDefaultZ()); setTimepoint(model.getDefaultT()); setBin(model.getSelectedBin()); ProjectionParam ref = model.getLastProjRef(); if (ref != null) projectionRange.setInterval(ref.getStartZ()+1, ref.getEndZ()+1); } /** Resets the UI when the user switches to a new rendering control. */ void switchRndControl() { setSliderMax(zSlider, model.getMaxZ()); setSliderMax(zSliderGrid, model.getMaxZ()); setSliderMax(tSliderGrid, model.getRealT()); setSliderMax(tSlider, model.getRealT()); if (lifetimeSlider != null) { setSliderMax(lifetimeSlider, model.getMaxLifetimeBin()); setSliderMax(lifetimeSliderGrid, model.getMaxLifetimeBin()); } resetRndSettings(); } /** * 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) { Iterator<ChannelButton> i = channelButtons.iterator(); while (i.hasNext()) i.next().setEnabled(b); i = channelButtonsGrid.iterator(); while (i.hasNext()) i.next().setEnabled(b); i = channelButtonsProjection.iterator(); while (i.hasNext()) i.next().setEnabled(b); colorModelButton.setEnabled(b); colorModelButtonGrid.setEnabled(b); colorModelButtonProjection.setEnabled(b); //projection stuff if (projectionTypesBox != null) projectionTypesBox.setEnabled(b); if (projectionFrequency != null) projectionFrequency.setEnabled(b); if (b) onColorModelChanged(); else { if (overlays != null) overlays.setEnabled(false); if (overlayButtons != null) { i = overlayButtons.iterator(); while (i.hasNext()) i.next().setEnabled(false); } } //big images. if (model.isBigImage()) { boolean loading = model.getState() != ImViewer.LOADING_TILES; ratioSlider.setEnabled(loading); gridRatioSlider.setEnabled(loading); projectionRatioSlider.setEnabled(loading); if (resetZoom != null) resetZoom.setEnabled(loading); } } /** * Builds and returns a UI component hosting the time slider * corresponding to the passed index. * * @param index The index used to identify the slider. * @return See above. */ JPanel getTimeSliderPane(int index) { switch (index) { case ImViewer.GRID_INDEX: JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(createButtonToolBar(playTMovieGrid)); p.add(tSliderGrid); return p; case ImViewer.PROJECTION_INDEX: return layoutSlider(tSliderProjection); case ImViewer.VIEW_INDEX: default: JPanel pane = new JPanel(); pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS)); pane.add(createButtonToolBar(playTMovie)); pane.add(tSlider); return pane; } } /** * Builds and returns a UI component hosting the time slider * corresponding to the passed index. * * @param index The index used to identify the slider. * @return See above. */ JPanel getLifetimeSliderPane(int index) { JPanel pane = new JPanel(); pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS)); switch (index) { case ImViewer.VIEW_INDEX: default: pane.add(createButtonToolBar(playLifetimeMovie)); pane.add(lifetimeSlider); return pane; case ImViewer.GRID_INDEX: pane.add(createButtonToolBar(playLifetimeMovieGrid)); pane.add(lifetimeSliderGrid); return pane; } } /** * Sets the <code>enable</code> flag of the slider used to select * the current z-section and timepoint. * * @param b Pass <code>true</code> to enable the sliders, * <code>false</code> otherwise. */ void enableSliders(boolean b) { enableZSliders(b); enableTSliders(b); if (b) { boolean v = model.getMaxLifetimeBin() > 1; lifetimeSlider.setEnabled(v); lifetimeSliderGrid.setEnabled(v); } else { lifetimeSlider.setEnabled(b); lifetimeSliderGrid.setEnabled(b); } } /** * Sets the <code>enable</code> flag of the slider used to select * the current z-section. * * @param b Pass <code>true</code> to enable the sliders, * <code>false</code> otherwise. */ void enableZSliders(boolean b) { if (b) { zSlider.setEnabled(model.getMaxZ() != 0); zSliderGrid.setEnabled(model.getMaxZ() != 0); projectionRange.setEnabled(model.getMaxZ() != 0); } else { zSlider.setEnabled(b); zSliderGrid.setEnabled(b); projectionRange.setEnabled(b); } } /** * Sets the <code>enable</code> flag of the slider used to select * the current timepoint. * * @param b Pass <code>true</code> to enable the sliders, * <code>false</code> otherwise. */ void enableTSliders(boolean b) { if (b) { tSlider.setEnabled(model.getRealT() > 1); tSliderGrid.setEnabled(model.getRealT() > 1); tSliderProjection.setEnabled(model.getRealT() > 1); } else { tSlider.setEnabled(b); tSliderGrid.setEnabled(b); tSliderProjection.setEnabled(b); } } /** * 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) { Iterator<ChannelButton> i; ChannelButton button; switch (uiIndex) { case ImViewerUI.GRID_ONLY: i = channelButtonsGrid.iterator(); while (i.hasNext()) { button = i.next(); if (index == button.getChannelIndex()) button.setSelected(true); } break; case ImViewerUI.ALL_VIEW: i = channelButtons.iterator(); while (i.hasNext()) { button = i.next(); if (index == button.getChannelIndex()) button.setSelected(true); } i = channelButtonsGrid.iterator(); while (i.hasNext()) { button = i.next(); if (index == button.getChannelIndex()) button.setSelected(true); } i = channelButtonsProjection.iterator(); while (i.hasNext()) { button = i.next(); if (index == button.getChannelIndex()) button.setSelected(true); } } } /** * Returns the collection of active channels in the grid view. * * @return See above. */ List getActiveChannelsInGrid() { List<Integer> active = new ArrayList<Integer>(); Iterator<ChannelButton> i = channelButtonsGrid.iterator(); ChannelButton button; while (i.hasNext()) { button = i.next(); if (button.isSelected()) active.add(button.getChannelIndex()); } return active; } /** * Returns the collection of active channels in the projection view. * * @return See above. */ List getActiveChannelsInProjection() { List<Integer> active = new ArrayList<Integer>(); Iterator<ChannelButton> i = channelButtonsProjection.iterator(); ChannelButton button; while (i.hasNext()) { button = i.next(); if (button.isSelected()) active.add(button.getChannelIndex()); } return active; } /** * Updates UI components when a zooming factor is selected. * * @param zoomIndex The index of the selected zoomFactor. */ void setZoomFactor(int zoomIndex) { if (ratioSlider.getMinimum() > zoomIndex || ratioSlider.getMaximum() < zoomIndex) return; ratioSlider.removeChangeListener(this); ratioSlider.setValue(zoomIndex); ratioSlider.addChangeListener(this); projectionRatioSlider.removeChangeListener(this); projectionRatioSlider.setValue(zoomIndex); projectionRatioSlider.addChangeListener(this); } /** * Returns the lower bound of the z-section to project. (zero based) * * @return See above. */ int getProjectionStartZ() { return projectionRange.getStartValueAsInt()-1; } /** * Returns the lower bound of the z-section to project. (zero based) * * @return See above. */ int getProjectionEndZ() { return projectionRange.getEndValueAsInt()-1; } /** * Updates UI components when a zooming factor for the grid * is selected. * * @param zoomIndex The index of the selected zoomFactor. */ void setGridMagnificationFactor(int zoomIndex) { if (gridRatioSlider.getMinimum() > zoomIndex || gridRatioSlider.getMaximum() < zoomIndex) return; gridRatioSlider.removeChangeListener(this); gridRatioSlider.setValue(zoomIndex); gridRatioSlider.addChangeListener(this); } /** * Returns the stepping used for the projection. * * @return See above. */ int getProjectionStepping() { return (Integer) projectionFrequency.getValue(); } /** * Returns the type of projection. * * @return See above. */ int getProjectionType() { int index = projectionTypesBox.getSelectedIndex(); return projectionTypes.get(index); } /** Resets the zoom values when the image is large. */ void resetZoomValues() { //ratioSlider.setMaximum(ZoomAction.ZOOM_100); } /** * Returns a textual version of the type of projection. * * @return See above. */ String getProjectionTypeName() { int index = projectionTypesBox.getSelectedIndex(); return ProjectionParam.PROJECTIONS.get(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) { gridImageLabel.setVisible(busy); gridImageLabel.setBusy(busy); } /** * 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) { Iterator<ChannelButton> i = channelButtons.iterator(); while (i.hasNext()) { if (i.next() == source) return true; } i = channelButtonsGrid.iterator(); while (i.hasNext()) { if (i.next() == source) return true; } i = channelButtonsProjection.iterator(); while (i.hasNext()) { if (i.next() == source) return true; } return false; } /** Removes the overlays. */ void onColorModelChanged() { String colorModel = model.getColorModel(); if (overlays == null) return; if (ImViewer.GREY_SCALE_MODEL.equals(colorModel)) { overlays.removeActionListener(overlaysListener); overlays.setSelected(false); overlays.addActionListener(overlaysListener); overlays.setEnabled(false); Iterator<ChannelButton> i = overlayButtons.iterator(); while (i.hasNext()) i.next().setEnabled(false); } else { boolean ready = model.getState() == ImViewer.READY; overlays.setEnabled(ready); Iterator<ChannelButton> i = overlayButtons.iterator(); while (i.hasNext()) i.next().setEnabled(ready); } } /** Builds the overlays. */ void buildOverlays() { Map m = model.getOverLays(); if (m == null || m.size() == 0) return; overlays = new JCheckBox("Overlays"); overlaysListener = new ActionListener() { public void actionPerformed(ActionEvent e) { controller.renderOverlays(overlays.isSelected()); } }; overlays.addActionListener(overlaysListener); TableLayout layout = (TableLayout) controls.getLayout(); int row = layout.getNumRow()-1; overlayButtons = new ArrayList<ChannelButton>(); Iterator i = m.entrySet().iterator(); Entry entry; int index; ChannelButton button; Color c; JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS)); int j = 0; int w = 0; int h = 0; while (i.hasNext()) { entry = (Entry) i.next(); index = (Integer) entry.getKey(); c = new Color((Integer) entry.getValue()); button = new ChannelButton(""+j, c, index, true); button.setOverlay(true); button.addPropertyChangeListener(controller); overlayButtons.add(button); p.add(button); p.add(Box.createRigidArea(VBOX)); w = button.getPreferredSize().width; h = button.getPreferredSize().height; j++; } JPanel pane = new JPanel(); double size[][] = {{TableLayout.PREFERRED}, {TableLayout.PREFERRED, TableLayout.PREFERRED}}; pane.setLayout(new TableLayout(size)); pane.add(overlays, "0, 0, CENTER, CENTER"); if (overlayButtons.size() > ImViewer.MAX_OVERLAYS) { JScrollPane sp = new JScrollPane(p); Dimension d = new Dimension(2*w, h*ImViewer.MAX_OVERLAYS); sp.setPreferredSize(d); pane.add(sp, "0, 1, CENTER, CENTER"); } else pane.add(p, "0, 1, CENTER, CENTER"); controls.add(pane, "0, "+row+", LEFT, CENTER"); } /** * Turns on or off the selected overlay. * * @param index The index of the overlay. * @param selected Pass <code>true</code> to turn the overlay on, * <code>false</code> to turn it off. */ void renderOverlays(int index, boolean selected) { if (index == -1) return; Iterator<ChannelButton> i = overlayButtons.iterator(); ChannelButton b; while (i.hasNext()) { b = i.next(); if (b.getChannelIndex() == index) { b.setSelected(selected); break; } } } /** * Returns the selected overlays if displayed otherwise returns * <code>null</code>. * * @return See above. */ Map<Long, Integer> getSelectedOverlays() { Map<Long, Integer> m = new HashMap<Long, Integer>(); Iterator<ChannelButton> i = overlayButtons.iterator(); ChannelButton b; Color c; while (i.hasNext()) { b = i.next(); c = b.getColor(); if (b.isSelected() && c != null) { m.put((long) b.getChannelIndex(), c.getRGB() & 0x00ffffff); } } return m; } /** * Returns <code>true</code> if the overlays are turned on, * <code>false</code> otherwise. * * @return See above. */ boolean isOverlayActive() { return overlays.isSelected(); } /** * Returns the color model of the pane currently selected. * * @return See above. */ String getSelectedPaneColorModel() { switch (view.getTabbedIndex()) { case ImViewer.GRID_INDEX: return getColorModelFromIcon(colorModelButtonGrid); case ImViewer.PROJECTION_INDEX: return getColorModelFromIcon(colorModelButtonProjection); case ImViewer.VIEW_INDEX: default: return getColorModelFromIcon(colorModelButton); } } /** * Sets the tool tip of the specified slider. * * @param start The start z-section. * @param end The end z-section. */ void setRangeSliderToolTip(int start, int end) { String tip = "Selected Range Z="+(start+1)+"-"+(end+1)+ "/"+(model.getMaxZ()+1); projectionRange.setToolTipText(tip); } /** * Updates the component displaying the channels' details after update. */ void onChannelUpdated() { Dimension dimMax = updateText(channelButtons); updateText(channelButtonsGrid); updateText(channelButtonsProjection); resizeChannelButton(dimMax, channelButtons); resizeChannelButton(dimMax, channelButtonsGrid); resizeChannelButton(dimMax, channelButtonsProjection); repaint(); } /** * Updates the text of the specified components. Returns the maximum * size of the components. * * @param buttons The components to update. * @return See above */ private Dimension updateText(List<ChannelButton> buttons) { Iterator<ChannelButton> i = buttons.iterator(); ChannelData data; ChannelButton cb; Dimension d; Dimension dimMax = new Dimension(0, 0); while (i.hasNext()) { cb = i.next(); data = model.getChannelData(cb.getChannelIndex()); cb.setText(data.getChannelLabeling()); d = cb.getPreferredSize(); if (d.width > dimMax.width) dimMax = new Dimension(d.width, d.height); } return dimMax; } /** * Resizes the buttons after changing the text. * * @param d The dimension to set. * @param buttons The buttons to handle. */ private void resizeChannelButton(Dimension d, List<ChannelButton> buttons) { Iterator<ChannelButton> j = buttons.iterator(); while (j.hasNext()) j.next().setPreferredSize(d); repaint(); } /** * Reacts to the selection of an item in the projection box * @see ActionListener#actionPerformed(ActionEvent) */ public void actionPerformed(ActionEvent e) { int index = Integer.parseInt(e.getActionCommand()); if (index == FREQUENCY) { JComponent comp = projectionFrequency.getEditor(); if (comp instanceof JSpinner.NumberEditor) { JFormattedTextField field = ((JSpinner.NumberEditor) comp).getTextField(); String value = field.getText(); int v = -1; try { v = Integer.parseInt(value); } catch (Exception ex) {} if (v == -1 || v > model.getMaxZ() || v < 1) return; projectionFrequency.setValue(v); } } controller.setProjectionRange(true); } /** * Reacts to selection of a new plane. * @see ChangeListener#stateChanged(ChangeEvent) */ public void stateChanged(ChangeEvent e) { Object object = e.getSource(); if (object instanceof JSlider) { if (object.equals(gridRatioSlider)) { double r = (double) gridRatioSlider.getValue()/10; controller.setGridMagnificationFactor(r); return; } else if (object.equals(ratioSlider)) { if (model.isBigImage()) { if (!ratioSlider.isDragging()) controller.setZoomFactor(ratioSlider.getValue()); } else { controller.setZoomFactor(ratioSlider.getValue()); } } else if (object.equals(projectionRatioSlider)) { controller.setZoomFactor(projectionRatioSlider.getValue()); } if (object.equals(zSlider) || object.equals(tSlider)) setSelectedXYPlane(zSlider.getValue(), tSlider.getValue()); else if (object.equals(lifetimeSlider)) { controller.setSelectedXYPlane(model.getDefaultZ(), model.getRealSelectedT(), lifetimeSlider.getValue()); } else if (object.equals(lifetimeSliderGrid)) { controller.setSelectedXYPlane(model.getDefaultZ(), model.getRealSelectedT(), lifetimeSliderGrid.getValue()); } else if (object.equals(zSliderGrid) || object.equals(tSliderGrid)) setSelectedXYPlane(zSliderGrid.getValue(), tSliderGrid.getValue()); else if (object.equals(tSliderProjection)) { //Only if knob is released. if (!tSliderProjection.getValueIsAdjusting()) { try { setSelectedXYPlane(-1, tSliderProjection.getValue()); controller.setProjectionRange(true); } catch (Exception ex) {} } } } else if (object.equals(projectionFrequency)) controller.setProjectionRange(true); } /** * Reacts to wheels moved event related to the {@link #zSlider}, * {@link #tSlider}, {@link #zSliderGrid} and {@link #zSliderGrid}. * @see MouseWheelListener#mouseWheelMoved(MouseWheelEvent) */ public void mouseWheelMoved(MouseWheelEvent e) { Object source = e.getSource(); if (source == zSlider && zSlider.isEnabled()) mouseWheelMovedZ(e); else if (source == tSlider && tSlider.isEnabled()) mouseWheelMovedT(e); else if (source == zSliderGrid && zSliderGrid.isEnabled()) mouseWheelMovedZ(e); else if (source == tSliderGrid && tSliderGrid.isEnabled()) mouseWheelMovedT(e); else if (source == lifetimeSlider && lifetimeSlider.isEnabled()) mouseWheelMovedLifetime(e); else if (source == lifetimeSliderGrid && lifetimeSliderGrid.isEnabled()) mouseWheelMovedLifetime(e); } /** * Notifies that the projection range has been modified. * @see PropertyChangeListener#propertyChange(PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent evt) { String name = evt.getPropertyName(); if (TwoKnobsSlider.RIGHT_MOVED_PROPERTY.equals(name) || TwoKnobsSlider.LEFT_MOVED_PROPERTY.equals(name)) controller.setProjectionRange(false); else if (TwoKnobsSlider.KNOB_RELEASED_PROPERTY.equals(name)) controller.setProjectionRange(true); else if (OneKnobSlider.ONE_KNOB_RELEASED_PROPERTY.equals(name)) { controller.setZoomFactor(ratioSlider.getValue()); } } }