/* *------------------------------------------------------------------------------ * Copyright (C) 2006-2015 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.Component; import java.awt.Frame; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowFocusListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; 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 java.util.Set; import javax.swing.Icon; import javax.swing.JMenu; import javax.swing.JTabbedPane; import javax.swing.WindowConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.MenuEvent; import javax.swing.event.MenuKeyEvent; import javax.swing.event.MenuKeyListener; import javax.swing.event.MenuListener; import org.openmicroscopy.shoola.agents.imviewer.IconManager; import org.openmicroscopy.shoola.agents.imviewer.ImViewerAgent; import org.openmicroscopy.shoola.agents.imviewer.actions.ActivityImageAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ChannelMovieAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ChannelsSelectionAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ClearHistoryAction; import org.openmicroscopy.shoola.agents.imviewer.actions.CloseAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ColorModelAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ColorPickerAction; import org.openmicroscopy.shoola.agents.imviewer.actions.CompressionAction; import org.openmicroscopy.shoola.agents.imviewer.actions.DetachAction; import org.openmicroscopy.shoola.agents.imviewer.actions.HistoryAction; import org.openmicroscopy.shoola.agents.imviewer.actions.LensAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ManageRndSettingsAction; import org.openmicroscopy.shoola.agents.imviewer.actions.MetadataAction; import org.openmicroscopy.shoola.agents.imviewer.actions.MovieAction; import org.openmicroscopy.shoola.agents.imviewer.actions.PlayMovieAction; import org.openmicroscopy.shoola.agents.imviewer.actions.PreferencesAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ProjectionProjectAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ROIToolAction; import org.openmicroscopy.shoola.agents.imviewer.actions.RefreshAction; import org.openmicroscopy.shoola.agents.imviewer.actions.RendererAction; import org.openmicroscopy.shoola.agents.imviewer.actions.SaveAction; import org.openmicroscopy.shoola.agents.imviewer.actions.SaveRndSettingsAction; import org.openmicroscopy.shoola.agents.imviewer.actions.ShowViewAction; import org.openmicroscopy.shoola.agents.imviewer.actions.TextVisibleAction; import org.openmicroscopy.shoola.agents.imviewer.actions.UnitBarAction; import org.openmicroscopy.shoola.agents.imviewer.actions.UnitBarSizeAction; import org.openmicroscopy.shoola.agents.imviewer.actions.UserAction; 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.util.ChannelColorMenuItem; import org.openmicroscopy.shoola.agents.imviewer.util.PlaneInfoComponent; import org.openmicroscopy.shoola.agents.imviewer.util.PreferencesDialog; import org.openmicroscopy.shoola.agents.imviewer.util.UnitBarSizeDialog; import org.openmicroscopy.shoola.agents.imviewer.util.player.MoviePlayerDialog; import org.openmicroscopy.shoola.agents.imviewer.util.proj.ProjSavingDialog; import org.openmicroscopy.shoola.agents.imviewer.util.proj.ProjectionRef; import org.openmicroscopy.shoola.agents.metadata.view.MetadataViewer; import org.openmicroscopy.shoola.agents.util.ui.ChannelButton; import org.openmicroscopy.shoola.env.Environment; import org.openmicroscopy.shoola.env.LookupNames; import org.openmicroscopy.shoola.env.data.model.DownloadActivityParam; import org.openmicroscopy.shoola.env.data.model.DownloadAndLaunchActivityParam; import org.openmicroscopy.shoola.env.data.model.FigureActivityParam; import org.openmicroscopy.shoola.env.data.model.FigureParam; import org.openmicroscopy.shoola.env.data.model.ScriptActivityParam; import org.openmicroscopy.shoola.env.data.model.ScriptObject; import org.openmicroscopy.shoola.env.ui.UserNotifier; import org.openmicroscopy.shoola.util.ui.ClosableTabbedPaneComponent; import org.openmicroscopy.shoola.util.ui.LoadingWindow; import org.openmicroscopy.shoola.util.ui.UIUtilities; import org.openmicroscopy.shoola.util.ui.colourpicker.ColourPicker; import org.openmicroscopy.shoola.util.ui.filechooser.FileChooser; import org.openmicroscopy.shoola.util.ui.lens.LensComponent; import org.openmicroscopy.shoola.util.ui.tdialog.TinyDialog; import omero.gateway.model.DataObject; import omero.gateway.model.DatasetData; import omero.gateway.model.ExperimenterData; import omero.gateway.model.ImageData; import omero.gateway.model.PixelsData; import omero.gateway.model.WellSampleData; /** * The ImViewer's Controller. * * @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 ImViewerControl implements ActionListener, ChangeListener, ComponentListener, PropertyChangeListener, WindowFocusListener { /** Identifies the <code>Close</code> action in the menu. */ static final Integer CLOSE = Integer.valueOf(0); /** Identifies the <code>Renderer</code> action in the menu. */ static final Integer RENDERER = Integer.valueOf(1); /** Identifies the <code>Movie</code> action in the menu. */ static final Integer MOVIE = Integer.valueOf(2); /** Identifies the <code>Save</code> action in the menu. */ static final Integer SAVE = Integer.valueOf(3); /** Identifies the <code>Zooming 25%</code> action in the menu. */ static final Integer ZOOM_25 = Integer.valueOf(4); /** Identifies the <code>Zooming 50%</code> action in the menu. */ static final Integer ZOOM_50 = Integer.valueOf(5); /** Identifies the <code>Zooming 75%</code> action in the menu. */ static final Integer ZOOM_75 = Integer.valueOf(6); /** Identifies the <code>Zooming 100%</code> action in the menu. */ static final Integer ZOOM_100 = Integer.valueOf(7); /** Identifies the <code>Zooming 125%</code> action in the menu. */ static final Integer ZOOM_125 = Integer.valueOf(8); /** Identifies the <code>Zooming 150%</code> action in the menu. */ static final Integer ZOOM_150 = Integer.valueOf(9); /** Identifies the <code>Zooming 175%</code> action in the menu. */ static final Integer ZOOM_175 = Integer.valueOf(10); /** Identifies the <code>Zooming 200%</code> action in the menu. */ static final Integer ZOOM_200 = Integer.valueOf(11); /** Identifies the <code>Zooming 225%</code> action in the menu. */ static final Integer ZOOM_225 = Integer.valueOf(12); /** Identifies the <code>Zooming 250%</code> action in the menu. */ static final Integer ZOOM_250 = Integer.valueOf(13); /** Identifies the <code>Zooming 275%</code> action in the menu. */ static final Integer ZOOM_275 = Integer.valueOf(14); /** Identifies the <code>Zooming 300%</code> action in the menu. */ static final Integer ZOOM_300 = Integer.valueOf(15); /** Identifies the <code>Zooming Fit to Window</code> action in the menu. */ static final Integer ZOOM_FIT_TO_WINDOW = Integer.valueOf(16); /** Identifies the <code>Lens</code> action in the menu. */ static final Integer LENS = Integer.valueOf(17); /** Identifies the <code>Grey Scale</code> action in the menu. */ static final Integer GREY_SCALE_MODEL = Integer.valueOf(18); /** Identifies the <code>RGB</code> action in the menu. */ static final Integer RGB_MODEL = Integer.valueOf(19); /** Identifies the <code>HSB</code> action in the menu. */ static final Integer HSB_MODEL = Integer.valueOf(20); /** * Identifies the <code>Channel movie</code> action in the * menu. */ static final Integer CHANNEL_MOVIE = Integer.valueOf(26); /** Identifies the <code>UnitBar</code> action in the menu. */ static final Integer UNIT_BAR = Integer.valueOf(27); /** Identifies the <code>Size one of the unit bar</code> action. */ static final Integer UNIT_BAR_ONE = Integer.valueOf(28); /** Identifies the <code>Size two of the unit bar</code> action. */ static final Integer UNIT_BAR_TWO = Integer.valueOf(29); /** Identifies the <code>Size five of the unit bar</code> action. */ static final Integer UNIT_BAR_FIVE = Integer.valueOf(30); /** Identifies the <code>Size ten of the unit bar</code> action. */ static final Integer UNIT_BAR_TEN = Integer.valueOf(31); /** Identifies the <code>Size twenty of the unit bar</code> action. */ static final Integer UNIT_BAR_TWENTY = Integer.valueOf(32); /** Identifies the <code>Size fifty of the unit bar</code> action. */ static final Integer UNIT_BAR_FIFTY = Integer.valueOf(33); /** Identifies the <code>Size hundred of the unit bar</code> action. */ static final Integer UNIT_BAR_HUNDRED = Integer.valueOf(34); /** Identifies the <code>customized size of the unit bar</code> action. */ static final Integer UNIT_BAR_CUSTOM = Integer.valueOf(35); /** Identifies the <code>color Picker</code> action. */ static final Integer COLOR_PICKER = Integer.valueOf(36); /** Identifies the <code>text visible</code> action in the menu. */ static final Integer TEXT_VISIBLE = Integer.valueOf(38); /** Identifies the <code>Measurement tool</code> action in the menu. */ static final Integer MEASUREMENT_TOOL = Integer.valueOf(39); /** Identifies the <code>Play movie across T</code> action. */ static final Integer PLAY_MOVIE_T = Integer.valueOf(44); /** Identifies the <code>Play movie across Z</code> action. */ static final Integer PLAY_MOVIE_Z = Integer.valueOf(45); /** Identifies the <code>Preferences</code> action. */ static final Integer PREFERENCES = Integer.valueOf(47); /** Identifies the <code>User</code> action. */ static final Integer USER = Integer.valueOf(48); /** * Identifies the <code>Zooming 25%</code> action of the grid image * in the menu. */ static final Integer ZOOM_GRID_25 = Integer.valueOf(49); /** * Identifies the <code>Zooming 50%</code> action of the grid image * in the menu. */ static final Integer ZOOM_GRID_50 = Integer.valueOf(50); /** * Identifies the <code>Zooming 75%</code> action of the grid image * in the menu. */ static final Integer ZOOM_GRID_75 = Integer.valueOf(51); /** * Identifies the <code>Zooming 100%</code> action of the grid image * in the menu. */ static final Integer ZOOM_GRID_100 = Integer.valueOf(52); /** Identifies the <code>View tab</code> action. */ static final Integer TAB_VIEW = Integer.valueOf(54); /** Identifies the <code>Projection tab</code> action. */ static final Integer TAB_PROJECTION = Integer.valueOf(55); /** Identifies the <code>Grid tab</code> action. */ static final Integer TAB_GRID = Integer.valueOf(56); /** Identifies the <code>History</code> action. */ static final Integer HISTORY = Integer.valueOf(57); /** Identifies the <code>Paste rendering settings</code> action. */ static final Integer PASTE_RND_SETTINGS = Integer.valueOf(58); /** Identifies the <code>Copy rendering settings</code> action. */ static final Integer COPY_RND_SETTINGS = Integer.valueOf(59); /** Identifies the <code>Save rendering settings</code> action. */ static final Integer SAVE_RND_SETTINGS = Integer.valueOf(60); /** Identifies the <code>Reset rendering settings</code> action. */ static final Integer RESET_RND_SETTINGS = Integer.valueOf(61); /** * Identifies the <code>Set the rendering settings to min max</code> action. */ static final Integer SET_RND_SETTINGS_MIN_MAX = Integer.valueOf(62); /** * Identifies the <code>Set the rendering settings to owner's * settings</code> action. */ static final Integer SET_OWNER_RND_SETTINGS= Integer.valueOf(63); /** Identifies the <code>Undo rendering settings</code> action. */ static final Integer UNDO_RND_SETTINGS = Integer.valueOf(64); /** Identifies the <code>Projection project</code> action. */ static final Integer PROJECTION_PROJECT = Integer.valueOf(66); /** Identifies the <code>Compression</code> action. */ static final Integer COMPRESSION = Integer.valueOf(67); /** Identifies the <code>Clear history</code> action. */ static final Integer CLEAR_HISTORY = Integer.valueOf(68); /** Identifies the <code>Metadata</code> action in the menu. */ static final Integer METADATA = Integer.valueOf(69); /** Identifies the <code>Play movie across life time bin</code> action. */ static final Integer PLAY_LIFETIME_MOVIE = Integer.valueOf(70); /** Identifies the <code>Channels On</code> action. */ static final Integer CHANNELS_ON = Integer.valueOf(71); /** Identifies the <code>Channels Off</code> action. */ static final Integer CHANNELS_OFF = Integer.valueOf(72); /** Identifies the <code>Activity</code> action. */ static final Integer ACTIVITY = Integer.valueOf(73); /** Identifies the <code>Detach</code> action. */ static final Integer DETACH = Integer.valueOf(74); /** Identifies the <code>Refresh</code> action. */ static final Integer REFRESH = Integer.valueOf(75); /** * Reference to the {@link ImViewer} component, which, in this context, * is regarded as the Model. */ private ImViewer model; /** Reference to the View. */ private ImViewerUI view; /** Maps actions identifiers onto actual <code>Action</code> object. */ private Map<Integer, ViewerAction> actionsMap; /** Keep track of the old state.*/ private int historyState; /** Index of the channel invoking the color picker. */ private int colorPickerIndex; /** Reference to the movie player. */ private MoviePlayerDialog moviePlayer; /** Helper method to create all the UI actions. */ private void createActions() { actionsMap.put(RENDERER, new RendererAction(model)); actionsMap.put(MOVIE, new MovieAction(model)); actionsMap.put(SAVE, new SaveAction(model)); actionsMap.put(ZOOM_25, new ZoomAction(model, ZoomAction.ZOOM_25)); actionsMap.put(ZOOM_50, new ZoomAction(model, ZoomAction.ZOOM_50)); actionsMap.put(ZOOM_75, new ZoomAction(model, ZoomAction.ZOOM_75)); actionsMap.put(ZOOM_100, new ZoomAction(model, ZoomAction.ZOOM_100)); actionsMap.put(ZOOM_125, new ZoomAction(model, ZoomAction.ZOOM_125)); actionsMap.put(ZOOM_150, new ZoomAction(model, ZoomAction.ZOOM_150)); actionsMap.put(ZOOM_175, new ZoomAction(model, ZoomAction.ZOOM_175)); actionsMap.put(ZOOM_200, new ZoomAction(model, ZoomAction.ZOOM_200)); actionsMap.put(ZOOM_225, new ZoomAction(model, ZoomAction.ZOOM_225)); actionsMap.put(ZOOM_250, new ZoomAction(model, ZoomAction.ZOOM_250)); actionsMap.put(ZOOM_275, new ZoomAction(model, ZoomAction.ZOOM_275)); actionsMap.put(ZOOM_300, new ZoomAction(model, ZoomAction.ZOOM_300)); actionsMap.put(ZOOM_FIT_TO_WINDOW, new ZoomAction(model, ZoomAction.ZOOM_FIT_TO_WINDOW)); actionsMap.put(LENS, new LensAction(model)); actionsMap.put(GREY_SCALE_MODEL, new ColorModelAction(model, ColorModelAction.GREY_SCALE_MODEL)); actionsMap.put(RGB_MODEL, new ColorModelAction(model, ColorModelAction.RGB_MODEL)); actionsMap.put(HSB_MODEL, new ColorModelAction(model, ColorModelAction.HSB_MODEL)); actionsMap.put(CHANNEL_MOVIE, new ChannelMovieAction(model)); actionsMap.put(UNIT_BAR, new UnitBarAction(model)); actionsMap.put(UNIT_BAR_ONE, new UnitBarSizeAction(model, UnitBarSizeAction.ONE)); actionsMap.put(UNIT_BAR_TWO, new UnitBarSizeAction(model, UnitBarSizeAction.TWO)); actionsMap.put(UNIT_BAR_FIVE, new UnitBarSizeAction(model, UnitBarSizeAction.FIVE)); actionsMap.put(UNIT_BAR_TEN, new UnitBarSizeAction(model, UnitBarSizeAction.TEN)); actionsMap.put(UNIT_BAR_TWENTY, new UnitBarSizeAction(model, UnitBarSizeAction.TWENTY)); actionsMap.put(UNIT_BAR_FIFTY, new UnitBarSizeAction(model, UnitBarSizeAction.FIFTY)); actionsMap.put(UNIT_BAR_HUNDRED, new UnitBarSizeAction(model, UnitBarSizeAction.HUNDRED)); actionsMap.put(UNIT_BAR_CUSTOM, new UnitBarSizeAction(model, UnitBarSizeAction.CUSTOMIZED)); actionsMap.put(COLOR_PICKER, new ColorPickerAction(model)); actionsMap.put(TEXT_VISIBLE, new TextVisibleAction(model)); actionsMap.put(MEASUREMENT_TOOL, new ROIToolAction(model)); actionsMap.put(PLAY_MOVIE_T, new PlayMovieAction(model, PlayMovieAction.ACROSS_T)); actionsMap.put(PLAY_MOVIE_Z, new PlayMovieAction(model, PlayMovieAction.ACROSS_Z)); actionsMap.put(PREFERENCES, new PreferencesAction(model)); actionsMap.put(USER, new UserAction(model)); actionsMap.put(ZOOM_GRID_25, new ZoomGridAction(model, ZoomGridAction.ZOOM_25)); actionsMap.put(ZOOM_GRID_50, new ZoomGridAction(model, ZoomGridAction.ZOOM_50)); actionsMap.put(ZOOM_GRID_75, new ZoomGridAction(model, ZoomGridAction.ZOOM_75)); actionsMap.put(ZOOM_GRID_100, new ZoomGridAction(model, ZoomGridAction.ZOOM_100)); actionsMap.put(TAB_VIEW, new ShowViewAction(model, ShowViewAction.VIEW)); actionsMap.put(TAB_PROJECTION, new ShowViewAction(model, ShowViewAction.PROJECTION)); actionsMap.put(TAB_GRID, new ShowViewAction(model, ShowViewAction.SPLIT)); actionsMap.put(HISTORY, new HistoryAction(model)); actionsMap.put(PASTE_RND_SETTINGS, new ManageRndSettingsAction(model, ManageRndSettingsAction.PASTE)); actionsMap.put(COPY_RND_SETTINGS, new ManageRndSettingsAction(model, ManageRndSettingsAction.COPY)); actionsMap.put(SAVE_RND_SETTINGS, new SaveRndSettingsAction(model)); actionsMap.put(RESET_RND_SETTINGS, new ManageRndSettingsAction(model, ManageRndSettingsAction.RESET)); actionsMap.put(SET_OWNER_RND_SETTINGS, new ManageRndSettingsAction(model, ManageRndSettingsAction.SET_OWNER)); actionsMap.put(SET_RND_SETTINGS_MIN_MAX, new ManageRndSettingsAction(model, ManageRndSettingsAction.SET_MIN_MAX)); actionsMap.put(UNDO_RND_SETTINGS, new ManageRndSettingsAction(model, ManageRndSettingsAction.UNDO)); actionsMap.put(PROJECTION_PROJECT, new ProjectionProjectAction(model)); actionsMap.put(COMPRESSION, new CompressionAction(model)); actionsMap.put(CLEAR_HISTORY, new ClearHistoryAction(model)); actionsMap.put(METADATA, new MetadataAction(model)); actionsMap.put(CHANNELS_ON, new ChannelsSelectionAction(model, true)); actionsMap.put(CHANNELS_OFF, new ChannelsSelectionAction(model, false)); actionsMap.put(ACTIVITY, new ActivityImageAction(model)); actionsMap.put(CLOSE, new CloseAction(model)); actionsMap.put(DETACH, new DetachAction(model)); actionsMap.put(REFRESH, new RefreshAction(model)); actionsMap.put(PLAY_LIFETIME_MOVIE, new PlayMovieAction(model, PlayMovieAction.ACROSS_LIFETIME)); } /** * Attaches a window listener to the view to discard the model when * the user closes the window. */ private void attachListeners() { model.addChangeListener(this); model.addPropertyChangeListener(this); JMenu menu = ImViewerFactory.getWindowMenu(); menu.addMenuListener(new MenuListener() { public void menuSelected(MenuEvent e) { Object source = e.getSource(); if (source instanceof JMenu) ImViewerFactory.register((JMenu) source); } /** * Required by I/F but not actually needed in our case, * no-operation implementation. * @see MenuListener#menuCanceled(MenuEvent) */ public void menuCanceled(MenuEvent e) {} /** * Required by I/F but not actually needed in our case, * no-operation implementation. * @see MenuListener#menuDeselected(MenuEvent) */ public void menuDeselected(MenuEvent e) {} }); //Listen to keyboard selection menu.addMenuKeyListener(new MenuKeyListener() { public void menuKeyReleased(MenuKeyEvent e) { Object source = e.getSource(); if (source instanceof JMenu) ImViewerFactory.register((JMenu) source); } /** * Required by I/F but not actually needed in our case, * no-operation implementation. * @see MenuKeyListener#menuKeyPressed(MenuKeyEvent) */ public void menuKeyPressed(MenuKeyEvent e) {} /** * Required by I/F but not actually needed in our case, * no-operation implementation. * @see MenuKeyListener#menuKeyTyped(MenuKeyEvent) */ public void menuKeyTyped(MenuKeyEvent e) {} }); view.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); view.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { model.close(true); } public void windowDeiconified(WindowEvent e) { model.iconified(false); } public void windowIconified(WindowEvent e) { model.iconified(true); } //public void windowOpened(WindowEvent e) //{ view.addWindowFocusListener(this); } }); view.getLoadingWindow().addPropertyChangeListener( LoadingWindow.CANCEL_LOADING_PROPERTY, this); view.addWindowFocusListener(this); } /** Uploads the script.*/ private void uploadScript() { /* Map<Long, String> map; Registry reg = ImViewerAgent.getRegistry(); try { //TODO: asynchronous call instead map = reg.getImageService().getScriptsAsString(); } catch (Exception e) { String s = "Data Retrieval Failure: "; LogMessage msg = new LogMessage(); msg.print(s); msg.print(e); reg.getLogger().error(this, msg); map = new HashMap<Long, String>(); } ScriptUploaderDialog dialog = new ScriptUploaderDialog(model.getUI() , map, ImViewerAgent.getRegistry()); dialog.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { Object o = evt.getNewValue(); if (o instanceof ScriptObject) { ScriptObject script = (ScriptObject) o; UserNotifier un = ImViewerAgent.getRegistry().getUserNotifier(); if (script == null) { un.notifyInfo("Upload Script", "No script to upload"); return; } ScriptActivityParam p = new ScriptActivityParam(script, ScriptActivityParam.UPLOAD); un.notifyActivity(p); } } }); UIUtilities.centerAndShow(dialog); */ } /** * Downloads the possible script. * * @param param The parameter holding the script. */ private void downloadScript(ScriptActivityParam param) { FileChooser chooser = new FileChooser(view, FileChooser.SAVE, "Download", "Select where to download the file.", null, true); IconManager icons = IconManager.getInstance(); chooser.setTitleIcon(icons.getIcon(IconManager.DOWNLOAD_48)); chooser.setSelectedFileFull(param.getScript().getName()); chooser.setApproveButtonText("Download"); final long id = param.getScript().getScriptID(); chooser.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { String name = evt.getPropertyName(); if (FileChooser.APPROVE_SELECTION_PROPERTY.equals(name)) { File[] files = (File[]) evt.getNewValue(); File folder = files[0]; IconManager icons = IconManager.getInstance(); DownloadActivityParam activity; activity = new DownloadActivityParam(id, DownloadActivityParam.ORIGINAL_FILE, folder, icons.getIcon(IconManager.DOWNLOAD_22)); UserNotifier un = ImViewerAgent.getRegistry().getUserNotifier(); un.notifyActivity(model.getSecurityContext(), activity); } } }); chooser.centerDialog(); } /** * Creates a new instance. * The {@link #initialize(ImViewerComponent, ImViewerUI) initialize} * method should be called straight * after to link this Controller to the other MVC components. */ ImViewerControl() {} /** * Links this Controller to its Model and its View. * * @param model Reference to the {@link ImViewer} component, which, in * this context, is regarded as the Model. * Mustn't be <code>null</code>. * @param view Reference to the View. Mustn't be <code>null</code>. */ void initialize(ImViewer model, ImViewerUI view) { if (model == null) throw new NullPointerException("No model."); if (view == null) throw new NullPointerException("No view."); this.model = model; this.view = view; historyState = -1; colorPickerIndex = -1; actionsMap = new HashMap<Integer, ViewerAction>(); createActions(); attachListeners(); ImViewerFactory.attachWindowMenuToTaskBar(); } /** * Returns the action corresponding to the specified id. * * @param id One of the flags defined by this class. * @return The specified action. */ ViewerAction getAction(Integer id) { return actionsMap.get(id); } /** * Returns the action corresponding to the levels. This method should * only be used for big image. * * @param levels The levels to handle. * @return See above. */ ViewerAction getZoomActionFromLevels(int levels) { switch (levels) { case ZoomAction.ZOOM_50: return getAction(ZOOM_50); case ZoomAction.ZOOM_75: return getAction(ZOOM_75); case ZoomAction.ZOOM_100: return getAction(ZOOM_100); case ZoomAction.ZOOM_125: return getAction(ZOOM_125); case ZoomAction.ZOOM_150: return getAction(ZOOM_150); case ZoomAction.ZOOM_200: return getAction(ZOOM_200); case ZoomAction.ZOOM_225: return getAction(ZOOM_225); case ZoomAction.ZOOM_250: return getAction(ZOOM_250); case ZoomAction.ZOOM_275: return getAction(ZOOM_275); case ZoomAction.ZOOM_300: return getAction(ZOOM_300); } return null; } /** * Renders the specified XY-Plane. * * @param z The selected z-section. * @param t The selected timepoint. * @param bin The selected bin, only used for lifetime. */ void setSelectedXYPlane(int z, int t, int bin) { boolean enableSave = z != model.getDefaultZ() || t != model.getDefaultT(); model.setSelectedXYPlane(z, t, bin); if (enableSave) actionsMap.get(SAVE_RND_SETTINGS).setEnabled(true); } /** * Returns the previous state. * * @return See above. */ int getHistoryState() { return historyState; } /** * Sets the previous state. * * @param s The value to set. */ void setHistoryState(int s) { historyState = s; } /** * Brings up the color picker. Initializes the color picker with * the color associated to the selected channel. * * @param index The index of the selected channel. */ void showColorPicker(int index) { colorPickerIndex = index; Color c = model.getChannelColor(index); ColourPicker dialog = new ColourPicker(view, c); dialog.setPreviewVisible(true); dialog.addPropertyChangeListener(this); UIUtilities.setLocationRelativeToAndShow(view, dialog); } /** * Initializes the movie player if required. * or recycles it. * * @return See above. */ MoviePlayerDialog getMoviePlayer() { if (moviePlayer != null) return moviePlayer; moviePlayer = new MoviePlayerDialog(view, model); moviePlayer.addPropertyChangeListener(MoviePlayerDialog.CLOSE_PROPERTY, this); return moviePlayer; } /** * Sets the zoom factor corresponding to the passed index. * * @param zoomIndex The index to handle. */ void setZoomFactor(int zoomIndex) { double f = ZoomAction.getZoomFactor(zoomIndex); model.setZoomFactor(f, zoomIndex); } /** * Moves the view to the front, to avoid loops, first removes the * WindowFocusListener. */ void toFront() { if (view.getExtendedState() != Frame.NORMAL) return; if (!view.isFocused()) { view.removeWindowFocusListener(this); view.setVisible(true); //view.addWindowFocusListener(this); } } /** Sets the preferences before closing. */ void setPreferences() { ViewerPreferences pref = ImViewerFactory.getPreferences(); if (pref == null) pref = new ViewerPreferences(); Rectangle bounds = view.getBounds(); if (bounds != null) pref.setViewerBounds(bounds); int index = view.getZoomIndex(); if (index > 0) pref.setZoomIndex(index); pref.setRenderer(view.isRendererShown()); pref.setHistory(view.isHistoryShown()); Color c = model.getUnitBarColor(); if (c != null) pref.setScaleBarColor(c); index = view.getScaleBarIndex(); if (index > 0) pref.setScaleBarIndex(index); pref.setInterpolation(model.isInterpolation()); ImViewerFactory.setPreferences(pref); } /** * Sets the zoom factor for the grid view. * * @param factor The value to set. */ void setGridMagnificationFactor(double factor) { model.setGridMagnificationFactor(factor); } /** * Sets the interval of z-sections to project. * * @param released Pass <code>true</code> if the knob is released, * <code>false</code> otherwise. */ void setProjectionRange(boolean released) { view.setLeftStatus(); view.setPlaneInfoStatus(); if (released) model.renderXYPlane(); } /** * Renders the overlays. * * @param selected Pass <code>true</code> if the overlays have to be * displayed, <code>false</code> otherwise. */ void renderOverlays(boolean selected) { model.renderOverlays(-1, selected); } /** * Reacts to change fired by buttons used to select the color * models. * @see ActionListener#actionPerformed(ActionEvent) */ public void actionPerformed(ActionEvent e) { String m = model.getColorModel(); ViewerAction a = null; if (ImViewer.RGB_MODEL.equals(m)) { a = getAction(ImViewerControl.GREY_SCALE_MODEL); a.actionPerformed(e); } else if (ImViewer.GREY_SCALE_MODEL.equals(m)) { a = getAction(ImViewerControl.RGB_MODEL); a.actionPerformed(e); } } /** * Reacts to state changes in the {@link ImViewer}. * @see ChangeListener#stateChanged(ChangeEvent) */ public void stateChanged(ChangeEvent e) { if (e.getSource() instanceof JTabbedPane) { JTabbedPane pane = (JTabbedPane) e.getSource(); Component c = pane.getSelectedComponent(); if (c instanceof ClosableTabbedPaneComponent) { int index = ((ClosableTabbedPaneComponent) c).getIndex(); model.setSelectedPane(index); } return; } int state = model.getState(); LoadingWindow window = view.getLoadingWindow(); switch (state) { case ImViewer.DISCARDED: window.close(); view.setVisible(false); if (view.isLensVisible()) view.setLensVisible(false, model.getSelectedIndex()); view.dispose(); historyState = state; break; case ImViewer.LOADING_RND: case ImViewer.LOADING_BIRD_EYE_VIEW: if (!window.isVisible()) UIUtilities.centerAndShow(window); break; case ImViewer.CANCELLED: window.setVisible(false); case ImViewer.LOADING_IMAGE: if (historyState == ImViewer.LOADING_METADATA) window.setVisible(false); view.onStateChange(false); window.setVisible(false); /* window = view.getLoadingWindow(); if (!window.isVisible()) UIUtilities.centerAndShow(window); */ historyState = state; break; case ImViewer.PROJECTING: case ImViewer.PROJECTION_PREVIEW: case ImViewer.PASTING: view.setStatus(true); view.onStateChange(false); break; case ImViewer.READY: view.setStatus(false); window.setVisible(false); if (historyState == ImViewer.CHANNEL_MOVIE) view.onStateChange(false); else { view.onStateChange(true); historyState = state; } break; case ImViewer.LOADING_TILES: window.setVisible(false); view.onStateChange(false); break; case ImViewer.CHANNEL_MOVIE: historyState = ImViewer.CHANNEL_MOVIE; view.onStateChange(false); } } /** * Reacts to property changes in the {@link ImViewer}. * @see PropertyChangeListener#propertyChange(PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent pce) { String pName = pce.getPropertyName(); if (ImViewer.Z_SELECTED_PROPERTY.equals(pName)) { view.setZSection(((Integer) pce.getNewValue()).intValue()); } else if (ImViewer.T_SELECTED_PROPERTY.equals(pName)) { view.setTimepoint(((Integer) pce.getNewValue()).intValue()); } else if (ImViewer.BIN_SELECTED_PROPERTY.equals(pName)) { view.setBin(((Integer) pce.getNewValue()).intValue()); } else if (ChannelButton.CHANNEL_SELECTED_PROPERTY.equals(pName)) { Map map = (Map) pce.getNewValue(); if (map == null) return; if (map.size() != 1) return; Set set = map.entrySet(); Entry entry = (Entry) map.entrySet().iterator().next(); Integer index = (Integer) entry.getKey(); model.setChannelSelection(index.intValue(), (Boolean) entry.getValue()); } else if (ChannelButton.CHANNEL_OVERLAY_PROPERTY.equals(pName)) { Map map = (Map) pce.getNewValue(); if (map == null) return; if (map.size() != 1) return; Set set = map.entrySet(); Entry entry; Iterator i = set.iterator(); Integer index; while (i.hasNext()) { entry = (Entry) i.next(); index = (Integer) entry.getKey(); model.renderOverlays(index.intValue(), (Boolean) entry.getValue()); } } else if (LoadingWindow.CANCEL_LOADING_PROPERTY.equals(pName)) { model.cancelInit(); } else if (MetadataViewer.RENDER_PLANE_PROPERTY.equals(pName)) { model.renderXYPlane(); } else if (MetadataViewer.RND_LOADED_PROPERTY.equals(pName)) { boolean b = (Boolean) pce.getNewValue(); model.onRndLoaded(b); } else if (ChannelColorMenuItem.CHANNEL_COLOR_PROPERTY.equals(pName)) { model.showColorPicker(((Integer) pce.getNewValue()).intValue()); } else if (ChannelButton.CHANNEL_COLOUR_PROPERTY.equals(pName) || ChannelColorMenuItem.CHANNEL_COLOR_PROPERTY.equals(pName)) { if (view.isSourceDisplayed(pce.getSource())) model.showColorPicker(((Integer) pce.getNewValue()).intValue()); } else if (ColourPicker.COLOUR_PROPERTY.equals(pName)) { Color c = (Color) pce.getNewValue(); if (colorPickerIndex != -1) { model.setChannelColor(colorPickerIndex, c, false); } } else if (ColourPicker.COLOUR_PREVIEW_PROPERTY.equals(pName)) { Color c = (Color) pce.getNewValue(); if (colorPickerIndex != -1) { model.setChannelColor(colorPickerIndex, c, true); } } else if (ColourPicker.CANCEL_PROPERTY.equals(pName)) { model.setChannelColor(colorPickerIndex, null, true); } else if (UnitBarSizeDialog.UNIT_BAR_VALUE_PROPERTY.equals(pName)) { double v = ((Double) pce.getNewValue()).doubleValue(); model.setUnitBarSize(v); } else if (ImViewer.ICONIFIED_PROPERTY.equals(pName)) { if (moviePlayer != null) model.playMovie(false, false, -1); view.onIconified(); } else if (LensComponent.LENS_LOCATION_PROPERTY.equals(pName)) { view.scrollToNode((Rectangle) pce.getNewValue()); } else if (MoviePlayerDialog.CLOSE_PROPERTY.equals(pName)) { model.playMovie(false, false, -1); } else if (MoviePlayerDialog.MOVIE_STATE_CHANGED_PROPERTY.equals(pName)) { //when movie player stop boolean b = ((Boolean) pce.getNewValue()).booleanValue(); if (!b) { if (!getMoviePlayer().isVisible()) { PlayMovieAction action = (PlayMovieAction) getAction(PLAY_MOVIE_T); action.setActionIcon(true); action = (PlayMovieAction) getAction(PLAY_MOVIE_Z); action.setActionIcon(true); action = (PlayMovieAction) getAction(PLAY_LIFETIME_MOVIE); action.setActionIcon(true); model.playMovie(false, false, -1); } } } else if (PreferencesDialog.VIEWER_PREF_PROPERTY.equals(pName)) { Map map = (Map) pce.getNewValue(); if (map == null) ImViewerFactory.setPreferences(null); ViewerPreferences pref = ImViewerFactory.getPreferences(); if (pref == null) pref = new ViewerPreferences(); pref.setSelectedFields(map); ImViewerFactory.setPreferences(pref); } else if (UsersPopupMenu.USER_RNDSETTINGS_PROPERTY.equals(pName)) { ExperimenterData exp = (ExperimenterData) pce.getNewValue(); model.setUserRndSettings(exp); } else if (ProjSavingDialog.PROJECTION_PROPERTY.equals(pName)) { model.projectImage((ProjectionRef) pce.getNewValue()); } else if (PlaneInfoComponent.PLANE_INFO_PROPERTY.equals(pName)) { view.showPlaneInfoDetails((PlaneInfoComponent) pce.getNewValue()); } else if (TinyDialog.CLOSED_PROPERTY.equals(pName)) { view.hideAnimation(); } else if (ProjSavingDialog.LOAD_ALL_PROPERTY.equals(pName)) { model.loadAllContainers(); } else if (MetadataViewer.SELECTED_CHANNEL_PROPERTY.equals(pName)) { int index = (Integer) pce.getNewValue(); model.onChannelSelection(index); } else if (MetadataViewer.CLOSE_RENDERER_PROPERTY.equals(pName)) { Object ref = pce.getNewValue(); ImageData image = null; if (ref instanceof ImageData) { image = (ImageData) ref; } else if (ref instanceof WellSampleData) { image = ((WellSampleData) ref).getImage(); } if (image != null) { PixelsData pixs = image.getDefaultPixels(); if (pixs != null && pixs.getId() == view.getPixelsID()) model.discard(); } } else if (MetadataViewer.CHANNEL_COLOR_CHANGED_PROPERTY.equals( pName)) { int index = (Integer) pce.getNewValue(); model.onChannelColorChanged(index); } else if (MetadataViewer.HANDLE_SCRIPT_PROPERTY.equals(pName)) { UserNotifier un = ImViewerAgent.getRegistry().getUserNotifier(); ScriptActivityParam p = (ScriptActivityParam) pce.getNewValue(); int index = p.getIndex(); ScriptObject script = p.getScript(); if (index == ScriptActivityParam.VIEW) { Environment env = (Environment) ImViewerAgent.getRegistry().lookup(LookupNames.ENV); String path = env.getOmeroFilesHome(); path += File.separator+script.getName(); File f = new File(path); DownloadAndLaunchActivityParam activity; activity = new DownloadAndLaunchActivityParam( p.getScript().getScriptID(), DownloadAndLaunchActivityParam.ORIGINAL_FILE, f, null); un.notifyActivity(model.getSecurityContext(), activity); } else if (index == ScriptActivityParam.DOWNLOAD) { downloadScript(p); } else { un.notifyActivity(model.getSecurityContext(), pce.getNewValue()); } } else if (MetadataViewer.UPLOAD_SCRIPT_PROPERTY.equals(pName)) { uploadScript(); } else if (MetadataViewer.GENERATE_FIGURE_PROPERTY.equals(pName)) { Object object = pce.getNewValue(); if (!(object instanceof FigureParam)) return; UserNotifier un = ImViewerAgent.getRegistry().getUserNotifier(); IconManager icons = IconManager.getInstance(); Icon icon = icons.getIcon(IconManager.SPLIT_VIEW_FIGURE_22); FigureActivityParam activity; List<Long> ids = new ArrayList<Long>(); Iterator i; DataObject obj; FigureParam param = (FigureParam) object; Class klass = null; Object p = null; if (param.getIndex() == FigureParam.THUMBNAILS) { klass = ImageData.class; p = view.getParentObject(); if (!(p instanceof DatasetData)) p = null; if (p != null) param.setAnchor((DataObject) p); } ids.add(view.getImageID()); // not set if (param.getIndex() != FigureParam.THUMBNAILS) param.setAnchor((DataObject) p); activity = new FigureActivityParam(object, ids, klass, FigureActivityParam.SPLIT_VIEW_FIGURE); activity.setIcon(icon); un.notifyActivity(model.getSecurityContext(), activity); } } /** * Captures the resize event of the {@link ImViewerUI}, if the user has * selected the zoom to fit to the window then resize the image to fit to * the new size of the image. * @see ComponentListener#componentResized(ComponentEvent) */ public void componentResized(ComponentEvent e) { //Review that code. if (model.isBigImage() && model.isRendererLoaded() ) { model.loadTiles(null); } else { if (model.isZoomFitToWindow()) model.setZoomFactor(-1, ZoomAction.ZOOM_FIT_TO_WINDOW); } view.onComponentResized(); view.maximizeWindow(); setPreferences(); } /** * Posts an event to bring the related window to the front. * @see WindowFocusListener#windowGainedFocus(WindowEvent) */ public void windowGainedFocus(WindowEvent e) { //model.refresh(); } /** * Required by the I/F but no-operation implementation in our case. * @see WindowFocusListener#windowLostFocus(WindowEvent) */ public void windowLostFocus(WindowEvent e) {} /** * Required by the {@link ComponentListener} I/F but no-operation * implementation in our case. * @see ComponentListener#componentShown(ComponentEvent) */ public void componentShown(ComponentEvent e) {} /** * Required by the {@link ComponentListener} I/F but no-operation * implementation in our case. * @see ComponentListener#componentHidden(ComponentEvent) */ public void componentHidden(ComponentEvent e) {} /** * Required by the {@link ComponentListener} I/F but no-operation * implementation in our case. * @see ComponentListener#componentMoved(ComponentEvent) */ public void componentMoved(ComponentEvent e) {} /** * Returns if interpolation is enabled or not * * @return */ boolean isInterpolation() { return model.isInterpolation(); } /** * En-/Disables interpolation * * @param interpolation */ void setInterpolation(boolean interpolation) { model.setInterpolation(interpolation); ImViewerFactory.setInterpolation(interpolation); } }