93839 - tooltiptext should work without specifying tooltip, r=pinkerton, sr=hyatt

This commit is contained in:
hewitt%netscape.com 2001-12-04 23:45:22 +00:00
Родитель 8311eb999f
Коммит 7d640e36ad
2 изменённых файлов: 828 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,681 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsXULTooltipListener.h"
#include "nsIDOMMouseEvent.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMXULDocument.h"
#include "nsIDOMXULElement.h"
#include "nsIDocument.h"
#include "nsXULAtoms.h"
#include "nsIPresShell.h"
#include "nsIFrame.h"
#include "nsIPopupBoxObject.h"
#include "nsIPref.h"
#include "nsIServiceManager.h"
#include "nsIOutlinerView.h"
#include "nsGUIEvent.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIPresContext.h"
//////////////////////////////////////////////////////////////////////////
//// nsISupports
nsXULTooltipListener::nsXULTooltipListener()
: mSourceNode(nsnull), mTargetNode(nsnull),
mCurrentTooltip(nsnull),
mMouseClientX(0), mMouseClientY(0),
mIsTargetOutliner(PR_FALSE), mNeedTitletip(PR_FALSE),
mOutlinerBox(nsnull), mLastOutlinerRow(-1)
{
NS_INIT_REFCNT();
}
nsXULTooltipListener::~nsXULTooltipListener()
{
HideTooltip();
// unregister the prefs callback
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (prefs) {
// register the callback so we get notified of updates
prefs->UnregisterCallback("browser.chrome.toolbar_tips", (PrefChangedFunc)sTooltipPrefChanged, (void*)this);
}
}
NS_IMPL_ADDREF(nsXULTooltipListener)
NS_IMPL_RELEASE(nsXULTooltipListener)
NS_INTERFACE_MAP_BEGIN(nsXULTooltipListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseMotionListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMXULListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMouseMotionListener)
NS_INTERFACE_MAP_END
//////////////////////////////////////////////////////////////////////////
//// nsIDOMMouseListener
NS_IMETHODIMP
nsXULTooltipListener::MouseDown(nsIDOMEvent* aMouseEvent)
{
HideTooltip();
return NS_OK;
}
NS_IMETHODIMP
nsXULTooltipListener::MouseOut(nsIDOMEvent* aMouseEvent)
{
// if the timer is running and no tooltip is shown, we
// have to cancel the timer here so that it doesn't
// show the tooltip if we move the mouse out of the window
if (mTooltipTimer && !mCurrentTooltip) {
mTooltipTimer->Cancel();
mTooltipTimer = nsnull;
return NS_OK;
}
if (mNeedTitletip)
return NS_OK;
// check to see if the mouse left the targetNode, and if so,
// hide the tooltip
if (mCurrentTooltip) {
// which node did the mouse leave?
nsCOMPtr<nsIDOMEventTarget> eventTarget;
aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
nsCOMPtr<nsIDOMNode> targetNode(do_QueryInterface(eventTarget));
// which node is our tooltip on?
nsCOMPtr<nsIDocument> doc;
mCurrentTooltip->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIDOMXULDocument> xulDoc(do_QueryInterface(doc));
if (!doc) // remotely possible someone could have
return NS_OK; // removed tooltip from dom while it was open
nsCOMPtr<nsIDOMNode> tooltipNode;
xulDoc->GetTooltipNode (getter_AddRefs(tooltipNode));
// if they're the same, the mouse left the node the tooltip appeared on,
// close the tooltip.
if (tooltipNode == targetNode) {
HideTooltip();
// reset special outliner tracking
if (mIsTargetOutliner) {
mOutlinerBox = nsnull;
mLastOutlinerRow = -1;
mLastOutlinerCol.Truncate();
}
}
}
return NS_OK;
}
//////////////////////////////////////////////////////////////////////////
//// nsIDOMMouseMotionListener
NS_IMETHODIMP
nsXULTooltipListener::MouseMove(nsIDOMEvent* aMouseEvent)
{
if (!sShowTooltips)
return NS_OK;
// stash the coordinates of the event so that we can still get back to it from within the
// timer callback. On win32, we'll get a MouseMove event even when a popup goes away --
// even when the mouse doesn't change position! To get around this, we make sure the
// mouse has really moved before proceeding.
nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(aMouseEvent));
PRInt32 newMouseX, newMouseY;
mouseEvent->GetClientX(&newMouseX);
mouseEvent->GetClientY(&newMouseY);
if (mMouseClientX == newMouseX && mMouseClientY == newMouseY)
return NS_OK;
mMouseClientX = newMouseX;
mMouseClientY = newMouseY;
if (mIsTargetOutliner)
CheckOutlinerBodyMove(mouseEvent);
// as the mouse moves, we want to make sure we reset the timer to show it,
// so that the delay is from when the mouse stops moving, not when it enters
// the node.
KillTooltipTimer();
// If the mouse moves while the tooltip is up, don't do anything. We make it
// go away only if it times out or leaves the target node. If nothing is
// showing, though, we have to do the work.
if (!mCurrentTooltip) {
mTooltipTimer = do_CreateInstance("@mozilla.org/timer;1");
if (mTooltipTimer) {
nsCOMPtr<nsIDOMEventTarget> eventTarget;
aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
if (eventTarget) {
nsCOMPtr<nsIContent> targetContent(do_QueryInterface(eventTarget));
mTargetNode = targetContent;
}
if (mTargetNode) {
nsresult rv = mTooltipTimer->Init(sTooltipCallback, this, kTooltipShowTime, NS_PRIORITY_HIGH);
if (NS_FAILED(rv))
mTargetNode = nsnull;
}
}
}
return NS_OK;
}
//////////////////////////////////////////////////////////////////////////
//// nsIDOMKeyListener
NS_IMETHODIMP
nsXULTooltipListener::KeyDown(nsIDOMEvent* aKeyEvent)
{
HideTooltip();
return NS_OK;
}
//////////////////////////////////////////////////////////////////////////
//// nsIDOMEventListener
NS_IMETHODIMP
nsXULTooltipListener::HandleEvent(nsIDOMEvent* aEvent)
{
nsAutoString type;
aEvent->GetType(type);
if (type.Equals(NS_LITERAL_STRING("DOMMouseScroll")))
HideTooltip();
return NS_OK;
}
//////////////////////////////////////////////////////////////////////////
//// nsXULTooltipListener
NS_IMETHODIMP
nsXULTooltipListener::PopupHiding(nsIDOMEvent* aEvent)
{
DestroyTooltip();
return NS_OK;
}
//////////////////////////////////////////////////////////////////////////
//// nsXULTooltipListener
PRBool nsXULTooltipListener::sShowTooltips = PR_FALSE;
nsresult
nsXULTooltipListener::Init(nsIContent* aSourceNode, nsIRootBox* aRootBox)
{
mRootBox = aRootBox;
mSourceNode = aSourceNode;
AddTooltipSupport(aSourceNode);
// if the target is an outlinerbody, we may have some special
// case handling to do
nsCOMPtr<nsIAtom> tag;
mSourceNode->GetTag(*getter_AddRefs(tag));
mIsTargetOutliner = tag == nsXULAtoms::outlinerbody;
static PRBool prefChangeRegistered = PR_FALSE;
// Only the first time, register the callback and get the initial value of the pref
if (!prefChangeRegistered) {
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (prefs) {
// get the initial value of the pref
nsresult rv = prefs->GetBoolPref("browser.chrome.toolbar_tips", &sShowTooltips);
if (NS_SUCCEEDED(rv)) {
// register the callback so we get notified of updates
rv = prefs->RegisterCallback("browser.chrome.toolbar_tips", (PrefChangedFunc)sTooltipPrefChanged, nsnull);
if (NS_SUCCEEDED(rv))
prefChangeRegistered = PR_TRUE;
}
}
}
return NS_OK;
}
nsresult
nsXULTooltipListener::AddTooltipSupport(nsIContent* aNode)
{
if (!aNode)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aNode));
evtTarget->AddEventListener(NS_LITERAL_STRING("mouseout"), (nsIDOMMouseListener*)this, PR_FALSE);
evtTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), (nsIDOMMouseListener*)this, PR_FALSE);
return NS_OK;
}
nsresult
nsXULTooltipListener::RemoveTooltipSupport(nsIContent* aNode)
{
if (!aNode)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aNode));
evtTarget->RemoveEventListener(NS_LITERAL_STRING("mouseout"), (nsIDOMMouseListener*)this, PR_FALSE);
evtTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), (nsIDOMMouseListener*)this, PR_FALSE);
return NS_OK;
}
void
nsXULTooltipListener::CheckOutlinerBodyMove(nsIDOMMouseEvent* aMouseEvent)
{
if (!mOutlinerBox) {
// This will be called from MouseMove before the tooltip timer is
// killed so that mTargetNode isn't yet set to null
if (mTargetNode) {
nsCOMPtr<nsIDocument> doc;
mSourceNode->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIPresShell> shell;
doc->GetShellAt(0, getter_AddRefs(shell));
if (shell) {
nsIFrame* bodyFrame = nsnull;
shell->GetPrimaryFrameFor(mTargetNode, &bodyFrame);
if (bodyFrame) {
nsCOMPtr<nsIOutlinerBoxObject> bx(do_QueryInterface(bodyFrame));
mOutlinerBox = bx;
}
}
}
}
if (mOutlinerBox) {
PRInt32 x, y;
aMouseEvent->GetClientX(&x);
aMouseEvent->GetClientY(&y);
PRInt32 row;
nsXPIDLString colId, obj;
mOutlinerBox->GetCellAt(x, y, &row, getter_Copies(colId), getter_Copies(obj));
// determine if we are going to need a titletip
// XXX check the disabletitletips attribute on the outliner content
mNeedTitletip = PR_FALSE;
if (obj.Equals(NS_LITERAL_STRING("text"))) {
nsCOMPtr<nsIOutlinerView> view;
mOutlinerBox->GetView(getter_AddRefs(view));
PRInt32 rowCount;
view->GetRowCount(&rowCount);
if (row < rowCount) {
PRBool isCropped;
mOutlinerBox->IsCellCropped(row, colId, &isCropped);
mNeedTitletip = isCropped;
}
}
if (row != mLastOutlinerRow || !mLastOutlinerCol.Equals(colId)) {
HideTooltip();
}
mLastOutlinerRow = row;
mLastOutlinerCol.Assign(colId);
}
}
nsresult
nsXULTooltipListener::ShowTooltip()
{
// get the tooltip content designated for the target node
GetTooltipFor(mSourceNode, &mCurrentTooltip);
if (!mCurrentTooltip)
return NS_ERROR_FAILURE; // the target node doesn't need a tooltip
// set the node in the document that triggered the tooltip and show it
nsCOMPtr<nsIDocument> doc;
mCurrentTooltip->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIDOMXULDocument> xulDoc(do_QueryInterface(doc));
if (xulDoc) {
// Make sure the target node is still attached to some document.
// It might have been deleted.
nsCOMPtr<nsIDocument> targetDoc;
mSourceNode->GetDocument(*getter_AddRefs(targetDoc));
if (targetDoc) {
if (!mIsTargetOutliner) {
mLastOutlinerRow = -1;
mLastOutlinerCol.Truncate();
}
nsCOMPtr<nsIDOMNode> targetNode(do_QueryInterface(mTargetNode));
xulDoc->SetTooltipNode(targetNode);
xulDoc->SetPopupNode(targetNode);
LaunchTooltip(mSourceNode, mMouseClientX, mMouseClientY);
// at this point, |mCurrentTooltip| holds the content node of
// the tooltip. If there is an attribute on the popup telling us
// not to create the auto-hide timer, don't.
nsCOMPtr<nsIDOMElement> tooltipEl(do_QueryInterface(mCurrentTooltip));
nsAutoString noAutoHide;
tooltipEl->GetAttribute(NS_LITERAL_STRING("noautohide"), noAutoHide);
if (noAutoHide != NS_LITERAL_STRING("true"))
CreateAutoHideTimer();
// listen for popuphidden on the tooltip node, so that we can
// be sure DestroyPopup is called even if someone else closes the tooltip
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(mCurrentTooltip));
evtTarget->AddEventListener(NS_LITERAL_STRING("popuphiding"),
(nsIDOMMouseListener*)this, PR_FALSE);
// listen for mousedown,keydown, and DOMMouseScroll events at document level
nsCOMPtr<nsIDocument> doc;
mSourceNode->GetDocument(*getter_AddRefs(doc));
if (doc) {
evtTarget = do_QueryInterface(doc);
evtTarget->AddEventListener(NS_LITERAL_STRING("DOMMouseScroll"),
(nsIDOMMouseListener*)this, PR_TRUE);
evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"),
(nsIDOMMouseListener*)this, PR_TRUE);
evtTarget->AddEventListener(NS_LITERAL_STRING("keydown"),
(nsIDOMMouseListener*)this, PR_TRUE);
}
}
}
return NS_OK;
}
static void
GetOutlinerCellCoords(nsIOutlinerBoxObject* aOutlinerBox, nsIContent* aSourceNode,
PRInt32 aRow, nsAutoString aCol, PRInt32* aX, PRInt32* aY)
{
PRInt32 junk;
const PRUnichar empty[] = {'\0'};
aOutlinerBox->GetCoordsForCellItem(aRow, aCol.get(), empty, aX, aY, &junk, &junk);
nsCOMPtr<nsIDOMXULElement> xulEl(do_QueryInterface(aSourceNode));
nsCOMPtr<nsIBoxObject> bx;
xulEl->GetBoxObject(getter_AddRefs(bx));
PRInt32 myX, myY;
bx->GetX(&myX);
bx->GetY(&myY);
*aX += myX;
*aY += myY;
}
static void
SetTitletipLabel(nsIOutlinerBoxObject* aOutlinerBox, nsIContent* aTooltip,
PRInt32 aRow, nsAutoString aCol)
{
nsCOMPtr<nsIOutlinerView> view;
aOutlinerBox->GetView(getter_AddRefs(view));
PRUnichar* cellText = nsnull;
view->GetCellText(aRow, aCol.get(), &cellText);
nsAutoString label;
label.Assign(cellText);
aTooltip->SetAttr(nsnull, nsXULAtoms::label, label, PR_FALSE);
}
nsresult
nsXULTooltipListener::LaunchTooltip(nsIContent* aTarget, PRInt32 aX, PRInt32 aY)
{
nsresult rv = NS_OK;
if (!mCurrentTooltip)
return NS_OK;
nsCOMPtr<nsIBoxObject> popupBox;
nsCOMPtr<nsIDOMXULElement> xulTooltipEl(do_QueryInterface(mCurrentTooltip));
if (!xulTooltipEl) {
NS_ERROR("tooltip isn't a XUL element!");
return NS_ERROR_FAILURE;
}
xulTooltipEl->GetBoxObject(getter_AddRefs(popupBox));
nsCOMPtr<nsIPopupBoxObject> popupBoxObject(do_QueryInterface(popupBox));
if (popupBoxObject) {
PRInt32 x = aX;
PRInt32 y = aY;
if (mNeedTitletip) {
GetOutlinerCellCoords(mOutlinerBox, mSourceNode,
mLastOutlinerRow, mLastOutlinerCol, &x, &y);
SetTitletipLabel(mOutlinerBox, mCurrentTooltip, mLastOutlinerRow, mLastOutlinerCol);
mCurrentTooltip->SetAttr(nsnull, nsXULAtoms::titletip, NS_LITERAL_STRING("true"), PR_FALSE);
} else
mCurrentTooltip->UnsetAttr(nsnull, nsXULAtoms::titletip, PR_FALSE);
nsCOMPtr<nsIDOMElement> targetEl(do_QueryInterface(aTarget));
popupBoxObject->ShowPopup(targetEl, xulTooltipEl, x, y,
NS_LITERAL_STRING("tooltip").get(),
NS_LITERAL_STRING("none").get(),
NS_LITERAL_STRING("topleft").get());
}
return NS_OK;
}
nsresult
nsXULTooltipListener::HideTooltip()
{
if (mCurrentTooltip) {
// hide the popup through its box object
nsCOMPtr<nsIDOMXULElement> tooltipEl(do_QueryInterface(mCurrentTooltip));
nsCOMPtr<nsIBoxObject> boxObject;
if (tooltipEl)
tooltipEl->GetBoxObject(getter_AddRefs(boxObject));
nsCOMPtr<nsIPopupBoxObject> popupObject(do_QueryInterface(boxObject));
if (popupObject)
popupObject->HidePopup();
}
DestroyTooltip();
return NS_OK;
}
static void
GetImmediateChild(nsIContent* aContent, nsIAtom *aTag, nsIContent** aResult)
{
*aResult = nsnull;
PRInt32 childCount;
aContent->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> child;
aContent->ChildAt(i, *getter_AddRefs(child));
nsCOMPtr<nsIAtom> tag;
child->GetTag(*getter_AddRefs(tag));
if (aTag == tag.get()) {
*aResult = child;
NS_ADDREF(*aResult);
return;
}
}
return;
}
nsresult
nsXULTooltipListener::GetTooltipFor(nsIContent* aTarget, nsIContent** aTooltip)
{
if (!aTarget)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMElement> targetEl(do_QueryInterface(aTarget));
if (!targetEl)
return NS_ERROR_FAILURE; // could be a text node or something
PRBool needTooltip;
targetEl->HasAttribute(NS_LITERAL_STRING("tooltiptext"), &needTooltip);
if (needTooltip) {
// specifying tooltiptext means we will always use the default tooltip
mRootBox->GetDefaultTooltip(aTooltip);
return NS_OK;
} else {
nsAutoString tooltipId;
targetEl->GetAttribute(NS_LITERAL_STRING("tooltip"), tooltipId);
// if tooltip == _child, look for first <tooltip> child
if (tooltipId.Equals(NS_LITERAL_STRING("_child"))) {
GetImmediateChild(aTarget, nsXULAtoms::tooltip, aTooltip); // this addrefs
} else {
if (!tooltipId.IsEmpty()) {
// tooltip must be an id, use getElementById to find it
nsresult rv;
nsCOMPtr<nsIDocument> document;
if (NS_FAILED(rv = aTarget->GetDocument(*getter_AddRefs(document)))) {
NS_ERROR("Unable to retrieve the tooltip node document.");
return rv;
}
nsCOMPtr<nsIDOMXULDocument> xulDocument = do_QueryInterface(document);
if (!xulDocument) {
NS_ERROR("tooltip attached to an element that isn't in XUL!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMElement> tooltipEl;
xulDocument->GetElementById(tooltipId, getter_AddRefs(tooltipEl));
if (tooltipEl) {
mNeedTitletip = PR_FALSE;
nsCOMPtr<nsIContent> tooltipContent(do_QueryInterface(tooltipEl));
*aTooltip = tooltipContent;
return NS_OK;
}
}
}
}
// titletips should just use the default tooltip
if (mIsTargetOutliner && mNeedTitletip) {
mRootBox->GetDefaultTooltip(aTooltip);
return NS_OK;
}
return NS_OK;
}
nsresult
nsXULTooltipListener::DestroyTooltip()
{
if (mCurrentTooltip) {
// clear out the tooltip node on the document
nsCOMPtr<nsIDocument> doc;
mCurrentTooltip->GetDocument(*getter_AddRefs(doc));
if (doc) {
nsCOMPtr<nsIDOMXULDocument> xulDoc(do_QueryInterface(doc));
if (xulDoc)
xulDoc->SetTooltipNode(nsnull);
// remove the mousedown and keydown listener from document
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(doc));
evtTarget->RemoveEventListener(NS_LITERAL_STRING("DOMMouseScroll"), (nsIDOMMouseListener*)this, PR_TRUE);
evtTarget->RemoveEventListener(NS_LITERAL_STRING("mousedown"), (nsIDOMMouseListener*)this, PR_TRUE);
evtTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"), (nsIDOMMouseListener*)this, PR_TRUE);
}
// remove the popuphidden listener from tooltip
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(mCurrentTooltip));
evtTarget->RemoveEventListener(NS_LITERAL_STRING("popuphiding"), (nsIDOMMouseListener*)this, PR_FALSE);
// kill any ongoing timers
KillTooltipTimer();
if (mAutoHideTimer) {
mAutoHideTimer->Cancel();
mAutoHideTimer = nsnull;
}
mCurrentTooltip = nsnull;
}
return NS_OK;
}
void
nsXULTooltipListener::KillTooltipTimer()
{
if (mTooltipTimer) {
mTooltipTimer->Cancel();
mTooltipTimer = nsnull;
mTargetNode = nsnull;
}
}
void
nsXULTooltipListener::CreateAutoHideTimer()
{
if (mAutoHideTimer) {
mAutoHideTimer->Cancel();
mAutoHideTimer = nsnull;
}
mAutoHideTimer = do_CreateInstance("@mozilla.org/timer;1");
if ( mAutoHideTimer )
mAutoHideTimer->Init(sAutoHideCallback, this, kTooltipAutoHideTime, NS_PRIORITY_HIGH);
}
void
nsXULTooltipListener::sTooltipCallback(nsITimer *aTimer, void *aListener)
{
nsXULTooltipListener* self = NS_STATIC_CAST(nsXULTooltipListener*, aListener);
if (self)
self->ShowTooltip();
}
void
nsXULTooltipListener::sAutoHideCallback(nsITimer *aTimer, void* aListener)
{
nsXULTooltipListener* self = NS_STATIC_CAST(nsXULTooltipListener*, aListener);
if (self)
self->HideTooltip();
}
int
nsXULTooltipListener::sTooltipPrefChanged(const char* aPref, void* aData)
{
nsXULTooltipListener* self = NS_STATIC_CAST(nsXULTooltipListener*, aData);
if (self) {
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (prefs)
prefs->GetBoolPref("browser.chrome.toolbar_tips", &sShowTooltips);
}
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,147 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsXULTooltipListener_h__
#define nsXULTooltipListener_h__
#include "nsIDOMMouseListener.h"
#include "nsIDOMMouseMotionListener.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMMouseEvent.h"
#include "nsIDOMXULListener.h"
#include "nsIContent.h"
#include "nsIDOMElement.h"
#include "nsITimer.h"
#include "nsIRootBox.h"
#include "nsIOutlinerBoxObject.h"
#include "nsString.h"
class nsXULTooltipListener : public nsIDOMMouseListener,
public nsIDOMMouseMotionListener,
public nsIDOMKeyListener,
public nsIDOMXULListener
{
public:
nsXULTooltipListener();
virtual ~nsXULTooltipListener();
// nsISupports
NS_DECL_ISUPPORTS
// nsIDOMMouseListener
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent) { return NS_OK; };
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent) { return NS_OK; };
NS_IMETHOD MouseDblClick(nsIDOMEvent* aMouseEvent) { return NS_OK; };
NS_IMETHOD MouseOver(nsIDOMEvent* aMouseEvent) { return NS_OK; };
NS_IMETHOD MouseOut(nsIDOMEvent* aMouseEvent);
// nsIDOMMouseMotionListener
NS_IMETHOD DragMove(nsIDOMEvent* aMouseEvent) { return NS_OK; };
NS_IMETHOD MouseMove(nsIDOMEvent* aMouseEvent);
// nsIDOMKeyListener
NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent) { return NS_OK; };
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent) { return NS_OK; };
// nsIDOMXULListener
NS_IMETHOD PopupShowing(nsIDOMEvent* aEvent) { return NS_OK; };
NS_IMETHOD PopupShown(nsIDOMEvent* aEvent) { return NS_OK; };
NS_IMETHOD PopupHiding(nsIDOMEvent* aEvent);
NS_IMETHOD PopupHidden(nsIDOMEvent* aEvent) { return NS_OK; };
NS_IMETHOD Close(nsIDOMEvent* aEvent) { return NS_OK; };
NS_IMETHOD Command(nsIDOMEvent* aEvent) { return NS_OK; };
NS_IMETHOD Broadcast(nsIDOMEvent* aEvent) { return NS_OK; };
NS_IMETHOD CommandUpdate(nsIDOMEvent* aEvent) { return NS_OK; };
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
nsresult Init(nsIContent* aSourceNode, nsIRootBox* aRootBox);
nsresult SetDefaultTooltip(nsIContent* aDefaultTooltip);
nsresult GetDefaultTooltip(nsIContent** aDefaultTooltip);
nsresult AddTooltipSupport(nsIContent* aNode);
nsresult RemoveTooltipSupport(nsIContent* aNode);
protected:
// pref callback for when the "show tooltips" pref changes
static int sTooltipPrefChanged (const char* aPref, void* aData);
static PRBool sShowTooltips;
void KillTooltipTimer();
void CreateAutoHideTimer();
void CheckOutlinerBodyMove(nsIDOMMouseEvent* aMouseEvent);
nsresult ShowTooltip();
nsresult LaunchTooltip(nsIContent* aTarget, PRInt32 aX, PRInt32 aY);
nsresult HideTooltip();
nsresult DestroyTooltip();
nsresult GetTooltipFor(nsIContent* aTarget, nsIContent** aTooltip);
nsIRootBox* mRootBox;
nsIContent* mSourceNode;
nsIContent* mTargetNode;
nsIContent* mCurrentTooltip;
// a timer for showing the tooltip
nsCOMPtr<nsITimer> mTooltipTimer;
static void sTooltipCallback (nsITimer* aTimer, void* aListener);
PRInt32 mMouseClientX, mMouseClientY;
// a timer for auto-hiding the tooltip after a certain delay
nsCOMPtr<nsITimer> mAutoHideTimer;
static void sAutoHideCallback (nsITimer* aTimer, void* aListener);
// various delays for tooltips
enum {
kTooltipAutoHideTime = 5000, // 5000ms = 5 seconds
kTooltipShowTime = 500 // 500ms = 0.5 seconds
};
// special members for handling outliners
PRBool mIsTargetOutliner;
PRBool mNeedTitletip;
PRInt32 mLastOutlinerRow;
nsIOutlinerBoxObject* mOutlinerBox;
nsAutoString mLastOutlinerCol;
};
#endif // nsXULTooltipListener