From cd1fb81bec181a2ff5d558444dc148ab07c23842 Mon Sep 17 00:00:00 2001
From: buczekp <buczekp>
Date: Tue, 24 Mar 2009 13:38:20 +0000
Subject: [PATCH] [LMS-789] inline Hyperlinks with ClickListeners added and
 used in PropertyGrid for samples links in sample detail view

SVN: 10340
---
 .../application/renderer/LinkRenderer.java    | 37 +++++++-
 .../ui/PropertyValueRenderers.java            | 87 ++++++++++++++-----
 .../AbstractPropertyValueRenderer.java        | 22 +----
 .../AbstractSimplePropertyValueRenderer.java  | 58 +++++++++++++
 .../property/DatePropertyValueRenderer.java   |  2 +-
 .../ui/property/IPropertyValueRenderer.java   |  7 +-
 .../ObjectArrayPropertyValueRenderer.java     | 32 +++----
 .../property/ObjectPropertyValueRenderer.java |  2 +-
 .../application/ui/property/PropertyGrid.java | 22 ++---
 .../ui/widget/InlineHyperlink.java            | 41 +++++++++
 .../sample/GenericSampleViewer.java           | 28 ++++--
 11 files changed, 249 insertions(+), 89 deletions(-)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/AbstractSimplePropertyValueRenderer.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/InlineHyperlink.java

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/renderer/LinkRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/renderer/LinkRenderer.java
index ba7fa62cea8..3242206dea0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/renderer/LinkRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/renderer/LinkRenderer.java
@@ -18,11 +18,14 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer;
 
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.Hyperlink;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.InlineHyperlink;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
+ * @author Piotr Buczek
  */
 public class LinkRenderer
 {
@@ -35,4 +38,34 @@ public class LinkRenderer
         return DOM.toString(div);
     }
 
+    /**
+     * @return {@link Hyperlink} GWT widget that is displayed as a link with given <var>text</var>
+     *         and a <var>listener</var> registered on the click event. The link display style is
+     *         default (not invalidated).
+     */
+    public static Hyperlink getLinkWidget(final String text, final ClickListener listener)
+    {
+        return getLinkWidget(text, listener, false);
+    }
+
+    /**
+     * @return {@link Hyperlink} GWT widget that is displayed as a link with given <var>text</var>
+     *         and a <var>listener</var> registered on the click event. The link display style is
+     *         based on <var>invalidate</var> (default style is for false).
+     */
+    public static Hyperlink getLinkWidget(final String text, final ClickListener listener,
+            boolean invalidate)
+    {
+        Hyperlink link = new InlineHyperlink(text);
+        if (listener != null)
+        {
+            link.addClickListener(listener);
+        }
+        if (invalidate)
+        {
+            link.addStyleName("invalid");
+        }
+        return link;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PropertyValueRenderers.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PropertyValueRenderers.java
index 8f16b6317fe..2313bce9897 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PropertyValueRenderers.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PropertyValueRenderers.java
@@ -16,16 +16,32 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
 
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Hyperlink;
+import com.google.gwt.user.client.ui.InlineHTML;
+import com.google.gwt.user.client.ui.Widget;
+
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DispatcherHelper;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.ITabItemFactory;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.plugin.IClientPlugin;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.plugin.IClientPluginFactory;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.DateRenderer;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.LinkRenderer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.PersonRenderer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.property.AbstractPropertyValueRenderer;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.property.AbstractSimplePropertyValueRenderer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.property.IPropertyValueRenderer;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.DOMUtils;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Invalidation;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Sample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityProperty;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialProperty;
@@ -50,9 +66,9 @@ public final class PropertyValueRenderers
      * Creates a {@link IPropertyValueRenderer} implementation for rendering {@link Sample}.
      */
     public final static IPropertyValueRenderer<Sample> createSamplePropertyValueRenderer(
-            final IMessageProvider messageProvider, final boolean withType)
+            final IViewContext<?> viewContext, final boolean withType)
     {
-        return new SamplePropertyValueRenderer(messageProvider, withType);
+        return new SamplePropertyValueRenderer(viewContext, withType);
     }
 
     /**
@@ -101,9 +117,12 @@ public final class PropertyValueRenderers
     {
         private final boolean withType;
 
-        SamplePropertyValueRenderer(final IMessageProvider messageProvider, final boolean withType)
+        private final IViewContext<?> viewContext;
+
+        SamplePropertyValueRenderer(final IViewContext<?> viewContext, final boolean withType)
         {
-            super(messageProvider);
+            super(viewContext);
+            this.viewContext = viewContext;
             this.withType = withType;
         }
 
@@ -111,23 +130,51 @@ public final class PropertyValueRenderers
         // AbstractPropertyValueRenderer
         //
 
-        @Override
-        protected final String renderNotNull(final Sample sample)
+        public Widget getAsWidget(final Sample sample)
         {
             final String code = sample.getCode();
-            final StringBuilder builder = new StringBuilder();
-            if (sample.getInvalidation() != null)
+            final boolean invalidate = sample.getInvalidation() != null;
+            final ClickListener listener =
+                    new OpenSampleDetailsTabClickListener(sample, viewContext);
+            final Hyperlink link = LinkRenderer.getLinkWidget(code, listener, invalidate);
+
+            FlowPanel panel = new FlowPanel();
+            panel.add(link);
+            if (withType)
             {
-                builder.append(DOMUtils.createDelElement(code));
-            } else
+                panel.add(new InlineHTML(" [" + sample.getSampleType().getCode() + "]"));
+            }
+            return panel;
+        }
+
+        /** A {@link ClickListener} that opens Sample details tab on click. */
+        private static final class OpenSampleDetailsTabClickListener implements ClickListener
+        {
+            private final Sample sample;
+
+            private final IViewContext<?> viewContext;
+
+            public OpenSampleDetailsTabClickListener(Sample sample,
+                    final IViewContext<?> viewContext)
             {
-                builder.append(code);
+                super();
+                this.sample = sample;
+                this.viewContext = viewContext;
             }
-            if (withType)
+
+            public void onClick(Widget sender)
             {
-                builder.append(" [").append(sample.getSampleType().getCode()).append("]");
+
+                final EntityKind entityKind = EntityKind.SAMPLE;
+                final IClientPluginFactory clientPluginFactory =
+                        viewContext.getClientPluginFactoryProvider().getClientPluginFactory(
+                                entityKind, sample.getSampleType());
+                final IClientPlugin<EntityType, EntityTypePropertyType<EntityType>, EntityProperty<EntityType, EntityTypePropertyType<EntityType>>, IIdentifierHolder, IEditableEntity<EntityType, EntityTypePropertyType<EntityType>, EntityProperty<EntityType, EntityTypePropertyType<EntityType>>>> createClientPlugin =
+                        clientPluginFactory.createClientPlugin(entityKind);
+                final ITabItemFactory tabView = createClientPlugin.createEntityViewer(sample);
+
+                DispatcherHelper.dispatchNaviEvent(tabView);
             }
-            return builder.toString();
         }
     }
 
