/*
 * ImageButtonColumn.java
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */
package org.rstudio.core.client.cellview;

import static com.google.gwt.dom.client.BrowserEvents.CLICK;
import static com.google.gwt.dom.client.BrowserEvents.KEYDOWN;

import org.rstudio.core.client.resources.ImageResource2x;
import org.rstudio.core.client.widget.OperationWithInput;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.Column;

public class ImageButtonColumn<T> extends Column<T, T>
{
   public static interface TitleProvider<U>
   {
      public String get(U object);
   }
   
   private static class ImageButtonCell<U> extends AbstractCell<U>
   {
      public ImageButtonCell(final ImageResource2x image,
                             final TitleProvider<U> titleProvider)
      {
         super(CLICK, KEYDOWN);
         
         image_ = image;
         titleProvider_ = titleProvider;
      }
      
      @Override
      public void render(Context context,
                         U value,
                         SafeHtmlBuilder sb)
      {
         if (value != null)
         {
            sb.appendHtmlConstant("<span title=\"" + titleProvider_.get(value) + "\" " +
                  "style=\"cursor: pointer;\">");
            sb.append(image_.getSafeHtml());
            sb.appendHtmlConstant("</span>");
         }
      }
      
      @Override
      public void onBrowserEvent(Context context,
                                 Element parent,
                                 U value,
                                 NativeEvent event,
                                 ValueUpdater<U> valueUpdater)
      {
         super.onBrowserEvent(context, parent, value, event, valueUpdater);
         
         if (CLICK.equals(event.getType()))
         {
            EventTarget eventTarget = event.getEventTarget();
            if (!Element.is(eventTarget))
               return;
            
            if (parent.getFirstChildElement().isOrHasChild(Element.as(eventTarget))) {
               // Ignore clicks that occur outside of the main element.
               onEnterKeyDown(context, parent, value, event, valueUpdater);
            }
         }
      }
      
      @Override
      protected void onEnterKeyDown(Context context,
                                    Element Parent,
                                    U value,
                                    NativeEvent event,
                                    ValueUpdater<U> valueUpdater)
      {
         if (valueUpdater != null)
            valueUpdater.update(value);
      }
      
      private final ImageResource2x image_;
      private final TitleProvider<U> titleProvider_;
   }
   
   public ImageButtonColumn(final ImageResource2x image,
                            final OperationWithInput<T> onClick,
                            final TitleProvider<T> titleProvider)
   {
      super(new ImageButtonCell<T>(image, titleProvider));

      setFieldUpdater(new FieldUpdater<T, T>() {
         public void update(int index, T object, T value)
         {
            if (value != null)
               onClick.execute(object);
         }
      });
   }
   
   public ImageButtonColumn(final ImageResource2x image,
                            final OperationWithInput<T> onClick,
                            final String title)
   {
      this(image, onClick, new TitleProvider<T>()
      {
         @Override
         public String get(T object)
         {
            return title;
         }
      });
   }

   @Override
   public T getValue(T object)
   {
      if (showButton(object))
         return object;
      else
         return null;
   }
   
   protected boolean showButton(T object)
   {
      return true;
   }
}
@@ -1002,32 +1002,71 @@
 t.ValueUpdater;%0A
+import com.google.gwt.core.client.GWT;%0A
 import com.googl
@@ -1087,24 +1087,24 @@
 nt.Element;%0A
-
 import com.g
@@ -1179,24 +1179,129 @@
 ativeEvent;%0A
+import com.google.gwt.safehtml.client.SafeHtmlTemplates;%0Aimport com.google.gwt.safehtml.shared.SafeHtml;%0A
 import com.g
@@ -1541,24 +1541,237 @@
 );%0A   %7D%0A   %0A
+   public static interface RenderTemplates extends SafeHtmlTemplates%0A   %7B%0A      @Template(%22%3Cspan title=%5C%22%7B1%7D%5C%22 style=%5C%22cursor: pointer;%5C%22%3E%7B0%7D%3C/span%3E%22)%0A      SafeHtml render(SafeHtml image, String title);%0A   %7D%0A   %0A
    private s
@@ -2295,214 +2295,74 @@
 pend
-HtmlConstant(%22%3Cspan title=%5C%22%22 + titleProvider_.get(value) + %22%5C%22 %22 +%0A                  %22style=%5C%22cursor: pointer;%5C%22%3E%22);%0A            sb.append(image_.getSafeHtml());%0A            sb.appendHtmlConstant(%22%3C/span%3E%22
+(TEMPLATES.render(image_.getSafeHtml(), titleProvider_.get(value))
 );%0A 
@@ -4754,9 +4754,100 @@
 e;%0A   %7D%0A
+   %0A   private static final RenderTemplates TEMPLATES = GWT.create(RenderTemplates.class);%0A
 %7D

use SafeHtmlTemplates for safe html generation