From c931a75bb23be77ee5e7084dff01613e654b21c7 Mon Sep 17 00:00:00 2001
From: tpylak <tpylak>
Date: Fri, 10 Dec 2010 12:58:48 +0000
Subject: [PATCH] LMS-1915 MIC(roscopy): extract image view

SVN: 19081
---
 .../client/web/client/ParameterNames.java     |   2 +
 .../ScreeningDisplaySettingsManager.java      |   3 +-
 .../application/ScreeningViewContext.java     |   2 +-
 .../detailviewers/ChannelChooser.java         |   6 +-
 .../detailviewers/ImageUrlUtils.java          |  54 ++--
 ...Images.java => LogicalImageReference.java} |  17 +-
 .../detailviewers/LogicalImageViewer.java     | 210 ++++++++++++++
 .../detailviewers/WellContentDialog.java      | 267 ++++--------------
 .../WellContentTimepointsViewer.java          |   8 +-
 .../detailviewers/WellSearchGrid.java         |   8 -
 .../web/server/ImageViewerLaunchServlet.java  |   6 +
 .../dataaccess/IImagingReadonlyQueryDAO.java  |   7 +-
 12 files changed, 328 insertions(+), 262 deletions(-)
 rename screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/{WellImages.java => LogicalImageReference.java} (82%)
 create mode 100644 screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LogicalImageViewer.java

diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/ParameterNames.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/ParameterNames.java
index 227b2fa41d2..ead8ea9af8f 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/ParameterNames.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/ParameterNames.java
@@ -27,5 +27,7 @@ public class ParameterNames
 
     public static final String DATA_SET_AND_WELLS = "data-set-and-wells";
 