@@ -137,7 +184,7 @@ public final class PropertyValueRenderers
      * @author Christian Ribeaud
      */
     private final static class SampleTypePropertyValueRenderer extends
-            AbstractPropertyValueRenderer<SampleType>
+            AbstractSimplePropertyValueRenderer<SampleType>
     {
 
         SampleTypePropertyValueRenderer(final IMessageProvider messageProvider)
@@ -162,7 +209,7 @@ public final class PropertyValueRenderers
      * @author Christian Ribeaud
      */
     private final static class PersonPropertyValueRenderer extends
-            AbstractPropertyValueRenderer<Person>
+            AbstractSimplePropertyValueRenderer<Person>
     {
 
         PersonPropertyValueRenderer(final IMessageProvider messageProvider)
@@ -187,7 +234,7 @@ public final class PropertyValueRenderers
      * @author Christian Ribeaud
      */
     private final static class InvalidationPropertyValueRenderer extends
-            AbstractPropertyValueRenderer<Invalidation>
+            AbstractSimplePropertyValueRenderer<Invalidation>
     {
 
         InvalidationPropertyValueRenderer(final IMessageProvider messageProvider)
@@ -224,7 +271,7 @@ public final class PropertyValueRenderers
      * @author Christian Ribeaud
      */
     private final static class EntityPropertyPropertyValueRenderer<T extends EntityProperty<?, ?>>
-            extends AbstractPropertyValueRenderer<T>
+            extends AbstractSimplePropertyValueRenderer<T>
     {
 
         EntityPropertyPropertyValueRenderer(final IMessageProvider messageProvider)
@@ -258,7 +305,7 @@ public final class PropertyValueRenderers
      * @author Izabela Adamczyk
      */
     private final static class ExperimentTypePropertyValueRenderer extends
-            AbstractPropertyValueRenderer<ExperimentType>
+            AbstractSimplePropertyValueRenderer<ExperimentType>
     {
 
         ExperimentTypePropertyValueRenderer(final IMessageProvider messageProvider)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/AbstractPropertyValueRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/AbstractPropertyValueRenderer.java
index 9c70590defb..3054deb798a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/AbstractPropertyValueRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/AbstractPropertyValueRenderer.java
@@ -19,8 +19,7 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.proper
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
 
 /**
- * A default <code>PropertyValueRenderer</code> implementation which catches <code>null</code>
- * value by rendering <code>-</code>.
+ * A default <code>PropertyValueRenderer</code> implementation.
  * 
  * @author Christian Ribeaud
  */
@@ -28,9 +27,6 @@ public abstract class AbstractPropertyValueRenderer<T> implements IPropertyValue
 {
     private final IMessageProvider messageProvider;
 
-    /** The table <code>null</code> value representation. */
-    public static final String TABLE_NULL_VALUE = "-";
-
     public AbstractPropertyValueRenderer(final IMessageProvider messageProvider)
     {
         this.messageProvider = messageProvider;
@@ -40,20 +36,4 @@ public abstract class AbstractPropertyValueRenderer<T> implements IPropertyValue
     {
         return messageProvider;
     }
-
-    /** Here we are sure to get a non-<code>null</code> value. */
-    protected abstract String renderNotNull(final T value);
-
-    //
-    // PropertyValueRenderer
-    //
-
-    public final String render(final T object)
-    {
-        if (object == null)
-        {
-            return TABLE_NULL_VALUE;
-        }
-        return renderNotNull(object);
-    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/AbstractSimplePropertyValueRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/AbstractSimplePropertyValueRenderer.java
new file mode 100644
index 00000000000..ad20b12f8fe
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/AbstractSimplePropertyValueRenderer.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2007 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.generic.client.web.client.application.ui.property;
+
+import com.google.gwt.user.client.ui.InlineHTML;
+import com.google.gwt.user.client.ui.Widget;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
+
+/**
+ * A default <code>PropertyValueRenderer</code> implementation for simple property values which
+ * catches <code>null</code> value by rendering <code>-</code> and renders as an inline html.
+ * 
+ * @author Piotr Buczek
+ */
+public abstract class AbstractSimplePropertyValueRenderer<T> extends
+        AbstractPropertyValueRenderer<T>
+{
+    /** The table <code>null</code> value representation. */
+    public static final String TABLE_NULL_VALUE = "-";
+
+    public AbstractSimplePropertyValueRenderer(final IMessageProvider messageProvider)
+    {
+        super(messageProvider);
+    }
+
+    /** Here we are sure to get a non-<code>null</code> value. */
+    protected abstract String renderNotNull(final T value);
+
+    private final String render(final T object)
+    {
+        if (object == null)
+        {
+            return TABLE_NULL_VALUE;
+        }
+        return renderNotNull(object);
+    }
+
+    public Widget getAsWidget(final T object)
+    {
+        // default widget is a simple HTML span element wrapped around text
+        return new InlineHTML(render(object));
+    }
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/DatePropertyValueRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/DatePropertyValueRenderer.java
index 4dd915622c3..ab235bb209b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/DatePropertyValueRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/DatePropertyValueRenderer.java
@@ -26,7 +26,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMess
  * 
  * @author Christian Ribeaud
  */
-public class DatePropertyValueRenderer extends AbstractPropertyValueRenderer<Date>
+public class DatePropertyValueRenderer extends AbstractSimplePropertyValueRenderer<Date>
 {
     private final String pattern;
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/IPropertyValueRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/IPropertyValueRenderer.java
index 23aba3fe6b1..9e45a325f17 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/IPropertyValueRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/IPropertyValueRenderer.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.property;
 
+import com.google.gwt.user.client.ui.Widget;
+
 /**
  * A property value renderer for <code>Object</code>.
  * 
@@ -26,8 +28,7 @@ public interface IPropertyValueRenderer<T>
 {
 
     /**
-     * Renders given <var>object</var> found at given <var>row</var> as <code>String</code>
-     * object.
+     * @return A {@link Widget} displaying given <var>object</var>.
      */
-    public String render(final T object);
+    public Widget getAsWidget(final T object);
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/ObjectArrayPropertyValueRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/ObjectArrayPropertyValueRenderer.java
index 29a9764d2df..a21268cb784 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/ObjectArrayPropertyValueRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/ObjectArrayPropertyValueRenderer.java
@@ -16,11 +16,14 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.property;
 
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.DOMUtils;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Widget;
+
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
 
 /**
- * A <code>PropertyValueRenderer</code> implementation for <code>Object[]</code>.
+ * A <code>PropertyValueRenderer</code> implementation for <code>Object[]</code> that renders as a
+ * one column table.
  * 
  * @author Christian Ribeaud
  */
@@ -35,32 +38,17 @@ public final class ObjectArrayPropertyValueRenderer<T> extends AbstractPropertyV
         this.propertyValueRenderer = propertyValueRenderer;
     }
 
-    protected String getItemSeparator()
-    {
-        return DOMUtils.BR;
-    }
-
     //
     // AbstractPropertyValueRenderer
     //
 
-    @Override
-    public final String renderNotNull(final T[] objects)
+    public Widget getAsWidget(T[] objects)
     {
-        if (objects.length == 0)
-        {
-            return "";
-        }
-        final String itemSeparator = getItemSeparator();
-        final StringBuffer buffer = new StringBuffer();
-        for (int i = 0; i < objects.length; i++)
+        FlowPanel panel = new FlowPanel();
+        for (T object : objects)
         {
-            if (buffer.length() > 1)
-            {
-                buffer.append(itemSeparator);
-            }
-            buffer.append(propertyValueRenderer.render(objects[i]));
+            panel.add(propertyValueRenderer.getAsWidget(object));
         }
-        return buffer.toString();
+        return panel;
     }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/ObjectPropertyValueRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/ObjectPropertyValueRenderer.java
index 14ef7ef08ca..61e05aeb079 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/ObjectPropertyValueRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/ObjectPropertyValueRenderer.java
@@ -23,7 +23,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMess
  * 
  * @author Christian Ribeaud
  */
-public class ObjectPropertyValueRenderer extends AbstractPropertyValueRenderer<Object>
+public class ObjectPropertyValueRenderer extends AbstractSimplePropertyValueRenderer<Object>
 {
     public ObjectPropertyValueRenderer(final IMessageProvider messageProvider)
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/PropertyGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/PropertyGrid.java
index 27549be3ec4..02adea45ef7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/PropertyGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property/PropertyGrid.java
@@ -24,6 +24,7 @@ import java.util.Map;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.SourcesTableEvents;
 import com.google.gwt.user.client.ui.TableListener;
+import com.google.gwt.user.client.ui.Widget;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
 
@@ -116,10 +117,10 @@ public final class PropertyGrid extends Grid
     }
 
     /**
-     * Adds a <code>GridCellListener</code> for given <var>row</var>.
+     * Adds a <code>GridCellListener</code> for given <var>key</var>.
      * <p>
-     * If there is already a <code>GridCellListener</code> registered for given <var>row</var>,
-     * the new one will replace it.
+     * If there is already a <code>GridCellListener</code> registered for given <var>key</var>, the
+     * new one will replace it.
      * </p>
      */
     public final void addGridCellListener(final String key, final GridCellListener listener)
@@ -137,17 +138,17 @@ public final class PropertyGrid extends Grid
         this.properties = properties;
         fillTable();
     }
-    
+
     public Map<String, ?> getProperties()
     {
         return properties;
     }
 
-    private final <T> String renderValue(final T value)
+    private final <T> Widget getAsWidget(final T value)
     {
         final IPropertyValueRenderer<? super T> propertyValueRenderer =
                 getPropertyValueRenderer(value);
-        return propertyValueRenderer.render(value);
+        return propertyValueRenderer.getAsWidget(value);
     }
 
     private final void fillTable()
@@ -157,8 +158,10 @@ public final class PropertyGrid extends Grid
         for (final Iterator<String> iterator = properties.keySet().iterator(); iterator.hasNext(); row++)
         {
             final String key = iterator.next();
+            final Object value = properties.get(key);
+            final Widget widget = getAsWidget(value);
             setHTML(row, 0, key);
-            setHTML(row, 1, renderValue(properties.get(key)));
+            setWidget(row, 1, widget);
         }
     }
 
@@ -179,15 +182,14 @@ public final class PropertyGrid extends Grid
             // Only for property value (index 1).
             if (column == 1)
             {
-                final String cellValue = getText(row, column);
-                final GridCellListener listener = listeners.get(cellValue);
+                final String keyValue = getText(row, 0);
+                final GridCellListener listener = listeners.get(keyValue);
                 if (listener != null)
                 {
                     listener.onCellClicked();
                 }
             }
         }
-
     }
 
     /** Event listener interface for property table events. */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/InlineHyperlink.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/InlineHyperlink.java
new file mode 100644
index 00000000000..86b36ef4a24
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/InlineHyperlink.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2008 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.generic.client.web.client.application.ui.widget;
+
+import com.google.gwt.user.client.ui.Hyperlink;
+
+/**
+ * A {@link Hyperlink} widget extension that changes default display style from block to inline and
+ * keeps no history token.
+ * 
+ * @author Piotr Buczek
+ */
+public final class InlineHyperlink extends Hyperlink
+{
+
+    /**
+     * Creates a hyperlink with its text specified (no history token) and inline display style.
+     * 
+     * @param text the hyperlink's text
+     */
+    public InlineHyperlink(String text)
+    {
+        super(text, null);
+        addStyleName("inline");
+    }
+    
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleViewer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleViewer.java
index c323def1fd9..953755077ac 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleViewer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleViewer.java
@@ -130,7 +130,8 @@ public final class GenericSampleViewer extends AbstractViewer<IGenericClientServ
         container.add(panel, new RowData(1, 0.5, new Margins(0, 5, 5, 0)));
         // External data
         panel = createContentPanel(viewContext.getMessage(Dict.EXTERNAL_DATA_HEADING));
-        disposableBrowser = SampleDataSetBrowser.create(viewContext, sampleIdentifier, getId() + DATA_POSTFIX);
+        disposableBrowser =
+                SampleDataSetBrowser.create(viewContext, sampleIdentifier, getId() + DATA_POSTFIX);
         panel.add(disposableBrowser.getComponent());
         container.add(panel, new RowData(1, 0.5, new Margins(0, 5, 0, 0)));
         return container;
@@ -223,6 +224,14 @@ public final class GenericSampleViewer extends AbstractViewer<IGenericClientServ
         properties.put(messageProvider.getMessage(Dict.REGISTRATOR), sample.getRegistrator());
         properties.put(messageProvider.getMessage(Dict.REGISTRATION_DATE), sample
                 .getRegistrationDate());
+        
+        // TODO 2009-03-24 Piotr Buczek: Uncomment after lazy initialization problem is resolved
+        // final Procedure procedure = sample.getValidProcedure();
+        // if (procedure != null)
+        // {
+        // properties.put(messageProvider.getMessage(Dict.EXPERIMENT), procedure.getExperiment());
+        // }
+
         if (generated.length > 0)
         {
             properties.put(messageProvider.getMessage(Dict.GENERATED_SAMPLES), generated);
@@ -264,22 +273,23 @@ public final class GenericSampleViewer extends AbstractViewer<IGenericClientServ
     }
 
     public static PropertyGrid createPropertyGrid(String sampleIdentifier,
-            final SampleGeneration sampleGeneration, final IMessageProvider messageProvider)
+            final SampleGeneration sampleGeneration, final IViewContext<?> viewContext)
     {
-        final Map<String, Object> properties = createProperties(messageProvider, sampleGeneration);
-        final PropertyGrid propertyGrid = new PropertyGrid(messageProvider, properties.size());
+        final Map<String, Object> properties = createProperties(viewContext, sampleGeneration);
+        final PropertyGrid propertyGrid = new PropertyGrid(viewContext, properties.size());
         propertyGrid.getElement().setId(PROPERTIES_ID_PREFIX + sampleIdentifier);
         propertyGrid.registerPropertyValueRenderer(Person.class, PropertyValueRenderers
-                .createPersonPropertyValueRenderer(messageProvider));
+                .createPersonPropertyValueRenderer(viewContext));
         propertyGrid.registerPropertyValueRenderer(SampleType.class, PropertyValueRenderers
-                .createSampleTypePropertyValueRenderer(messageProvider));
+                .createSampleTypePropertyValueRenderer(viewContext));
         propertyGrid.registerPropertyValueRenderer(Sample.class, PropertyValueRenderers
-                .createSamplePropertyValueRenderer(messageProvider, true));
+                .createSamplePropertyValueRenderer(viewContext, true));
         propertyGrid.registerPropertyValueRenderer(Invalidation.class, PropertyValueRenderers
-                .createInvalidationPropertyValueRenderer(messageProvider));
+                .createInvalidationPropertyValueRenderer(viewContext));
         propertyGrid.registerPropertyValueRenderer(SampleProperty.class, PropertyValueRenderers
-                .createSamplePropertyPropertyValueRenderer(messageProvider));
+                .createSamplePropertyPropertyValueRenderer(viewContext));
         propertyGrid.setProperties(properties);
+
         return propertyGrid;
     }
 
-- 
GitLab