gt: 			edgeWidth = size-n*w;
context: /*
   * org.openmicroscopy.shoola.agents.iviewer.view.ImViewerModel
   *
   *------------------------------------------------------------------------------
   *  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;
  
  
  
  //Java imports
  import java.awt.Color;
  import java.awt.Component;
  import java.awt.Dimension;
  import java.awt.Point;
  import java.awt.Rectangle;
  import java.awt.Toolkit;
  import java.awt.image.BufferedImage;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.Comparator;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.LinkedHashMap;
  import java.util.List;
  import java.util.Map;
  
  import omero.model.Length;
  import omero.model.LengthI;
  import omero.model.PlaneInfo;
  import omero.model.enums.UnitsLength;
  import omero.romio.PlaneDef;
  
  import org.apache.commons.io.FilenameUtils;
  import org.openmicroscopy.shoola.agents.events.iviewer.CopyRndSettings;
  import org.openmicroscopy.shoola.agents.imviewer.AcquisitionDataLoader;
  import org.openmicroscopy.shoola.agents.imviewer.BirdEyeLoader;
  import org.openmicroscopy.shoola.agents.imviewer.ContainerLoader;
  import org.openmicroscopy.shoola.agents.imviewer.DataLoader;
  import org.openmicroscopy.shoola.agents.imviewer.ImViewerAgent;
  import org.openmicroscopy.shoola.agents.imviewer.ImageDataLoader;
  import org.openmicroscopy.shoola.agents.imviewer.ImageLoader;
  import org.openmicroscopy.shoola.agents.imviewer.MeasurementsLoader;
  import org.openmicroscopy.shoola.agents.imviewer.OverlaysRenderer;
  import org.openmicroscopy.shoola.agents.imviewer.PlaneInfoLoader;
  import org.openmicroscopy.shoola.agents.imviewer.ProjectionSaver;
  import org.openmicroscopy.shoola.agents.imviewer.RenderingSettingsCreator;
  import org.openmicroscopy.shoola.agents.imviewer.RenderingSettingsLoader;
  import org.openmicroscopy.shoola.agents.imviewer.TileLoader;
  import org.openmicroscopy.shoola.agents.imviewer.actions.ZoomAction;
  import org.openmicroscopy.shoola.agents.imviewer.browser.Browser;
  import org.openmicroscopy.shoola.agents.imviewer.browser.BrowserFactory;
  import org.openmicroscopy.shoola.agents.imviewer.util.HistoryItem;
  import org.openmicroscopy.shoola.agents.imviewer.util.player.ChannelPlayer;
  import org.openmicroscopy.shoola.agents.imviewer.util.player.Player;
  import org.openmicroscopy.shoola.agents.imviewer.util.proj.ProjectionRef;
  import org.openmicroscopy.shoola.agents.metadata.rnd.Renderer;
  import org.openmicroscopy.shoola.agents.metadata.view.MetadataViewer;
  import org.openmicroscopy.shoola.agents.metadata.view.MetadataViewerFactory;
  import org.openmicroscopy.shoola.agents.util.EditorUtil;
  import org.openmicroscopy.shoola.env.LookupNames;
  import org.openmicroscopy.shoola.env.data.OmeroImageService;
  import org.openmicroscopy.shoola.env.data.model.ProjectionParam;
  
  import omero.gateway.SecurityContext;
  import omero.gateway.exception.DSOutOfServiceException;
  import omero.gateway.exception.RenderingServiceException;
  import omero.gateway.model.TableResult;
  
  import org.openmicroscopy.shoola.env.event.EventBus;
  import org.openmicroscopy.shoola.env.rnd.RenderingControl;
  import org.openmicroscopy.shoola.env.rnd.RndProxyDef;
  import org.openmicroscopy.shoola.env.rnd.data.Region;
  import org.openmicroscopy.shoola.env.rnd.data.ResolutionLevel;
  import org.openmicroscopy.shoola.env.rnd.data.Tile;
  import org.openmicroscopy.shoola.util.CommonsLangUtils;
  import org.openmicroscopy.shoola.util.file.modulo.ModuloInfo;
  import org.openmicroscopy.shoola.util.image.geom.Factory;
  import org.openmicroscopy.shoola.util.ui.UIUtilities;
  
  import pojos.ChannelData;
  import pojos.DataObject;
  import pojos.ExperimenterData;
  import pojos.GroupData;
  import pojos.ImageData;
  import pojos.ObjectiveData;
  import pojos.PixelsData;
  import pojos.WellData;
  import pojos.WellSampleData;
  
  /** 
  * The Model component in the <code>ImViewer</code> MVC triad.
  * This class tracks the <code>ImViewer</code>'s state and knows how to
  * initiate data retrievals. It also knows how to store and manipulate
  * the results. This class provides a suitable data loader.
  * The {@link ImViewerComponent} intercepts the results of data loadings, feeds
  * them back to this class and fires state transitions as appropriate.
  * 
  * @author Jean-Marie Burel &nbsp;&nbsp;&nbsp;&nbsp;
  *         <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
  * @author Andrea Falconi &nbsp;&nbsp;&nbsp;&nbsp;
  *         <a href="mailto:a.falconi@dundee.ac.uk">a.falconi@dundee.ac.uk</a>
  * @author Donald MacDonald &nbsp;&nbsp;&nbsp;&nbsp;
  *         <a href="mailto:donald@lifesci.dundee.ac.uk">
  *         donald@lifesci.dundee.ac.uk</a>
  * @version 3.0
  * @since OME2.2
  */
  class ImViewerModel
  {
  
  	
  	/** The maximum size for the bird eye view for standard screen size.*/
  	private static final int BIRD_EYE_SIZE_LOWER = 128;
  	
  	/** The maximum size for the bird eye view for a.*/
  	private static final int BIRD_EYE_SIZE_MEDIUM = 196;
  	
  	/** The maximum size for the bird eye view.*/
  	private static final int BIRD_EYE_SIZE_HEIGH = 256;
  	
  	/** The maximum number of items in the history. */
  	private static final int MAX_HISTORY = 10;
  	
  	/** The maximum width of the thumbnail. */
  	private static final int THUMB_MAX_WIDTH = 24; 
  
  	/** The maximum height of the thumbnail. */
  	private static final int THUMB_MAX_HEIGHT = 24;
  	
  	/** Index of the <code>RenderingSettings</code> loader. */
  	private static final int SETTINGS = 0;
  	
  	/** Index of the <code>ImageLoader</code> loader. */
  	private static final int IMAGE = 1;
  	
  	/** Index of the <code>ImageLoader</code> loader. */
  	private static final int BIRD_EYE_VIEW = 2;
  	
  	/** The image to view. */
  	private DataObject image; 
  
  	/** Holds one of the state flags defined by {@link ImViewer}. */
  	private int state;
  
  	/** Reference to the component that embeds this model. */
  	private ImViewer component;
  
  	/** Map hosting the various loaders. */
  	private Map<Integer, DataLoader> loaders;
  	
  	/** The sub-component that hosts the display. */
  	private Browser browser;
  
  	/** Reference to the current player. */
  	private ChannelPlayer player;
  
  	/** The width of the thumbnail if the window is iconified. */
  	private int sizeX;
  
  	/** The height of the thumbnail if the window is iconified. */
  	private int sizeY;
  
  	/** The magnification factor for the thumbnail. */
  	private double factor;
  
  	/** The image icon. */
  	private BufferedImage imageIcon;
  
  	/** The bounds of the component requesting the viewer. */
  	private Rectangle requesterBounds;
  
  	/** The index of the selected tab. */
  	private int tabbedIndex;
  
  	/** 
  	 * Flag indicating to paint or not some textual information on top
  	 * of the grid image.
  	 */
  	private boolean textVisible;
  
  	/** Flag indicating that a movie is played. */
  	private boolean playingMovie;
  	
  	/** Flag indicating that a movie is played. */
  	private boolean playingChannelMovie;
  
  	/** Collection of history item. */
  	private List<HistoryItem> historyItems;
  
  	/** 
  	 * The index of the movie, not that we set to <code>-1</code>
  	 * when the movie player is launched.
  	 */
  	private int movieIndex;
  	
  	/** The rendering setting related to a given set of pixels. */
  	private Map renderingSettings;
  	
  	/** The metadata viewer. */
  	private MetadataViewer metadataViewer;
  	
  	/** Flag indicating if the metadata are loaded. */
  	private boolean metadataLoaded;
  	
  	/** The ID of the last selected pixels set. */
  	private long currentPixelsID;
  
  	/** The rendering settings set by another user. */
  	private RndProxyDef alternativeSettings;
  	
  	/** The id of the selected user. */
  	private long selectedUserID;
  	
  	/** 
  	 * Flag to compute the magnification factor when the image
  	 * is set for the first time.
  	 */
  	private boolean initMagnificationFactor;
  	
      /** The parent of the image or <code>null</code> if no context specified. */
      private DataObject parent;
      
      /** 
       * The grandparent of the image or <code>null</code> if no 
       * context specified. 
       */
      private DataObject grandParent;
      
      /** The plane information. */
      private Map<Integer, PlaneInfo> planeInfos;
      
      /** The id of the image. */
      private long imageID;
      
      /** Copy of the original rendering settings.  */
      private RndProxyDef originalDef;
      
      /** Copy of the last rendering settings for the main image.  */
      private RndProxyDef lastMainDef;
      
      /** Copy of the last rendering settings of the projection preview.  */
      private RndProxyDef lastProjDef;
      
      /** The projection's preview parameters. */
      private ProjectionParam lastProjRef;
      
      /** The last projection timepoint. */
      private int lastProjTime;
      
      /** The collection of containers hosting the image. */
      private Collection containers;
      
      /** 
       * The collection of measurements linked to either the image or the plate.
       */
      private Collection measurements;
      
      /**  
       * Flag indicating if the viewer should be opened as a separate window
       * or not. The default value is <code>true</code>.
       */
      private boolean separateWindow;
      
      /** The id of the table containing the overlay. */
      private long overlayTableID;
  
      /** 
       * The value indicating the reduction factor used for big images. 
       * The default value is <code>1</code>.
       */
      private double originalRatio;
      
      /** The tiles to display. */
      private Map<Integer, Tile> tiles;
      
      /** The number of rows, default is <code>1</code>.*/
      private int numberOfRows;
      
      /** The number of columns, default is <code>1</code>.*/
      private int numberOfColumns;
  
  	/** The collection of resolutions levels.*/
  	private List<ResolutionLevel> resolutions;
  	
  	/** The size of the tiled image along the X-axis.*/
  	private int tiledImageSizeX;
  	
  	/** The size of the tiled image along the Y-axis.*/
  	private int tiledImageSizeY;
  	
  	/** Flag indicating that the image is loaded for the first time.*/
  	private boolean firstTime;
  	
  	/** The security context.*/
      private SecurityContext ctx;
      
      /** The channels.*/
      private List<ChannelData> channels;
      
      /** The display mode.*/
      private int displayMode;
      
      /** The number of tiles to load.*/
      private int tileTotalCount;
      
      /** The number of tiles already loaded.*/
      private int tileLoadedCount;
  
      /** The default plane size.*/
      private int planeSize;
  
      /** The units corresponding to the pixels size.*/
      private String refUnit;
      
      /**
       * Returns the default resolution level.
       * 
       * @return See above.
       */
      private int getDefaultResolutionLevel()
      {
          String zoomLevel = (String) ImViewerAgent.getRegistry().lookup(
                  LookupNames.BIGIMAGE_INITIAL_ZOOM);
          if (isBigImage() && CommonsLangUtils.isNotBlank(zoomLevel)) {
              //Use the default zoom level from the properties
              return Integer.parseInt(zoomLevel);
          }
          
          // Determine the level according to the window size.
          Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
          int w = 9 * (screenSize.width / 10);
          int h = 8 * (screenSize.height / 10);
          ResolutionLevel level;
          Dimension d;
          for (int i = resolutions.size() - 1; i >= 0; i--) {
              level = resolutions.get(i);
              d = level.getImageSize();
              if (d.width < w || d.height < h)
                  return level.getLevel();
          }
          return 0;
      }
      
  	/**
  	 * Creates the plane to retrieve.
  	 * 
  	 * @return See above.
  	 */
  	private PlaneDef createPlaneDef()
  	{
  		PlaneDef pDef = new PlaneDef();
  		pDef.t = getDefaultT();
  		pDef.z = getDefaultZ();
  		pDef.slice = omero.romio.XY.value;
  		return pDef;
  	}
  	
  	/** Initializes the tiles objects.*/
  	private void initializeTiles()
  	{
  		ResolutionLevel level = getResolutionDescription();
  		Dimension d = level.getTileSize();
  		int w = d.width;
  		int h = d.height;
  		int edgeWidth = w;
  		int edgeHeight = h;
  		int size = level.getImageSize().width;
  		edgeWidth = w;
  		int n = size/w;
  		tiledImageSizeX = n*w;
  		if (n*w < size) {
  