123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- /*
- @VaadinApache2LicenseForJavaFiles@
- */
- package com.vaadin.terminal.gwt.client;
-
- import com.google.gwt.user.client.DOM;
- import com.google.gwt.user.client.Element;
- import com.google.gwt.user.client.Event;
- import com.google.gwt.user.client.Timer;
- import com.google.gwt.user.client.Window;
- import com.google.gwt.user.client.ui.FlowPanel;
- import com.vaadin.terminal.gwt.client.ui.VOverlay;
-
- /**
- * TODO open for extension
- */
- public class VTooltip extends VOverlay {
- private static final String CLASSNAME = "v-tooltip";
- private static final int MARGIN = 4;
- public static final int TOOLTIP_EVENTS = Event.ONKEYDOWN
- | Event.ONMOUSEOVER | Event.ONMOUSEOUT | Event.ONMOUSEMOVE
- | Event.ONCLICK;
- protected static final int MAX_WIDTH = 500;
- private static final int QUICK_OPEN_TIMEOUT = 1000;
- private static final int CLOSE_TIMEOUT = 300;
- private static final int OPEN_DELAY = 750;
- private static final int QUICK_OPEN_DELAY = 100;
- VErrorMessage em = new VErrorMessage();
- Element description = DOM.createDiv();
- private ComponentConnector tooltipOwner;
-
- private boolean closing = false;
- private boolean opening = false;
- private ApplicationConnection ac;
- // Open next tooltip faster. Disabled after 2 sec of showTooltip-silence.
- private boolean justClosed = false;
- // If this is "additional" tooltip, this field contains the key for it
- private Object tooltipKey;
-
- public VTooltip(ApplicationConnection client) {
- super(false, false, true);
- ac = client;
- setStyleName(CLASSNAME);
- FlowPanel layout = new FlowPanel();
- setWidget(layout);
- layout.add(em);
- DOM.setElementProperty(description, "className", CLASSNAME + "-text");
- DOM.appendChild(layout.getElement(), description);
- setSinkShadowEvents(true);
- }
-
- /**
- * Show a popup containing the information in the "info" tooltip
- *
- * @param info
- */
- private void show(TooltipInfo info) {
- boolean hasContent = false;
- if (info.getErrorUidl() != null) {
- em.setVisible(true);
- em.updateFromUIDL(info.getErrorUidl());
- hasContent = true;
- } else {
- em.setVisible(false);
- }
- if (info.getTitle() != null && !"".equals(info.getTitle())) {
- DOM.setInnerHTML(description, info.getTitle());
- DOM.setStyleAttribute(description, "display", "");
- hasContent = true;
- } else {
- DOM.setInnerHTML(description, "");
- DOM.setStyleAttribute(description, "display", "none");
- }
- if (hasContent) {
- setPopupPositionAndShow(new PositionCallback() {
- public void setPosition(int offsetWidth, int offsetHeight) {
-
- if (offsetWidth > MAX_WIDTH) {
- setWidth(MAX_WIDTH + "px");
-
- // Check new height and width with reflowed content
- offsetWidth = getOffsetWidth();
- offsetHeight = getOffsetHeight();
- }
-
- int x = tooltipEventMouseX + 10 + Window.getScrollLeft();
- int y = tooltipEventMouseY + 10 + Window.getScrollTop();
-
- if (x + offsetWidth + MARGIN - Window.getScrollLeft() > Window
- .getClientWidth()) {
- x = Window.getClientWidth() - offsetWidth - MARGIN;
- }
-
- if (y + offsetHeight + MARGIN - Window.getScrollTop() > Window
- .getClientHeight()) {
- y = tooltipEventMouseY - 5 - offsetHeight;
- if (y - Window.getScrollTop() < 0) {
- // tooltip does not fit on top of the mouse either,
- // put it at the top of the screen
- y = Window.getScrollTop();
- }
- }
-
- setPopupPosition(x, y);
- sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT);
- }
- });
- } else {
- hide();
- }
- }
-
- public void showTooltip(ComponentConnector owner, Event event, Object key) {
- if (closing && tooltipOwner == owner && tooltipKey == key) {
- // return to same tooltip, cancel closing
- closeTimer.cancel();
- closing = false;
- justClosedTimer.cancel();
- justClosed = false;
- return;
- }
-
- if (closing) {
- closeNow();
- }
-
- updatePosition(event);
-
- if (opening) {
- showTimer.cancel();
- }
- tooltipOwner = owner;
- tooltipKey = key;
-
- // Schedule timer for showing the tooltip according to if it was
- // recently closed or not.
- if (justClosed) {
- showTimer.schedule(QUICK_OPEN_DELAY);
- } else {
- showTimer.schedule(OPEN_DELAY);
- }
- opening = true;
- }
-
- private void closeNow() {
- if (closing) {
- hide();
- tooltipOwner = null;
- setWidth("");
- closing = false;
- }
- }
-
- private Timer showTimer = new Timer() {
- @Override
- public void run() {
- TooltipInfo info = ac.getTooltipTitleInfo(tooltipOwner, tooltipKey);
- if (null != info) {
- show(info);
- }
- opening = false;
- }
- };
-
- private Timer closeTimer = new Timer() {
- @Override
- public void run() {
- closeNow();
- justClosedTimer.schedule(2000);
- justClosed = true;
- }
- };
-
- private Timer justClosedTimer = new Timer() {
- @Override
- public void run() {
- justClosed = false;
- }
- };
-
- public void hideTooltip() {
- if (opening) {
- showTimer.cancel();
- opening = false;
- tooltipOwner = null;
- }
- if (!isAttached()) {
- return;
- }
- if (closing) {
- // already about to close
- return;
- }
- closeTimer.schedule(CLOSE_TIMEOUT);
- closing = true;
- justClosed = true;
- justClosedTimer.schedule(QUICK_OPEN_TIMEOUT);
-
- }
-
- private int tooltipEventMouseX;
- private int tooltipEventMouseY;
-
- public void updatePosition(Event event) {
- tooltipEventMouseX = DOM.eventGetClientX(event);
- tooltipEventMouseY = DOM.eventGetClientY(event);
-
- }
-
- public void handleTooltipEvent(Event event, ComponentConnector owner, Object key) {
- final int type = DOM.eventGetType(event);
- if ((VTooltip.TOOLTIP_EVENTS & type) == type) {
- if (type == Event.ONMOUSEOVER) {
- showTooltip(owner, event, key);
- } else if (type == Event.ONMOUSEMOVE) {
- updatePosition(event);
- } else {
- hideTooltip();
- }
- } else {
- // non-tooltip event, hide tooltip
- hideTooltip();
- }
- }
-
- @Override
- public void onBrowserEvent(Event event) {
- final int type = DOM.eventGetType(event);
- // cancel closing event if tooltip is mouseovered; the user might want
- // to scroll of cut&paste
-
- switch (type) {
- case Event.ONMOUSEOVER:
- closeTimer.cancel();
- closing = false;
- break;
- case Event.ONMOUSEOUT:
- hideTooltip();
- break;
- default:
- // NOP
- }
- }
-
- }
|