
com.extjs.gxt.ui.client.widget.tips.ToolTip Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gxt Show documentation
Show all versions of gxt Show documentation
Rich Internet Application Framework for GWT
/*
* Sencha GXT 2.3.0 - Sencha for GWT
* Copyright(c) 2007-2013, Sencha, Inc.
* [email protected]
*
* http://www.sencha.com/products/gxt/license/
*/
package com.extjs.gxt.ui.client.widget.tips;
import java.util.Date;
import com.extjs.gxt.ui.client.GXT;
import com.extjs.gxt.ui.client.core.El;
import com.extjs.gxt.ui.client.core.XDOM;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.EventType;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.util.Params;
import com.extjs.gxt.ui.client.util.Point;
import com.extjs.gxt.ui.client.util.Region;
import com.extjs.gxt.ui.client.util.Size;
import com.extjs.gxt.ui.client.util.Util;
import com.extjs.gxt.ui.client.widget.Component;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.event.dom.client.KeyCodes;
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;
/**
* A standard tooltip implementation for providing additional information when
* hovering over a target element.
*/
public class ToolTip extends Tip {
protected El anchorEl;
protected String anchorStyle;
protected Timer dismissTimer;
protected Timer hideTimer;
protected Listener listener;
protected Timer showTimer;
protected Component target;
protected Point targetXY = new Point(0, 0);
protected String titleHtml, html;
protected ToolTipConfig toolTipConfig;
private Date lastActive;
/**
* Creates a new tool tip.
*/
public ToolTip() {
toolTipConfig = new ToolTipConfig();
lastActive = new Date();
monitorWindowResize = true;
}
/**
* Creates a new tool tip.
*
* @param target the target widget
*/
public ToolTip(Component target) {
this();
initTarget(target);
}
/**
* Creates a new tool tip for the given target.
*
* @param target the target widget
*/
public ToolTip(Component target, ToolTipConfig config) {
this();
updateConfig(config);
initTarget(target);
}
/**
* Returns the quick show interval.
*
* @return the quick show interval
*/
public int getQuickShowInterval() {
return quickShowInterval;
}
/**
* Returns the current tool tip config.
*
* @return the tool tip config
*/
public ToolTipConfig getToolTipConfig() {
return toolTipConfig;
}
@Override
public void hide() {
clearTimers();
lastActive = new Date();
super.hide();
}
public void initTarget(final Component target) {
if (this.target != null) {
this.target.removeListener(Events.OnMouseOver, listener);
this.target.removeListener(Events.OnMouseOut, listener);
this.target.removeListener(Events.OnMouseMove, listener);
this.target.removeListener(Events.Hide, listener);
this.target.removeListener(Events.Detach, listener);
this.target.removeListener(Events.Render, listener);
if (GXT.isFocusManagerEnabled()) {
this.target.removeListener(Events.OnFocus, listener);
this.target.removeListener(Events.OnBlur, listener);
this.target.removeListener(Events.OnKeyDown, listener);
}
}
this.target = target;
if (listener == null) {
listener = new Listener() {
public void handleEvent(ComponentEvent be) {
Element source = target.getElement();
EventType type = be.getType();
if (type == Events.OnMouseOver) {
EventTarget from = be.getEvent().getRelatedEventTarget();
if (from == null
|| (Element.is(source) && Element.is(from) && !DOM.isOrHasChild(source, (Element) Element.as(from)))) {
onTargetOver(be);
}
} else if (type == Events.OnMouseOut) {
EventTarget to = be.getEvent().getRelatedEventTarget();
if (to == null
|| (Element.is(source) && Element.is(to) && !DOM.isOrHasChild(source, (Element) Element.as(to)))) {
onTargetOut(be);
}
} else if (type == Events.OnMouseMove) {
onMouseMove(be);
} else if (type == Events.Hide || type == Events.Detach) {
hide();
} else if (type == Events.OnFocus) {
if (GXT.isFocusManagerEnabled()) {
targetXY = be.getXY();
targetXY.y += target.getOffsetHeight();
targetXY.x += target.getOffsetWidth();
show();
}
} else if (type == Events.OnBlur) {
if (GXT.isFocusManagerEnabled() && !isClosable()) {
hide();
}
} else if (type == Events.OnKeyDown) {
if (GXT.isFocusManagerEnabled() && be.getKeyCode() == KeyCodes.KEY_ESCAPE) {
target.getFocusSupport().setIgnore(true);
hide();
}
}
}
};
}
if (target != null) {
target.addListener(Events.OnMouseOver, listener);
target.addListener(Events.Render, listener);
target.addListener(Events.OnMouseOut, listener);
target.addListener(Events.OnMouseMove, listener);
target.addListener(Events.Hide, listener);
target.addListener(Events.Detach, listener);
if (GXT.isFocusManagerEnabled()) {
this.target.addListener(Events.OnFocus, listener);
this.target.addListener(Events.OnBlur, listener);
this.target.addListener(Events.OnKeyDown, listener);
}
target.sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT | Event.ONMOUSEMOVE);
}
}
/**
* Sets the quick show interval (defaults to 250).
*
* @param quickShowInterval the quick show interval
*/
public void setQuickShowInterval(int quickShowInterval) {
this.quickShowInterval = quickShowInterval;
}
@Override
public void show() {
if (disabled) return;
String origAnchor = null;
boolean origConstrainPosition = false;
if (toolTipConfig.getAnchor() != null) {
origAnchor = toolTipConfig.getAnchor();
// pre-show it off screen so that the el will have dimensions
// for positioning calcs when getting xy next
showAt(-1000, -1000);
origConstrainPosition = this.constrainPosition;
constrainPosition = false;
}
showAt(getTargetXY(0));
if (toolTipConfig.getAnchor() != null) {
anchorEl.show();
syncAnchor();
constrainPosition = origConstrainPosition;
toolTipConfig.setAnchor(origAnchor);
} else {
anchorEl.hide();
}
}
@Override
public void showAt(int x, int y) {
if (disabled) return;
lastActive = new Date();
clearTimers();
super.showAt(x, y);
if (toolTipConfig.getAnchor() != null) {
anchorEl.show();
syncAnchor();
} else {
anchorEl.hide();
}
if (toolTipConfig.getDismissDelay() > 0 && toolTipConfig.isAutoHide() && !toolTipConfig.isCloseable()) {
dismissTimer = new Timer() {
public void run() {
hide();
}
};
dismissTimer.schedule(toolTipConfig.getDismissDelay());
}
}
/**
* Updates the tool tip with the given config.
*
* @param config the tool tip config
*/
public void update(ToolTipConfig config) {
updateConfig(config);
if (isRendered() && isAttached()) {
updateContent();
doAutoWidth();
}
}
protected void afterRender() {
super.afterRender();
anchorEl.setStyleAttribute("zIndex", el().getZIndex() + 1);
}
protected void clearTimer(String timer) {
if (timer.equals("hide")) {
if (hideTimer != null) {
hideTimer.cancel();
hideTimer = null;
}
} else if (timer.equals("dismiss")) {
if (dismissTimer != null) {
dismissTimer.cancel();
dismissTimer = null;
}
} else if (timer.equals("show")) {
if (showTimer != null) {
showTimer.cancel();
showTimer = null;
}
}
}
protected void clearTimers() {
clearTimer("show");
clearTimer("dismiss");
clearTimer("hide");
}
protected void delayHide() {
if (isAttached() && hideTimer == null && toolTipConfig.isAutoHide() && !toolTipConfig.isCloseable()) {
if (toolTipConfig.getHideDelay() == 0) {
hide();
return;
}
hideTimer = new Timer() {
public void run() {
hide();
}
};
hideTimer.schedule(toolTipConfig.getHideDelay());
}
}
protected void delayShow() {
if (!isAttached() && showTimer == null) {
if ((new Date().getTime() - lastActive.getTime()) < quickShowInterval) {
show();
} else {
if (toolTipConfig.getShowDelay() > 0) {
showTimer = new Timer() {
public void run() {
show();
}
};
showTimer.schedule(toolTipConfig.getShowDelay());
} else {
show();
}
}
} else if (isAttached()) {
show();
}
}
protected String getAnchorAlign() {
if (toolTipConfig.getAnchor().equals("top")) {
return "tl-bl";
} else if (toolTipConfig.getAnchor().equals("left")) {
return "tl-tr";
} else if (toolTipConfig.getAnchor().equals("right")) {
return "tr-tl";
}
return "bl-tl";
}
protected int[] getOffsets() {
int[] offsets;
char ap = toolTipConfig.getAnchor().charAt(0);
if (toolTipConfig.isAnchorToTarget() && !toolTipConfig.isTrackMouse()) {
switch (ap) {
case 't':
offsets = new int[] {0, 9};
break;
case 'b':
offsets = new int[] {0, -13};
break;
case 'r':
offsets = new int[] {-13, 0};
break;
default:
offsets = new int[] {9, 0};
break;
}
} else {
int anchorOffset = toolTipConfig.getAnchorOffset();
switch (ap) {
case 't':
offsets = new int[] {-15 - anchorOffset, 30};
break;
case 'b':
offsets = new int[] {-19 - anchorOffset, -13 - el().dom.getOffsetHeight()};
break;
case 'r':
offsets = new int[] {-15 - el().dom.getOffsetWidth(), -13 - anchorOffset};
break;
default:
offsets = new int[] {25, -13 - anchorOffset};
break;
}
}
int[] mouseOffset = toolTipConfig.getMouseOffset();
if (mouseOffset != null) {
offsets[0] += mouseOffset[0];
offsets[1] += mouseOffset[1];
}
return offsets;
}
protected void onMouseMove(ComponentEvent ce) {
targetXY = ce.getXY();
if (isRendered() && isAttached() && toolTipConfig.isTrackMouse()) {
String origAnchor = toolTipConfig.getAnchor();
Point p = getTargetXY(0);
toolTipConfig.setAnchor(origAnchor);
if (constrainPosition) {
p = el().adjustForConstraints(p);
}
setPagePosition(p);
}
}
protected void onRender(Element target, int index) {
super.onRender(target, index);
anchorEl = new El(DOM.createDiv());
anchorEl.addStyleName("x-tip-anchor");
el().appendChild(anchorEl.dom);
el().addStyleName("x-ignore");
}
protected void onTargetOut(ComponentEvent ce) {
if (disabled) {
return;
}
clearTimer("show");
delayHide();
}
protected void onTargetOver(ComponentEvent ce) {
if (disabled || !ce.within(target.getElement())) {
return;
}
clearTimer("hide");
targetXY = ce.getXY();
delayShow();
}
@Override
protected void onWindowResize(int width, int height) {
super.onWindowResize(width, height);
// this can only be reached if the tooltip is already visible, show it again
// to sync anchor
show();
}
protected void syncAnchor() {
String anchorPos, targetPos;
int[] offset;
int anchorOffset = toolTipConfig.getAnchorOffset();
switch (toolTipConfig.getAnchor().charAt(0)) {
case 't':
anchorPos = "b";
targetPos = "tl";
offset = new int[] {20 + anchorOffset, 2};
break;
case 'r':
anchorPos = "l";
targetPos = "tr";
offset = new int[] {-2, 11 + anchorOffset};
break;
case 'b':
anchorPos = "t";
targetPos = "bl";
offset = new int[] {20 + anchorOffset, -2};
break;
default:
anchorPos = "r";
targetPos = "tl";
offset = new int[] {2, 11 + anchorOffset};
break;
}
anchorEl.alignTo(el().dom, anchorPos + "-" + targetPos, offset);
}
@Override
protected void updateContent() {
getHeader().setHtml(titleHtml);
// show header or not
getHeader().el().selectNode("#" + getHeader().getId() + "-label").setVisible(titleHtml != null && !"".equals(titleHtml));
if (toolTipConfig.getTemplate() != null) {
Params p = toolTipConfig.getParams();
if (p == null) p = new Params();
p.set("text", html);
p.set("title", titleHtml);
toolTipConfig.getTemplate().overwrite(getBody().dom, p);
} else {
getBody().update(Util.isEmptyString(html) ? " " : html);
}
}
private Point getTargetXY(int targetCounter) {
if (toolTipConfig.getAnchor() != null) {
targetCounter++;
int[] offsets = getOffsets();
Point xy = (toolTipConfig.isAnchorToTarget() && !toolTipConfig.isTrackMouse()) ? el().getAlignToXY(
target.el().dom, getAnchorAlign(), null) : targetXY;
int dw = XDOM.getViewWidth(false) - 5;
int dh = XDOM.getViewHeight(false) - 5;
int scrollX = XDOM.getBodyScrollLeft() + 5;
int scrollY = XDOM.getBodyScrollTop() + 5;
int[] axy = new int[] {xy.x + offsets[0], xy.y + offsets[1]};
Size sz = getSize();
Region r = target.el().getRegion();
anchorEl.removeStyleName(anchorStyle);
// if we are not inside valid ranges we try to switch the anchor
if (!((toolTipConfig.getAnchor().equals("top") && (sz.height + offsets[1] + scrollY < dh - r.bottom))
|| (toolTipConfig.getAnchor().equals("right") && (sz.width + offsets[0] + scrollX < r.left))
|| (toolTipConfig.getAnchor().equals("bottom") && (sz.height + offsets[1] + scrollY < r.top)) || (toolTipConfig.getAnchor().equals(
"left") && (sz.width + offsets[0] + scrollX < dw - r.right)))
&& targetCounter < 4) {
if (sz.width + offsets[0] + scrollX < dw - r.right) {
toolTipConfig.setAnchor("left");
return getTargetXY(targetCounter);
}
if (sz.width + offsets[0] + scrollX < r.left) {
toolTipConfig.setAnchor("right");
return getTargetXY(targetCounter);
}
if (sz.height + offsets[1] + scrollY < dh - r.bottom) {
toolTipConfig.setAnchor("top");
return getTargetXY(targetCounter);
}
if (sz.height + offsets[1] + scrollY < r.top) {
toolTipConfig.setAnchor("bottom");
return getTargetXY(targetCounter);
}
}
anchorStyle = "x-tip-anchor-" + toolTipConfig.getAnchor();
anchorEl.addStyleName(anchorStyle);
targetCounter = 0;
return new Point(axy[0], axy[1]);
} else {
int x = targetXY.x;
int y = targetXY.y;
int[] mouseOffset = toolTipConfig.getMouseOffset();
if (mouseOffset != null) {
x += mouseOffset[0];
y += mouseOffset[1];
}
return new Point(x, y);
}
}
private void updateConfig(ToolTipConfig config) {
this.toolTipConfig = config;
if (!config.isEnabled()) {
clearTimers();
hide();
}
setMinWidth(config.getMinWidth());
setMaxWidth(config.getMaxWidth());
setClosable(config.isCloseable());
html = config.getHtml();
titleHtml = config.getTitleHtml();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy