/*
*
* Copyright (C) 2007-2015 Licensed to the Comunes Association (CA) under
* one or more contributor license agreements (see COPYRIGHT for details).
* The CA licenses this file to you under the GNU Affero General Public
* License version 3, (the "License"); you may not use this file except in
* compliance with the License. This file is part of kune.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package cc.kune.common.client.tooltip;
import cc.kune.common.client.utils.TimerWrapper;
import cc.kune.common.client.utils.TimerWrapper.Executer;
import cc.kune.common.shared.utils.TextUtils;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Singleton;
/**
* The Class Tooltip.
*
* @author vjrj@ourproject.org (Vicente J. Ruiz Jurado)
*/
@Singleton
public class Tooltip extends PopupPanel {
/**
* The Interface TooltipUiBinder.
*
* @author vjrj@ourproject.org (Vicente J. Ruiz Jurado)
*/
interface TooltipUiBinder extends UiBinder<Widget, Tooltip> {
}
private static BlurHandler blurHandler = new BlurHandler() {
@Override
public void onBlur(final BlurEvent event) {
getTip().getTimers().onOut();
}
};
private static FocusHandler focusHandler = new FocusHandler() {
@Override
public void onFocus(final FocusEvent event) {
getTip().getTimers().onOut();
}
};
private static final String KUNE_TOOLTIP_ATTR = "kune_tooltip";
private static MouseOutHandler mouseOutHandler = new MouseOutHandler() {
@Override
public void onMouseOut(final MouseOutEvent event) {
getTip().getTimers().onOut();
}
};
private static MouseOverHandler mouseOverHandler = new MouseOverHandler() {
@Override
public void onMouseOver(final MouseOverEvent event) {
final Widget source = (Widget) event.getSource();
final String text = source.getElement().getAttribute(KUNE_TOOLTIP_ATTR);
getTip().getTimers().configureOver(new Executer() {
@Override
public void execute() {
getTip().show(source, text);
}
});
getTip().getTimers().onOver();
}
};
private static Tooltip tip;
/** The ui binder. */
private static TooltipUiBinder uiBinder = GWT.create(TooltipUiBinder.class);
public static Tooltip getTip() {
if (tip == null) {
tip = new Tooltip();
}
return tip;
}
/**
* To.
*
* @param widget
* the widget
* @param text
* the text
*/
public static void to(final Widget forWidget, final String text) {
forWidget.getElement().setAttribute(KUNE_TOOLTIP_ATTR, text);
forWidget.addDomHandler(mouseOverHandler, MouseOverEvent.getType());
forWidget.addDomHandler(focusHandler, FocusEvent.getType());
forWidget.addDomHandler(blurHandler, BlurEvent.getType());
forWidget.addDomHandler(mouseOutHandler, MouseOutEvent.getType());
}
/** The arrow. */
@UiField
HTMLPanel arrow;
/** The arrow border. */
@UiField
HTMLPanel arrowBorder;
/** The content. */
@UiField
FlowPanel content;
/** The current. */
private Widget current;
/** The flow. */
@UiField
FlowPanel flow;
/** The tooltip. */
@UiField
HTMLPanel mainPanel;
/** The text label. */
private final Label textLabel;
/** The timers. */
private final TooltipTimers timers;
/** The title. */
@UiField
InlineLabel title;
/**
* Instantiates a new tooltip.
*/
private Tooltip() {
super.add(uiBinder.createAndBindUi(this));
super.setStyleName("k-tooltip-no-chrome");
super.getElement().getStyle().setZIndex(10000);
super.setAutoHideEnabled(false);
super.setAnimationEnabled(false);
final TimerWrapper overTimer = new TimerWrapper();
final Executer hideExecuter = new Executer() {
@Override
public void execute() {
hide();
}
};
final TimerWrapper outTimer = new TimerWrapper();
final TimerWrapper securityTimer = new TimerWrapper();
timers = new TooltipTimers(overTimer, outTimer, securityTimer);
outTimer.configure(hideExecuter);
securityTimer.configure(hideExecuter);
textLabel = new Label();
content.add(textLabel);
}
/**
* Calculate position.
*
* @return the tooltip position
*/
private TooltipPosition calculatePosition(final Widget forWidget) {
return TooltipPositionCalculator.calculate(Window.getClientWidth(), Window.getClientHeight(),
forWidget.getAbsoluteLeft(), forWidget.getAbsoluteTop(), forWidget.getOffsetWidth(),
forWidget.getOffsetHeight(), getTip().getWidth(), getTip().getHeight());
}
/**
* Gets the height.
*
* @return the height
*/
protected int getHeight() {
return mainPanel.getElement().getOffsetHeight();
}
protected TooltipTimers getTimers() {
return timers;
}
/**
* Gets the width.
*
* @return the width
*/
protected int getWidth() {
return mainPanel.getElement().getOffsetWidth();
}
/*
* (non-Javadoc)
*
* @see com.google.gwt.user.client.ui.PopupPanel#hide()
*/
@Override
public void hide() {
super.hide();
timers.cancel();
current = null;
}
/*
* (non-Javadoc)
*
* @see com.google.gwt.user.client.ui.PopupPanel#isVisible()
*/
@Override
public boolean isVisible() {
return super.isShowing();
}
/**
* Checks if is visible or will be.
*
* @return true, if is visible or will be
*/
public boolean isVisibleOrWillBe() {
return mainPanel.isVisible() || timers.showIsScheduled();
}
/**
* Sets the text.
*
* @param text
* the new text
*/
public void setText(final String text) {
textLabel.setText(text);
}
public void show(final Widget forWidget, final String text) {
if (current != null && !current.equals(forWidget) && getTip().isShowing()) {
Tooltip.getTip().hide();
}
setText(text);
if (forWidget.isAttached() && forWidget.isVisible()
&& (TextUtils.notEmpty(text) && !"undefined".equals(text))) {
Tooltip.super.show();
current = forWidget;
final int clientWidth = Window.getClientWidth();
if (mainPanel.getOffsetWidth() >= clientWidth) {
mainPanel.getElement().getStyle().setWidth(clientWidth - 20, Unit.PX);
} else if (mainPanel.getOffsetWidth() > 430) {
mainPanel.getElement().getStyle().setWidth(430, Unit.PX);
} else {
mainPanel.getElement().getStyle().clearWidth();
}
showAt(forWidget);
}
}
/**
* Show at.
*
* @param position
* the position
*/
protected void showAt(final TooltipPosition position) {
getTip().setPopupPosition(position.getLeft(), position.getTop());
switch (position.getArrowPosition()) {
case N:
case NW:
case NE:
arrow.getElement().getStyle().setLeft(position.getArrowLeft(), Unit.PX);
arrow.getElement().getStyle().clearBottom();
arrow.getElement().getStyle().setTop(position.getArrowTop() + 3, Unit.PX);
arrowBorder.getElement().getStyle().setLeft(position.getArrowLeft(), Unit.PX);
arrowBorder.getElement().getStyle().clearBottom();
arrowBorder.getElement().getStyle().setTop(position.getArrowTop() + 1, Unit.PX);
arrow.getElement().removeClassName("k-tooltip-arrow-s");
arrow.getElement().addClassName("k-tooltip-arrow-n");
arrowBorder.getElement().removeClassName("k-tooltip-arrow-border-s");
arrowBorder.getElement().addClassName("k-tooltip-arrow-border-n");
break;
case S:
case SE:
case SW:
arrow.getElement().getStyle().setLeft(position.getArrowLeft(), Unit.PX);
arrow.getElement().getStyle().clearTop();
arrow.getElement().getStyle().setBottom(position.getArrowTop() + 2, Unit.PX);
arrowBorder.getElement().getStyle().setLeft(position.getArrowLeft(), Unit.PX);
arrowBorder.getElement().getStyle().clearTop();
arrowBorder.getElement().getStyle().setBottom(position.getArrowTop(), Unit.PX);
arrow.getElement().addClassName("k-tooltip-arrow-s");
arrow.getElement().removeClassName("k-tooltip-arrow-n");
arrowBorder.getElement().addClassName("k-tooltip-arrow-border-s");
arrowBorder.getElement().removeClassName("k-tooltip-arrow-border-n");
break;
}
}
/**
* Show at.
*/
private void showAt(final Widget forWidget) {
Tooltip.getTip().showAt(calculatePosition(forWidget));
}
/**
* Show temporally.
*/
public void showTemporally(final Widget forWidget, final String text) {
show(forWidget, text);
timers.showTemporally();
}
}