package com.github.gwtbootstrap.client.ui;
import com.github.gwtbootstrap.client.ui.base.HasPlacement;
import com.github.gwtbootstrap.client.ui.base.HasShowDelay;
import com.github.gwtbootstrap.client.ui.base.HasTrigger;
import com.github.gwtbootstrap.client.ui.base.IsAnimated;
import com.github.gwtbootstrap.client.ui.constants.Placement;
import com.github.gwtbootstrap.client.ui.constants.Trigger;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.HasText;
import java.util.Set;
/**
* Cell decorator as a Tooltip.
* @author ohashi keisuke
*
* @param <C> Decorated Cell Parameter
*/
public class TooltipCellDecorator<C> implements Cell<C> ,IsAnimated, HasTrigger, HasPlacement, HasText, HasShowDelay{
/**
* Whether the widget is animated or not.
*/
protected boolean animated = true;
/**
* The placement of the widget relative to its trigger element.
*/
protected Placement placement = Placement.TOP;
/**
* The action that triggers the widget.
*/
protected Trigger trigger = Trigger.HOVER;
/**
* The delay until the widget is shown.
*/
protected int showDelayInMilliseconds = 0;
/**
* The delay until the widget is hidden.
*/
protected int hideDelayInMilliseconds = 0;
/**
* Appends the popover to a specific element.
*/
protected String container;
interface Template extends SafeHtmlTemplates {
@Template("<span class='gb-tooltip-cell' id='{0}'>{1}</span>")
SafeHtml span(String id , SafeHtml content);
}
private static Template template = GWT.create(Template.class);
private final Cell<C> cell;
private String tooltip;
/**
* Create Decorator cell
* @param cell decorated cell
*/
public TooltipCellDecorator(Cell<C> cell) {
this.cell = cell;
}
/**
* {@inheritDoc}
*/
@Override
public boolean dependsOnSelection() {
return cell.dependsOnSelection();
}
/**
* {@inheritDoc}
*/
@Override
public Set<String> getConsumedEvents() {
return cell.getConsumedEvents();
}
/**
* {@inheritDoc}
*/
@Override
public boolean handlesSelection() {
return cell.handlesSelection();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isEditing(Context context,
Element parent, C value) {
return cell.isEditing(context, getCellParent(parent), value);
}
/**
* {@inheritDoc}
*/
@Override
public void onBrowserEvent(Context context,
Element parent, C value, NativeEvent event,
ValueUpdater<C> valueUpdater) {
cell.onBrowserEvent(context, getCellParent(parent), value, event, valueUpdater);
}
/**
* {@inheritDoc}
*/
@Override
public void render(final Context context,
final C value, SafeHtmlBuilder sb) {
SafeHtmlBuilder cellBuilder = new SafeHtmlBuilder();
cell.render(context, value, cellBuilder);
final String id = DOM.createUniqueId();
sb.append(template.span(id, cellBuilder.toSafeHtml()));
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
Tooltip.configure("#" + id + "> :first-child",
getTooltipText(context, value),
getAnimation(context, value),
getPlacement(context, value).get(),
getTrigger(context, value).get(),
getShowDelay(context, value),
getHideDelay(context, value),
getContainer()
);
};
});
}
@Override
public boolean resetFocus(Context context,
Element parent, C value) {
return cell.resetFocus(context, getCellParent(parent), value);
}
@Override
public void setValue(Context context,
Element parent, C value) {
cell.setValue(context, getCellParent(parent), value);
}
/**
* {@inheritDoc}
*/
public void setAnimation(boolean animated) {
this.animated = animated;
}
/**
* {@inheritDoc}
*/
public boolean getAnimation() {
return animated;
}
protected boolean getAnimation(Context context,C value) {
return getAnimation();
}
/**
* {@inheritDoc} Relative to its trigger element.
*/
public void setPlacement(Placement placement) {
assert placement != null : "should not be null";
this.placement = placement;
}
/**
* {@inheritDoc}
*/
public Placement getPlacement() {
return placement;
}
protected Placement getPlacement(Context context, C value) {
return getPlacement();
}
/**
* {@inheritDoc}
*/
public void setTrigger(Trigger trigger) {
assert trigger != null : "should not be null";
this.trigger = trigger;
}
/**
* {@inheritDoc}
*/
public Trigger getTrigger() {
return trigger;
}
protected Trigger getTrigger(Context context,C value) {
return getTrigger();
}
/**
* {@inheritDoc}
*/
public void setShowDelay(int delayInMilliseconds) {
showDelayInMilliseconds = delayInMilliseconds;
}
/**
* {@inheritDoc}
*/
public int getShowDelay() {
return showDelayInMilliseconds;
}
protected int getShowDelay(Context context, C value) {
return getShowDelay();
}
/**
* {@inheritDoc}
*/
public void setHideDelay(int delayInMilliseconds) {
hideDelayInMilliseconds = delayInMilliseconds;
}
/**
* {@inheritDoc}
*/
public int getHideDelay() {
return hideDelayInMilliseconds;
}
protected int getHideDelay(Context context, C value) {
return getHideDelay();
}
/**
* {@inheritDoc}
*/
@Override
public String getText() {
return this.tooltip;
}
/**
* {@inheritDoc}
*/
@Override
public void setText(String text) {
assert text != null : "should not be null";
this.tooltip = text;
}
protected String getTooltipText(Context context, C value) {
return getText();
}
/**
* Get the parent element of the decorated cell.
*
* @param parent the parent of this cell
* @return the decorated cell's parent
*/
private Element getCellParent(Element parent) {
return parent.getFirstChildElement().cast();
}
/**
* @return Specific element the Popover/Tooltip is appended to
*/
public String getContainer() {
return container;
}
/**
* Set specific element the Popover/Tooltip is appended to
* @param container Specific element the Popover/Tooltip is appended to. E.g. 'body' or null.
*/
public void setContainer(String container) {
this.container = container;
}
}