001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.gwt.client.util;
029
030import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle;
031
032import com.google.gwt.dom.client.Element;
033import com.google.gwt.dom.client.Style.Unit;
034import com.google.gwt.event.dom.client.HasAllMouseHandlers;
035import com.google.gwt.event.dom.client.MouseMoveEvent;
036import com.google.gwt.event.dom.client.MouseMoveHandler;
037import com.google.gwt.event.dom.client.MouseOutEvent;
038import com.google.gwt.event.dom.client.MouseOutHandler;
039import com.google.gwt.event.dom.client.MouseOverEvent;
040import com.google.gwt.event.dom.client.MouseOverHandler;
041import com.google.gwt.event.shared.HandlerRegistration;
042import com.google.gwt.user.client.DOM;
043import com.google.gwt.user.client.Timer;
044import com.google.gwt.user.client.Window;
045import com.google.gwt.user.client.ui.RootPanel;
046
047/**
048 * A tool-tip handler. Allowing to show any HTML as a tool-tip on mouse over.<p>
049 *
050 * @since 8.0.0
051 */
052public class CmsToolTipHandler implements MouseOverHandler, MouseMoveHandler, MouseOutHandler {
053
054    /** The default tool-tip left offset. */
055    private static final int DEFAULT_OFFSET_LEFT = 10;
056
057    /** The default tool-tip top offset. */
058    private static final int DEFAULT_OFFSET_TOP = 10;
059
060    /** Time to wait before removing the tool tip. */
061    private static final int REMOVE_SCHEDULE = 10000;
062
063    /** The mouse move handler registration. */
064    private HandlerRegistration m_moveHandlerRegistration;
065
066    /** The tool-tip left offset. */
067    private int m_offsetLeft;
068
069    /** The tool-tip top offset. */
070    private int m_offsetTop;
071
072    /** The mouse out handler registration. */
073    private HandlerRegistration m_outHandlerRegistration;
074
075    /** The mouse over handler registration. */
076    private HandlerRegistration m_overHandlerRegistration;
077
078    /** Timer to remove the tool tip again. */
079    private Timer m_removeTimer;
080
081    /** Flag indicating if the tool-tip is currently showing. */
082    private boolean m_showing;
083
084    /** The widget to show the tool-tip for. */
085    private HasAllMouseHandlers m_target;
086
087    /** The tool-tip element. */
088    private Element m_toolTip;
089
090    /** The tool-tip HTML to show. */
091    private String m_toolTipHtml;
092
093    /**
094     * Constructor. Adds the tool-tip handler to the target.<p>
095     *
096     * @param target the target to show the tool-tip on
097     * @param toolTipHtml the tool-tip content
098     */
099    public CmsToolTipHandler(HasAllMouseHandlers target, String toolTipHtml) {
100
101        m_target = target;
102        m_toolTipHtml = toolTipHtml;
103        m_offsetLeft = DEFAULT_OFFSET_LEFT;
104        m_offsetTop = DEFAULT_OFFSET_TOP;
105        m_overHandlerRegistration = m_target.addMouseOverHandler(this);
106    }
107
108    /**
109     * Removes the tool-tip and mouse move and out handlers.<p>
110     */
111    public void clearShowing() {
112
113        m_showing = false;
114        if (m_toolTip != null) {
115            m_toolTip.removeFromParent();
116            m_toolTip = null;
117        }
118        if (m_moveHandlerRegistration != null) {
119            m_moveHandlerRegistration.removeHandler();
120            m_moveHandlerRegistration = null;
121        }
122        if (m_outHandlerRegistration != null) {
123            m_outHandlerRegistration.removeHandler();
124            m_outHandlerRegistration = null;
125        }
126        m_removeTimer = null;
127    }
128
129    /**
130     * Returns the tool-tip HTML.<p>
131     *
132     * @return the tool-tip HTML
133     */
134    public String getToolTipHtml() {
135
136        return m_toolTipHtml;
137    }
138
139    /**
140     * Returns if the tool-tip is showing.<p>
141     *
142     * @return <code>true</code> if the tool-tip is showing
143     */
144    public boolean isShowing() {
145
146        return m_showing;
147    }
148
149    /**
150     * @see com.google.gwt.event.dom.client.MouseMoveHandler#onMouseMove(com.google.gwt.event.dom.client.MouseMoveEvent)
151     */
152    public void onMouseMove(MouseMoveEvent event) {
153
154        m_removeTimer.schedule(REMOVE_SCHEDULE);
155        setToolTipPosition(event.getClientX(), event.getClientY());
156    }
157
158    /**
159     * @see com.google.gwt.event.dom.client.MouseOutHandler#onMouseOut(com.google.gwt.event.dom.client.MouseOutEvent)
160     */
161    public void onMouseOut(MouseOutEvent event) {
162
163        if (m_removeTimer != null) {
164            m_removeTimer.cancel();
165        }
166        clearShowing();
167    }
168
169    /**
170     * @see com.google.gwt.event.dom.client.MouseOverHandler#onMouseOver(com.google.gwt.event.dom.client.MouseOverEvent)
171     */
172    public void onMouseOver(MouseOverEvent event) {
173
174        // make sure not to double assign any handlers
175        if (m_removeTimer != null) {
176            m_removeTimer.cancel();
177        }
178        clearShowing();
179
180        createTimer();
181        m_removeTimer.schedule(REMOVE_SCHEDULE);
182
183        m_showing = true;
184        m_moveHandlerRegistration = m_target.addMouseMoveHandler(this);
185        m_outHandlerRegistration = m_target.addMouseOutHandler(this);
186        if (m_toolTip == null) {
187            m_toolTip = DOM.createDiv();
188            m_toolTip.addClassName(I_CmsLayoutBundle.INSTANCE.generalCss().toolTip());
189            m_toolTip.addClassName(I_CmsLayoutBundle.INSTANCE.generalCss().cornerAll());
190        }
191        m_toolTip.setInnerHTML(m_toolTipHtml);
192        RootPanel.getBodyElement().appendChild(m_toolTip);
193        setToolTipPosition(event.getClientX(), event.getClientY());
194    }
195
196    /**
197     * Removes this tool-tip handler completely. This instance will not be reusable.<p>
198     */
199    public void removeHandler() {
200
201        clearShowing();
202        if (m_overHandlerRegistration != null) {
203            m_overHandlerRegistration.removeHandler();
204            m_overHandlerRegistration = null;
205        }
206        m_target = null;
207    }
208
209    /**
210     * Sets the tool-tip left offset.<p>
211     *
212     * @param offsetLeft the tool-tip left offset to set
213     */
214    public void setOffsetLeft(int offsetLeft) {
215
216        m_offsetLeft = offsetLeft;
217    }
218
219    /**
220     * Sets the tool-tip top offset.<p>
221     *
222     * @param offsetTop the tool-tip top offset to set
223     */
224    public void setOffsetTop(int offsetTop) {
225
226        m_offsetTop = offsetTop;
227    }
228
229    /**
230     * Sets the tool-tip HTML.<p>
231     *
232     * @param toolTipHtml the tool-tip HTML to set
233     */
234    public void setToolTipHtml(String toolTipHtml) {
235
236        m_toolTipHtml = toolTipHtml;
237        if (m_showing) {
238            m_toolTip.setInnerHTML(toolTipHtml);
239        }
240    }
241
242    /**
243     * Creates the remove tool tip timer.<p>
244     */
245    private void createTimer() {
246
247        m_removeTimer = new Timer() {
248
249            /**
250             * @see com.google.gwt.user.client.Timer#run()
251             */
252            @Override
253            public void run() {
254
255                clearShowing();
256            }
257        };
258    }
259
260    /**
261     * Sets the tool-tip position.<p>
262     *
263     * @param clientLeft the mouse pointer left position relative to the client window
264     * @param clientTop the mouse pointer top  position relative to the client window
265     */
266    private void setToolTipPosition(int clientLeft, int clientTop) {
267
268        if (m_toolTip != null) {
269            int height = m_toolTip.getOffsetHeight();
270            int width = m_toolTip.getOffsetWidth();
271            int windowHeight = Window.getClientHeight();
272            int windowWidth = Window.getClientWidth();
273            int scrollLeft = Window.getScrollLeft();
274            int scrollTop = Window.getScrollTop();
275            int left = clientLeft + scrollLeft + m_offsetLeft;
276            if ((left + width) > (windowWidth + scrollLeft)) {
277                left = (windowWidth + scrollLeft) - m_offsetLeft - width;
278            }
279            m_toolTip.getStyle().setLeft(left, Unit.PX);
280            int top = clientTop + scrollTop + m_offsetTop;
281            if (((top + height) > (windowHeight + scrollTop)) && ((height + m_offsetTop) < clientTop)) {
282                top = (clientTop + scrollTop) - m_offsetTop - height;
283            }
284            m_toolTip.getStyle().setTop(top, Unit.PX);
285        }
286    }
287}