+    public static final String DATA_SETS = "data-sets";
+
     public static final String SERVER_URL = "server-url";
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningDisplaySettingsManager.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningDisplaySettingsManager.java
index de9a1c2483d..004ec4b3269 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningDisplaySettingsManager.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningDisplaySettingsManager.java
@@ -18,7 +18,6 @@ package ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DisplaySettingsManager;
-import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.IScreeningClientServiceAsync;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningDisplaySettings;
 
 /**
@@ -29,7 +28,7 @@ public class ScreeningDisplaySettingsManager
     private final ScreeningDisplaySettings screeningSettings;
 
     @SuppressWarnings("deprecation")
-    public ScreeningDisplaySettingsManager(IViewContext<IScreeningClientServiceAsync> viewContext)
+    public ScreeningDisplaySettingsManager(IViewContext<?> viewContext)
     {
         DisplaySettingsManager displaySettingsManager = viewContext.getDisplaySettingsManager();
         ScreeningDisplaySettings settingsOrNull =
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningViewContext.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningViewContext.java
index 6ebd7669158..76e457d200c 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningViewContext.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningViewContext.java
@@ -49,7 +49,7 @@ public final class ScreeningViewContext extends
     }
 
     public static ScreeningDisplaySettingsManager getTechnologySpecificDisplaySettingsManager(
-            IViewContext<IScreeningClientServiceAsync> viewContext)
+            IViewContext<?> viewContext)
     {
         return new ScreeningDisplaySettingsManager(viewContext);
     }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ChannelChooser.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ChannelChooser.java
index 1d81c5b1c3b..464a67ebcb9 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ChannelChooser.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ChannelChooser.java
@@ -21,7 +21,6 @@ import java.util.List;
 import com.extjs.gxt.ui.client.Style.Scroll;
 import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
 import com.extjs.gxt.ui.client.event.SelectionChangedListener;
-import com.extjs.gxt.ui.client.event.SelectionProvider;
 import com.extjs.gxt.ui.client.util.Margins;
 import com.extjs.gxt.ui.client.widget.Label;
 import com.extjs.gxt.ui.client.widget.LayoutContainer;
@@ -43,9 +42,7 @@ class ChannelChooser
 {
     public static interface IChanneledViewerFactory
     {
-        Widget create(String value);
-
-        void setChannelChooser(SelectionProvider<SimpleComboValue<String>> selectionProvider);
+        Widget create(String channelCode);
     }
 
     public static LayoutContainer createViewerWithChannelChooser(
@@ -71,7 +68,6 @@ class ChannelChooser
         {
             ComboBox<SimpleComboValue<String>> channelChooser =
                     new ChannelComboBox(channelCodes, defaultChannelState);
-            viewerFactory.setChannelChooser(channelChooser);
             channelChooser
                     .addSelectionChangedListener(new SelectionChangedListener<SimpleComboValue<String>>()
                         {
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ImageUrlUtils.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ImageUrlUtils.java
index 7278645879b..d2751d8b330 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ImageUrlUtils.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ImageUrlUtils.java
@@ -23,6 +23,7 @@ import com.extjs.gxt.ui.client.widget.LayoutContainer;
 import ch.systemsx.cisd.openbis.generic.shared.basic.URLMethodWithParameters;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConstants;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelStack;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
 
 /**
  * Generates URLs pointing to the images on Data Store server.
@@ -38,8 +39,8 @@ public class ImageUrlUtils
      * @param createImageLinks if true, each thumbnail will link to the original image
      */
     public static void addImageUrlWidget(LayoutContainer container, String sessionId,
-            WellImages images, String channel, int row, int col, int imageWidth, int imageHeight,
-            boolean createImageLinks)
+            LogicalImageReference images, String channel, int row, int col, int imageWidth,
+            int imageHeight, boolean createImageLinks)
     {
         String imageURL =
                 createDatastoreImageUrl(sessionId, images, channel, row, col, imageWidth,
@@ -52,7 +53,7 @@ public class ImageUrlUtils
      * container.
      */
     public static void addImageUrlWidget(LayoutContainer container, String sessionId,
-            WellImages images, String channel, ImageChannelStack channelStackRef,
+            LogicalImageReference images, String channel, ImageChannelStack channelStackRef,
             int imageWidth, int imageHeight)
     {
         String imageURL =
@@ -62,7 +63,7 @@ public class ImageUrlUtils
     }
 
     /** generates URL of an image on Data Store server */
-    private static String createDatastoreImageUrl(String sessionID, WellImages images,
+    private static String createDatastoreImageUrl(String sessionID, LogicalImageReference images,
             String channel, ImageChannelStack channelStackRef, int width, int height)
     {
         URLMethodWithParameters methodWithParameters =
@@ -70,8 +71,9 @@ public class ImageUrlUtils
 
         methodWithParameters
                 .addParameter("channelStackId", channelStackRef.getChannelStackTechId());
+        addImageTransformerSignature(methodWithParameters, images, channel);
         String linkURL = methodWithParameters.toString();
-        methodWithParameters.addParameter("mode", "thumbnail" + width + "x" + height);
+        addThumbnailSize(methodWithParameters, width, height);
 
         String imageURL = methodWithParameters.toString();
         // do not specify width to get correct aspect ratio of the original image
@@ -89,36 +91,52 @@ public class ImageUrlUtils
     }
 
     /**
-     * generates URL of an image on Data Store server
+     * Generates an HTML image tag with a thumbnail which links to the big image on Data Store
+     * server.
      * 
      * @param createImageLinks
      */
-    private static String createDatastoreImageUrl(String sessionID, WellImages images,
+    private static String createDatastoreImageUrl(String sessionID, LogicalImageReference images,
             String channel, int tileRow, int tileCol, int width, int height,
             boolean createImageLinks)
     {
         URLMethodWithParameters methodWithParameters =
                 createBasicImageURL(sessionID, images, channel);
 
-        methodWithParameters.addParameter("wellRow", images.getWellLocation().getRow());
-        methodWithParameters.addParameter("wellCol", images.getWellLocation().getColumn());
+        WellLocation wellLocation = images.tryGetWellLocation();
+        if (wellLocation != null)
+        {
+            methodWithParameters.addParameter("wellRow", wellLocation.getRow());
+            methodWithParameters.addParameter("wellCol", wellLocation.getColumn());
+        }
         methodWithParameters.addParameter("tileRow", tileRow);
         methodWithParameters.addParameter("tileCol", tileCol);
+        addImageTransformerSignature(methodWithParameters, images, channel);
+        String linkURLOrNull = createImageLinks ? methodWithParameters.toString() : null;
+        addThumbnailSize(methodWithParameters, width, height);
+
+        String imageURL = methodWithParameters.toString();
+        // do not specify width to get correct aspect ratio of the original image
+        return URLMethodWithParameters.createEmbededImageHtml(imageURL, linkURLOrNull, -1, height);
+    }
+
+    private static void addThumbnailSize(URLMethodWithParameters url, int width, int height)
+    {
+        url.addParameter("mode", "thumbnail" + width + "x" + height);
+    }
+
+    private static void addImageTransformerSignature(URLMethodWithParameters url,
+            LogicalImageReference images, String channel)
+    {
         String signature = images.getTransformerFactorySignatureOrNull(channel);
         if (signature != null)
         {
-            methodWithParameters.addParameter("transformerFactorySignature", signature);
+            url.addParameter("transformerFactorySignature", signature);
         }
-        String linkURL = createImageLinks ? methodWithParameters.toString() : null;
-        methodWithParameters.addParameter("mode", "thumbnail" + width + "x" + height);
-
-        String imageURL = methodWithParameters.toString();
-        // do not specify width to get correct aspect ratio of the original image
-        return URLMethodWithParameters.createEmbededImageHtml(imageURL, linkURL, -1, height);
     }
 
-    private static URLMethodWithParameters createBasicImageURL(String sessionID, WellImages images,
-            String channel)
+    private static URLMethodWithParameters createBasicImageURL(String sessionID,
+            LogicalImageReference images, String channel)
     {
         URLMethodWithParameters methodWithParameters =
                 new URLMethodWithParameters(images.getDatastoreHostUrl() + "/"
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellImages.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LogicalImageReference.java
similarity index 82%
rename from screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellImages.java
rename to screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LogicalImageReference.java
index b5c9042840e..365ab10a891 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellImages.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LogicalImageReference.java
@@ -24,27 +24,28 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageDatasetPa
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
 
 /**
- * Stores image dataset reference and well location.
+ * Points to one logical image in the image dataset. For HCS it will be all images of the well. For
+ * microscopy the whole dataset contains one logical image.
  * 
  * @author Tomasz Pylak
  */
-public class WellImages
+public class LogicalImageReference
 {
     private final DatasetImagesReference imageDataset;
 
-    private final WellLocation wellLocation;
+    private final WellLocation wellLocationOrNull;
 
-    public WellImages(DatasetImagesReference imageDataset, WellLocation location)
+    public LogicalImageReference(DatasetImagesReference imageDataset,
+            WellLocation wellLocationOrNull)
     {
         assert imageDataset != null : "image dataset is null";
-        assert location != null : "location is null";
         this.imageDataset = imageDataset;
-        this.wellLocation = location;
+        this.wellLocationOrNull = wellLocationOrNull;
     }
 
-    public WellLocation getWellLocation()
+    public WellLocation tryGetWellLocation()
     {
-        return wellLocation;
+        return wellLocationOrNull;
     }
 
     private ImageDatasetParameters getImageParams()
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LogicalImageViewer.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LogicalImageViewer.java
new file mode 100644
index 00000000000..93dd1dee0b5
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LogicalImageViewer.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers;
+
+import java.util.List;
+
+import com.extjs.gxt.ui.client.widget.LayoutContainer;
+import com.extjs.gxt.ui.client.widget.layout.TableLayout;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Widget;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.shared.basic.URLMethodWithParameters;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.ParameterNames;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.Constants;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ScreeningDisplaySettingsManager;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ScreeningDisplayTypeIDGenerator;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ScreeningViewContext;
+import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers.ChannelChooser.IChanneledViewerFactory;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelStack;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
+
+/**
+ * A widget which displays one logical image pointed by {@link LogicalImageReference}.
+ * 
+ * @author Tomasz Pylak
+ */
+public class LogicalImageViewer
+{
+
+    private static final int ONE_IMAGE_WIDTH_PX = 200;
+
+    private static final int ONE_IMAGE_HEIGHT_PX = 120;
+
+    // ----------------
+
+    private final LogicalImageReference logicalImageReference;
+
+    private final IViewContext<?> viewContext;
+
+    private final IDefaultChannelState channelState;
+
+    private String currentlySelectedChannelCode;
+
+    public LogicalImageViewer(LogicalImageReference logicalImageReference,
+            IViewContext<?> viewContext, String experimentPermId)
+    {
+        this.logicalImageReference = logicalImageReference;
+        this.viewContext = viewContext;
+        this.channelState = createDefaultChannelState(viewContext, experimentPermId);
+    }
+
+    /** Creates a widget which displays a series of images. */
+    public Widget getSeriesImageWidget(final List<ImageChannelStack> channelStackImages)
+    {
+        final IChanneledViewerFactory viewerFactory = new IChanneledViewerFactory()
+            {
+                public LayoutContainer create(String channel)
+                {
+                    currentlySelectedChannelCode = channel;
+                    String sessionId = getSessionId(viewContext);
+                    int imageWidth = getImageWidth(logicalImageReference);
+                    int imageHeight = getImageHeight(logicalImageReference);
+                    return WellContentTimepointsViewer.createTilesGrid(sessionId,
+                            channelStackImages, logicalImageReference, channel, imageWidth,
+                            imageHeight);
+                }
+            };
+        return ChannelChooser.createViewerWithChannelChooser(viewerFactory, channelState,
+                logicalImageReference.getChannelsCodes());
+    }
+
+    /** Creates a widget which displays images which has no series. */
+    public Widget getStaticImageWidget()
+    {
+
+        final IChanneledViewerFactory viewerFactory = new IChanneledViewerFactory()
+            {
+                public LayoutContainer create(String channel)
+                {
+                    currentlySelectedChannelCode = channel;
+                    String sessionId = getSessionId(viewContext);
+                    return createTilesGrid(logicalImageReference, channel, sessionId);
+                }
+            };
+        return ChannelChooser.createViewerWithChannelChooser(viewerFactory, channelState,
+                logicalImageReference.getChannelsCodes());
+    }
+
+    protected void setCurrentChannel(String channel)
+    {
+        this.currentlySelectedChannelCode = channel;
+    }
+
+    private static IDefaultChannelState createDefaultChannelState(
+            final IViewContext<?> viewContext, final String experimentPermId)
+    {
+        final ScreeningDisplaySettingsManager screeningDisplaySettingManager =
+                ScreeningViewContext.getTechnologySpecificDisplaySettingsManager(viewContext);
+        final ScreeningDisplayTypeIDGenerator wellSearchChannelIdGenerator =
+                ScreeningDisplayTypeIDGenerator.EXPERIMENT_CHANNEL;
+        final String displayTypeID = wellSearchChannelIdGenerator.createID(experimentPermId);
+
+        return new IDefaultChannelState()
+            {
+                public void setDefaultChannel(String channel)
+                {
+                    screeningDisplaySettingManager.setDefaultChannel(displayTypeID, channel);
+                }
+
+                public String tryGetDefaultChannel()
+                {
+                    return screeningDisplaySettingManager.tryGetDefaultChannel(displayTypeID);
+                }
+            };
+    }
+
+    /** Launches external image editor for the displayed image in the chosen channel. */
+    public void launchImageEditor()
+    {
+        final URLMethodWithParameters urlParams =
+                new URLMethodWithParameters(Constants.IMAGE_VIEWER_LAUNCH_SERVLET_NAME);
+        String sessionToken = viewContext.getModel().getSessionContext().getSessionID();
+        urlParams.addParameter("session", sessionToken);
+        urlParams.addParameter(ParameterNames.SERVER_URL, GWT.getHostPageBaseURL());
+
+        if (currentlySelectedChannelCode != null)
+        {
+            urlParams.addParameter(ParameterNames.CHANNEL, currentlySelectedChannelCode);
+        }
+        WellLocation wellLocation = logicalImageReference.tryGetWellLocation();
+        if (wellLocation != null)
+        {
+            String imagePointer =
+                    logicalImageReference.getDatasetCode() + ":" + wellLocation.getRow() + "."
+                            + wellLocation.getColumn();
+            urlParams.addParameter(ParameterNames.DATA_SET_AND_WELLS, imagePointer);
+        } else
+        {
+            urlParams
+                    .addParameter(ParameterNames.DATA_SETS, logicalImageReference.getDatasetCode());
+        }
+
+        Window.open(urlParams.toString(), "_blank", "resizable=yes,scrollbars=yes,dependent=yes");
+    }
+
+    private static LayoutContainer createTilesGrid(final LogicalImageReference images,
+            String channel, String sessionId)
+    {
+        return createRepresentativeImage(images, channel, sessionId, getImageWidth(images),
+                getImageHeight(images), true);
+    }
+
+    /** Creates a widget with a representative image of the specified logical image. */
+    // TODO 2010-12-10, Tomasz Pylak: implement me!
+    public static LayoutContainer createRepresentativeImage(LogicalImageReference images,
+            String channel, String sessionId, int imageWidth, int imageHeight,
+            boolean createImageLinks)
+    {
+        LayoutContainer container = new LayoutContainer(new TableLayout(images.getTileColsNum()));
+        for (int row = 1; row <= images.getTileRowsNum(); row++)
+        {
+            for (int col = 1; col <= images.getTileColsNum(); col++)
+            {
+                ImageUrlUtils.addImageUrlWidget(container, sessionId, images, channel, row, col,
+                        imageWidth, imageHeight, createImageLinks);
+            }
+        }
+        return container;
+    }
+
+    private static String getSessionId(IViewContext<?> viewContext)
+    {
+        return viewContext.getModel().getSessionContext().getSessionID();
+    }
+
+    private static int getImageHeight(LogicalImageReference images)
+    {
+        float imageSizeMultiplyFactor = getImageSizeMultiplyFactor(images);
+        return (int) (ONE_IMAGE_HEIGHT_PX * imageSizeMultiplyFactor);
+    }
+
+    private static int getImageWidth(LogicalImageReference images)
+    {
+        float imageSizeMultiplyFactor = getImageSizeMultiplyFactor(images);
+        return (int) (ONE_IMAGE_WIDTH_PX * imageSizeMultiplyFactor);
+    }
+
+    private static float getImageSizeMultiplyFactor(LogicalImageReference images)
+    {
+        float dim = Math.max(images.getTileRowsNum(), images.getTileColsNum());
+        // if there are more than 3 tiles, make them smaller, if there are less, make them bigger
+        return 4.0F / dim;
+    }
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellContentDialog.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellContentDialog.java
index 43008716e7f..40ebde2ac15 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellContentDialog.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellContentDialog.java
@@ -27,7 +27,6 @@ import com.extjs.gxt.ui.client.event.ButtonEvent;
 import com.extjs.gxt.ui.client.event.Events;
 import com.extjs.gxt.ui.client.event.Listener;
 import com.extjs.gxt.ui.client.event.SelectionListener;
-import com.extjs.gxt.ui.client.event.SelectionProvider;
 import com.extjs.gxt.ui.client.util.Rectangle;
 import com.extjs.gxt.ui.client.widget.Dialog;
 import com.extjs.gxt.ui.client.widget.Html;
@@ -35,15 +34,12 @@ import com.extjs.gxt.ui.client.widget.LayoutContainer;
 import com.extjs.gxt.ui.client.widget.Text;
 import com.extjs.gxt.ui.client.widget.button.Button;
 import com.extjs.gxt.ui.client.widget.button.ButtonBar;
-import com.extjs.gxt.ui.client.widget.form.SimpleComboValue;
 import com.extjs.gxt.ui.client.widget.layout.HBoxLayout;
 import com.extjs.gxt.ui.client.widget.layout.TableData;
 import com.extjs.gxt.ui.client.widget.layout.TableLayout;
 import com.extjs.gxt.ui.client.widget.toolbar.FillToolItem;
-import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Anchor;
 import com.google.gwt.user.client.ui.Widget;
 
@@ -53,26 +49,19 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewConte
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.LinkRenderer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.listener.OpenEntityDetailsTabClickListener;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWithPermId;
-import ch.systemsx.cisd.openbis.generic.shared.basic.URLMethodWithParameters;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.IScreeningClientServiceAsync;
-import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.ParameterNames;
-import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.Constants;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.Dict;
-import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ScreeningDisplaySettingsManager;
-import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ScreeningDisplayTypeIDGenerator;
-import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ScreeningViewContext;
-import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers.ChannelChooser.IChanneledViewerFactory;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ui.columns.specific.ScreeningLinkExtractor;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.utils.GuiUtils;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.DatasetImagesReference;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ExperimentReference;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelStack;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageDatasetParameters;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConstants;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellContent;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelStack;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellLocation;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellMetadata;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria.ExperimentSearchCriteria;
@@ -97,10 +86,6 @@ public class WellContentDialog extends Dialog
 
     // ---
 
-    private static final int ONE_IMAGE_WIDTH_PX = 200;
-
-    private static final int ONE_IMAGE_HEIGHT_PX = 120;
-
     /**
      * A dialog which shows the content of the well (static or a timepoints movie).
      */
@@ -109,53 +94,25 @@ public class WellContentDialog extends Dialog
             final IViewContext<IScreeningClientServiceAsync> viewContext)
     {
         final WellContentDialog contentDialog =
-                createContentDialog(wellData, viewContext, imageDatasetOrNull != null);
-
-        final IDefaultChannelState defaultChannelState =
-                createDefaultChannelState(viewContext, wellData.getExperiment().getPermId());
-
-        showContentDialog(contentDialog, imageDatasetOrNull, defaultChannelState, viewContext);
-    }
-
-    private static IDefaultChannelState createDefaultChannelState(
-            final IViewContext<IScreeningClientServiceAsync> viewContext,
-            final String experimentPermId)
-    {
-        final ScreeningDisplaySettingsManager screeningDisplaySettingManager =
-                ScreeningViewContext.getTechnologySpecificDisplaySettingsManager(viewContext);
-        final ScreeningDisplayTypeIDGenerator wellSearchChannelIdGenerator =
-                ScreeningDisplayTypeIDGenerator.EXPERIMENT_CHANNEL;
-        final String displayTypeID = wellSearchChannelIdGenerator.createID(experimentPermId);
-
-        return new IDefaultChannelState()
-            {
-                public void setDefaultChannel(String channel)
-                {
-                    screeningDisplaySettingManager.setDefaultChannel(displayTypeID, channel);
-                }
-
-                public String tryGetDefaultChannel()
-                {
-                    return screeningDisplaySettingManager.tryGetDefaultChannel(displayTypeID);
-                }
-            };
+                createContentDialog(wellData, viewContext);
+        showContentDialog(contentDialog, imageDatasetOrNull, viewContext);
     }
 
     private static void showContentDialog(final WellContentDialog contentDialog,
-            final DatasetImagesReference imagesOrNull, IDefaultChannelState channelState,
+            final DatasetImagesReference imagesOrNull,
             final IViewContext<IScreeningClientServiceAsync> viewContext)
     {
         if (imagesOrNull != null && imagesOrNull.getImageParameters().isMultidimensional())
         {
-            showTimepointImageDialog(contentDialog, imagesOrNull, channelState, viewContext);
+            showTimepointImageDialog(contentDialog, imagesOrNull, viewContext);
         } else
         {
-            showStaticImageDialog(contentDialog, imagesOrNull, channelState, viewContext);
+            showStaticImageDialog(contentDialog, imagesOrNull, viewContext);
         }
     }
 
     private static WellContentDialog createContentDialog(final WellData wellData,
-            final IViewContext<IScreeningClientServiceAsync> viewContext, boolean hasDataSet)
+            final IViewContext<IScreeningClientServiceAsync> viewContext)
     {
         WellLocation wellLocation = wellData.getWellLocation();
         WellMetadata wellMetadata = wellData.tryGetMetadata();
@@ -166,8 +123,8 @@ public class WellContentDialog extends Dialog
             wellOrNull = wellMetadata.getWellSample();
             wellPropertiesOrNull = wellMetadata.getWellSample().getProperties();
         }
-        return new WellContentDialog(wellOrNull, wellPropertiesOrNull, wellLocation, hasDataSet,
-                getExperiment(wellData), viewContext);
+        return new WellContentDialog(wellOrNull, wellPropertiesOrNull, wellLocation, getExperiment(wellData),
+                viewContext);
     }
 
     /**
@@ -198,10 +155,11 @@ public class WellContentDialog extends Dialog
 
         boolean createImageLinks = (imageParameters.isMultidimensional() == false);
         String sessionId = getSessionId(viewContext);
-        final WellImages wellImages = new WellImages(imageDataset, locationOrNull);
+        final LogicalImageReference wellImages =
+                new LogicalImageReference(imageDataset, locationOrNull);
         LayoutContainer staticTilesGrid =
-                createTilesGrid(wellImages, channel, sessionId, imageWidthPx, imageHeightPx,
-                        createImageLinks);
+                LogicalImageViewer.createRepresentativeImage(wellImages, channel, sessionId, imageWidthPx,
+                        imageHeightPx, createImageLinks);
 
         if (imageParameters.isMultidimensional())
         {
@@ -211,7 +169,7 @@ public class WellContentDialog extends Dialog
                 {
                     public void handleEvent(BaseEvent be)
                     {
-                        showContentDialog(viewContext, wellContent, imageDataset, false);
+                        showContentDialog(viewContext, wellContent, imageDataset);
                     }
                 });
         }
@@ -220,143 +178,76 @@ public class WellContentDialog extends Dialog
     }
 
     private static void showContentDialog(IViewContext<IScreeningClientServiceAsync> viewContext,
-            WellContent wellContent, DatasetImagesReference imageDatasetOrNull, boolean hasDataSet)
+            WellContent wellContent, DatasetImagesReference imageDatasetOrNull)
     {
         WellContentDialog contentDialog =
                 new WellContentDialog(wellContent.getWell(), null, wellContent.tryGetLocation(),
-                        hasDataSet, getExperiment(wellContent.getExperiment()), viewContext);
+                        getExperiment(wellContent.getExperiment()), viewContext);
 
-        final IDefaultChannelState defaultChannelState =
-                createDefaultChannelState(viewContext, wellContent.getExperiment().getPermId());
-        showContentDialog(contentDialog, imageDatasetOrNull, defaultChannelState, viewContext);
+        showContentDialog(contentDialog, imageDatasetOrNull, viewContext);
     }
 
     // --------------- STATIC IMAGES VIEWER
 
     private static void showStaticImageDialog(final WellContentDialog contentDialog,
-            final DatasetImagesReference imageDatasetOrNull, IDefaultChannelState channelState,
-            final IViewContext<?> viewContext)
+            final DatasetImagesReference imageDatasetOrNull, final IViewContext<?> viewContext)
     {
-        WellLocation wellLocation = contentDialog.wellLocationOrNull;
-        if (imageDatasetOrNull != null && wellLocation != null)
+        if (imageDatasetOrNull != null)
         {
-            contentDialog.setDataSetCode(imageDatasetOrNull.getDatasetCode());
-            final WellImages imagesOrNull = new WellImages(imageDatasetOrNull, wellLocation);
-            final IChanneledViewerFactory viewerFactory = new IChanneledViewerFactory()
-                {
-                    public LayoutContainer create(String channel)
-                    {
-                        String sessionId = getSessionId(viewContext);
-                        return createTilesGrid(imagesOrNull, channel, sessionId);
-                    }
-
-                    public void setChannelChooser(
-                            SelectionProvider<SimpleComboValue<String>> selectionProvider)
-                    {
-                        contentDialog.setChannelChooser(selectionProvider);
-                    }
-                };
-            LayoutContainer imageViewer =
-                    ChannelChooser.createViewerWithChannelChooser(viewerFactory, channelState,
-                            imagesOrNull.getChannelsCodes());
-            contentDialog.addImageView(imageViewer);
+            contentDialog.addImageStaticViewer(imageDatasetOrNull);
         }
         contentDialog.show();
     }
 
-    private static LayoutContainer createTilesGrid(final WellImages images, String channel,
-            String sessionId)
-    {
-        return createTilesGrid(images, channel, sessionId, getImageWidth(images),
-                getImageHeight(images), true);
-    }
-
-    private static LayoutContainer createTilesGrid(WellImages images, String channel,
-            String sessionId, int imageWidth, int imageHeight, boolean createImageLinks)
-    {
-        LayoutContainer container = new LayoutContainer(new TableLayout(images.getTileColsNum()));
-        for (int row = 1; row <= images.getTileRowsNum(); row++)
-        {
-            for (int col = 1; col <= images.getTileColsNum(); col++)
-            {
-                ImageUrlUtils.addImageUrlWidget(container, sessionId, images, channel, row, col,
-                        imageWidth, imageHeight, createImageLinks);
-            }
-        }
-        return container;
-    }
-
     // --------------- TIMEPOINT IMAGES PLAYER
 
     private static void showTimepointImageDialog(final WellContentDialog contentDialog,
-            final DatasetImagesReference imageDataset, final IDefaultChannelState channelState,
+            final DatasetImagesReference imageDataset,
             final IViewContext<IScreeningClientServiceAsync> viewContext)
     {
         assert imageDataset != null;
 
-        final WellLocation wellLocation = contentDialog.wellLocationOrNull;
-        if (wellLocation == null)
-        {
-            // images stacks cannot be obtained
-            contentDialog.show();
-        }
-        contentDialog.setDataSetCode(imageDataset.getDatasetCode());
         viewContext.getService().listImageChannelStacks(imageDataset.getDatasetCode(),
-                imageDataset.getDatastoreCode(), wellLocation,
+                imageDataset.getDatastoreCode(), contentDialog.wellLocationOrNull,
                 new AbstractAsyncCallback<List<ImageChannelStack>>(viewContext)
                     {
                         @Override
                         protected void process(final List<ImageChannelStack> channelStackImages)
                         {
-                            if (channelStackImages.size() == 0)
+                            if (channelStackImages.size() > 0)
                             {
-                                contentDialog.show();
-                            } else
-                            {
-                                final WellImages wellImages =
-                                        new WellImages(imageDataset, wellLocation);
-                                final String sessionId = getSessionId(viewContext);
-                                final IChanneledViewerFactory viewerFactory =
-                                        new IChanneledViewerFactory()
-                                            {
-                                                public LayoutContainer create(String channel)
-                                                {
-                                                    return WellContentTimepointsViewer
-                                                            .createTilesGrid(sessionId,
-                                                                    channelStackImages, wellImages,
-                                                                    channel,
-                                                                    getImageWidth(wellImages),
-                                                                    getImageHeight(wellImages));
-                                                }
-
-                                                public void setChannelChooser(
-                                                        SelectionProvider<SimpleComboValue<String>> selectionProvider)
-                                                {
-                                                    contentDialog
-                                                            .setChannelChooser(selectionProvider);
-                                                }
-                                            };
-                                LayoutContainer imageViewer =
-                                        ChannelChooser.createViewerWithChannelChooser(
-                                                viewerFactory, channelState,
-                                                wellImages.getChannelsCodes());
-                                contentDialog.addImageView(imageViewer);
-                                contentDialog.show();
+                                contentDialog
+                                        .addImageSeriesViewer(imageDataset, channelStackImages);
                             }
+                            contentDialog.show();
                         }
+
                     });
     }
 
-    private static int getImageHeight(WellImages images)
+    protected void addImageSeriesViewer(DatasetImagesReference imageDataset,
+            List<ImageChannelStack> channelStackImages)
     {
-        float imageSizeMultiplyFactor = getImageSizeMultiplyFactor(images);
-        return (int) (ONE_IMAGE_HEIGHT_PX * imageSizeMultiplyFactor);
+        LogicalImageViewer viewer = createImageViewer(imageDataset);
+        Widget viewerWidget = viewer.getSeriesImageWidget(channelStackImages);
+        add(viewerWidget);
+        addImageEditorLaunchButton(viewer);
     }
 
-    private static int getImageWidth(WellImages images)
+    protected void addImageStaticViewer(DatasetImagesReference imageDataset)
     {
-        float imageSizeMultiplyFactor = getImageSizeMultiplyFactor(images);
-        return (int) (ONE_IMAGE_WIDTH_PX * imageSizeMultiplyFactor);
+        LogicalImageViewer viewer = createImageViewer(imageDataset);
+        Widget viewerWidget = viewer.getStaticImageWidget();
+        add(viewerWidget);
+        addImageEditorLaunchButton(viewer);
+    }
+
+    private LogicalImageViewer createImageViewer(DatasetImagesReference imageDatasetOrNull)
+    {
+        final LogicalImageReference imagesOrNull =
+                new LogicalImageReference(imageDatasetOrNull, wellLocationOrNull);
+        return new LogicalImageViewer(imagesOrNull, viewContext,
+                experimentCriteria.getExperimentPermId());
     }
 
     private static SingleExperimentSearchCriteria getExperiment(WellData wellData)
@@ -373,13 +264,6 @@ public class WellContentDialog extends Dialog
                 experimentReference.getPermId(), experimentReference.getExperimentIdentifier());
     }
 
-    private static float getImageSizeMultiplyFactor(WellImages images)
-    {
-        float dim = Math.max(images.getTileRowsNum(), images.getTileColsNum());
-        // if there are more than 3 tiles, make them smaller, if there are less, make them bigger
-        return 4.0F / dim;
-    }
-
     private static String getSessionId(IViewContext<?> viewContext)
     {
         return viewContext.getModel().getSessionContext().getSessionID();
@@ -397,14 +281,9 @@ public class WellContentDialog extends Dialog
 
     private final IViewContext<IScreeningClientServiceAsync> viewContext;
 
-    private SelectionProvider<SimpleComboValue<String>> channelSelectionProvider;
-
-    private String datasetCode;
-
     private WellContentDialog(IEntityInformationHolderWithPermId wellOrNull,
             List<IEntityProperty> wellPropertiesOrNull, final WellLocation wellLocationOrNull,
-            boolean hasDataSet, final SingleExperimentSearchCriteria experimentCriteria,
-            final IViewContext<IScreeningClientServiceAsync> viewContext)
+            final SingleExperimentSearchCriteria experimentCriteria, final IViewContext<IScreeningClientServiceAsync> viewContext)
     {
         this.wellOrNull = wellOrNull;
         this.wellLocationOrNull = wellLocationOrNull;
@@ -440,71 +319,31 @@ public class WellContentDialog extends Dialog
                     center();
                 }
             });
-        if (wellLocationOrNull != null && hasDataSet
-                && "true".equals(viewContext.getPropertyOrNull("image-viewer-enabled")))
-        {
-            addImageViewerLaunchButton();
-        }
     }
 
-    private void addImageViewerLaunchButton()
+    private void addImageEditorLaunchButton(final LogicalImageViewer viewer)
     {
+        if ("true".equals(viewContext.getPropertyOrNull("image-viewer-enabled")) == false)
+        {
+            return;
+        }
         ButtonBar buttonBar = getButtonBar();
         buttonBar.setAlignment(HorizontalAlignment.LEFT);
         Button launchButton =
                 new Button(viewContext.getMessage(Dict.IMAGE_VIEWER_BUTTON),
                         new SelectionListener<ButtonEvent>()
                             {
-
                                 @Override
                                 public void componentSelected(ButtonEvent ce)
                                 {
-                                    final URLMethodWithParameters urlParams =
-                                            new URLMethodWithParameters(
-                                                    Constants.IMAGE_VIEWER_LAUNCH_SERVLET_NAME);
-                                    String sessionToken =
-                                            viewContext.getModel().getSessionContext()
-                                                    .getSessionID();
-                                    urlParams.addParameter("session", sessionToken);
-                                    urlParams.addParameter(ParameterNames.SERVER_URL,
-                                            GWT.getHostPageBaseURL());
-
-                                    if (channelSelectionProvider != null)
-                                    {
-                                        urlParams.addParameter(ParameterNames.CHANNEL,
-                                                channelSelectionProvider.getSelection().get(0)
-                                                        .getValue());
-                                    }
-                                    urlParams.addParameter(ParameterNames.DATA_SET_AND_WELLS,
-                                            datasetCode + ":" + wellLocationOrNull.getRow() + "."
-                                                    + wellLocationOrNull.getColumn());
-
-                                    Window.open(urlParams.toString(), "_blank",
-                                            "resizable=yes,scrollbars=yes,dependent=yes");
+                                    viewer.launchImageEditor();
                                     hide();
-
                                 }
                             });
         buttonBar.insert(new FillToolItem(), 0);
         buttonBar.insert(launchButton, 0);
     }
 
-    private void setChannelChooser(
-            final SelectionProvider<SimpleComboValue<String>> selectionProvider)
-    {
-        this.channelSelectionProvider = selectionProvider;
-    }
-
-    private void setDataSetCode(String datasetCode)
-    {
-        this.datasetCode = datasetCode;
-    }
-
-    private void addImageView(LayoutContainer component)
-    {
-        add(component);
-    }
-
     private String getWellDescription()
     {
         if (wellOrNull != null)
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellContentTimepointsViewer.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellContentTimepointsViewer.java
index 98e8790c370..f419563d4a0 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellContentTimepointsViewer.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellContentTimepointsViewer.java
@@ -41,7 +41,7 @@ class WellContentTimepointsViewer
 {
 
     public static LayoutContainer createTilesGrid(String sessionId,
-            List<ImageChannelStack> channelStackImages, WellImages images, String channel,
+            List<ImageChannelStack> channelStackImages, LogicalImageReference images, String channel,
             int imageWidth, int imageHeight)
     {
         Map<Float, List<ImageChannelStack>> channelStackImagesByTimepoint =
@@ -86,7 +86,7 @@ class WellContentTimepointsViewer
 
     private static List<LayoutContainer> createTimepointFrames(
             Map<Float, List<ImageChannelStack>> channelStackImagesByTimepoint,
-            WellImages images, String channel, String sessionId, int imageWidth, int imageHeight)
+            LogicalImageReference images, String channel, String sessionId, int imageWidth, int imageHeight)
     {
         final List<LayoutContainer> frames = new ArrayList<LayoutContainer>();
         int counter = 0;
@@ -116,7 +116,7 @@ class WellContentTimepointsViewer
     }
 
     private static LayoutContainer createTilesGridForTimepoint(
-            List<ImageChannelStack> channelStackReferences, WellImages images, String channel,
+            List<ImageChannelStack> channelStackReferences, LogicalImageReference images, String channel,
             String sessionId, int imageWidth, int imageHeight)
     {
         final LayoutContainer container =
@@ -143,7 +143,7 @@ class WellContentTimepointsViewer
     }
 
     private static ImageChannelStack[][] createTilesMap(
-            List<ImageChannelStack> stackReferences, WellImages images)
+            List<ImageChannelStack> stackReferences, LogicalImageReference images)
     {
         int rows = images.getTileRowsNum();
         int cols = images.getTileColsNum();
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellSearchGrid.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellSearchGrid.java
index 32e2499a1ce..84653d8a3c9 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellSearchGrid.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/WellSearchGrid.java
@@ -27,14 +27,12 @@ import com.extjs.gxt.ui.client.Style.Orientation;
 import com.extjs.gxt.ui.client.event.BaseEvent;
 import com.extjs.gxt.ui.client.event.Events;
 import com.extjs.gxt.ui.client.event.Listener;
-import com.extjs.gxt.ui.client.event.SelectionProvider;
 import com.extjs.gxt.ui.client.store.ListStore;
 import com.extjs.gxt.ui.client.widget.Component;
 import com.extjs.gxt.ui.client.widget.Label;
 import com.extjs.gxt.ui.client.widget.LayoutContainer;
 import com.extjs.gxt.ui.client.widget.form.Radio;
 import com.extjs.gxt.ui.client.widget.form.RadioGroup;
-import com.extjs.gxt.ui.client.widget.form.SimpleComboValue;
 import com.extjs.gxt.ui.client.widget.grid.ColumnData;
 import com.extjs.gxt.ui.client.widget.grid.Grid;
 import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
@@ -619,12 +617,6 @@ public class WellSearchGrid extends TypedTableGrid<WellContent>
                                 return WellContentDialog.createImageViewerForChannel(viewContext,
                                         entity, IMAGE_WIDTH_PX, IMAGE_HEIGHT_PX, channel);
                             }
-
-                            public void setChannelChooser(
-                                    SelectionProvider<SimpleComboValue<String>> selectionProvider)
-                            {
-                                // TODO 2010-11-09, felmer: Auto-generated method stub
-                            }
                         };
                     ChannelWidgetWithListener widgetWithListener =
                             new ChannelWidgetWithListener(viewerFactory);
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/ImageViewerLaunchServlet.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/ImageViewerLaunchServlet.java
index b8e7abb0a7c..c02d8ab3bb4 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/ImageViewerLaunchServlet.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/ImageViewerLaunchServlet.java
@@ -147,6 +147,12 @@ public class ImageViewerLaunchServlet extends AbstractServlet
             String channel = getParam(request, ParameterNames.CHANNEL);
             template.bind("channel", channel);
             StringBuilder builder = new StringBuilder();
+            // TODO 2010-12-09, Tomasz Pylak: add support for microscopy images in Image Viewer
+            // where there are no wells. Extend API to load images in such cases.
+            for (String dataSet : getParams(request, ParameterNames.DATA_SETS))
+            {
+                builder.append("    <argument>").append(dataSet + ":0.0").append("</argument>\n");
+            }
             for (String dataSetAndWells : getParams(request, ParameterNames.DATA_SET_AND_WELLS))
             {
                 builder.append("    <argument>").append(dataSetAndWells).append("</argument>\n");
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/IImagingReadonlyQueryDAO.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/IImagingReadonlyQueryDAO.java
index 17cefa71191..79194a2867d 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/IImagingReadonlyQueryDAO.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/IImagingReadonlyQueryDAO.java
@@ -54,9 +54,12 @@ public interface IImagingReadonlyQueryDAO extends BaseQuery
                     // joins
                     + "ACQUIRED_IMAGES.CHANNEL_STACK_ID = CHANNEL_STACKS.ID ";
 
+    // FIXME 2010-12-10, Tomasz Pylak: uncomment when we are able to show a representative image
     public static final String SQL_NO_MULTIDIMENTIONAL_DATA_COND =
-            " and CHANNEL_STACKS.T_in_SEC IS NULL                        "
-                    + " and CHANNEL_STACKS.Z_in_M IS NULL                ";
+            " order by CHANNEL_STACKS.T_in_SEC, CHANNEL_STACKS.Z_in_M limit 1";
+
+    // " and CHANNEL_STACKS.T_in_SEC IS NULL                        "
+    // + " and CHANNEL_STACKS.Z_in_M IS NULL                ";
 
     /**
      * @return an HCS image for the specified chanel, well and tile. If many images (e.g. for
-- 
GitLab