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

This commit is contained in:
hewitt%netscape.com 2001-12-04 22:32:49 +00:00
Родитель a5c0fa9511
Коммит 58fe14b67f
20 изменённых файлов: 415 добавлений и 452 удалений

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

@ -646,7 +646,9 @@ NS_METHOD nsDOMEvent::GetScreenY(PRInt32* aScreenY)
NS_METHOD nsDOMEvent::GetClientX(PRInt32* aClientX)
{
if (!mEvent ||
(mEvent->eventStructType != NS_MOUSE_EVENT && mEvent->eventStructType != NS_DRAGDROP_EVENT) ||
(mEvent->eventStructType != NS_MOUSE_EVENT
&& mEvent->eventStructType != NS_EVENT
&& mEvent->eventStructType != NS_DRAGDROP_EVENT) ||
!mPresContext) {
*aClientX = 0;
return NS_OK;
@ -697,7 +699,9 @@ NS_METHOD nsDOMEvent::GetClientX(PRInt32* aClientX)
NS_METHOD nsDOMEvent::GetClientY(PRInt32* aClientY)
{
if (!mEvent ||
(mEvent->eventStructType != NS_MOUSE_EVENT && mEvent->eventStructType != NS_DRAGDROP_EVENT) ||
(mEvent->eventStructType != NS_MOUSE_EVENT
&& mEvent->eventStructType != NS_EVENT
&& mEvent->eventStructType != NS_DRAGDROP_EVENT) ||
!mPresContext) {
*aClientY = 0;
return NS_OK;

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

@ -237,6 +237,8 @@ XUL_ATOM(textbox, "textbox")
XUL_ATOM(textarea, "textarea")
XUL_ATOM(listbox, "listbox")
XUL_ATOM(tooltip, "tooltip")
XUL_ATOM(titletip, "titletip")
XUL_ATOM(tooltiptext, "tooltiptext")
XUL_ATOM(context, "context")
XUL_ATOM(contextmenu, "contextmenu")
XUL_ATOM(style, "style")
@ -302,3 +304,4 @@ XUL_ATOM(sortDirection, "sortDirection")
XUL_ATOM(sortActive, "sortActive")
XUL_ATOM(selectedIndex, "selectedIndex")
XUL_ATOM(_star, "*")
XUL_ATOM(defaultz, "default")

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

@ -2060,8 +2060,7 @@ nsXULElement::AddListenerFor(nsINodeInfo *aNodeInfo,
nsCOMPtr<nsIAtom> attr;
aNodeInfo->GetNameAtom(*getter_AddRefs(attr));
if (attr == nsXULAtoms::tooltip ||
attr == nsXULAtoms::menu ||
if (attr == nsXULAtoms::menu ||
attr == nsXULAtoms::contextmenu ||
// XXXdwh popup and context are deprecated
attr == nsXULAtoms::popup ||
@ -4576,10 +4575,7 @@ nsXULElement::AddPopupListener(nsIAtom* aName)
if (NS_FAILED(rv)) return rv;
XULPopupType popupType;
if (aName == nsXULAtoms::tooltip) {
popupType = eXULPopupType_tooltip;
}
else if (aName == nsXULAtoms::context || aName == nsXULAtoms::contextmenu) {
if (aName == nsXULAtoms::context || aName == nsXULAtoms::contextmenu) {
popupType = eXULPopupType_context;
}
else {
@ -4592,15 +4588,8 @@ nsXULElement::AddPopupListener(nsIAtom* aName)
// Add the popup as a listener on this element.
nsCOMPtr<nsIDOMEventListener> eventListener = do_QueryInterface(popupListener);
if (popupType == eXULPopupType_tooltip) {
AddEventListener(NS_LITERAL_STRING("mouseout"), eventListener, PR_FALSE);
AddEventListener(NS_LITERAL_STRING("mousemove"), eventListener, PR_FALSE);
AddEventListener(NS_LITERAL_STRING("keydown"), eventListener, PR_FALSE);
}
else {
AddEventListener(NS_LITERAL_STRING("mousedown"), eventListener, PR_FALSE);
AddEventListener(NS_LITERAL_STRING("contextmenu"), eventListener, PR_FALSE);
}
AddEventListener(NS_LITERAL_STRING("mousedown"), eventListener, PR_FALSE);
AddEventListener(NS_LITERAL_STRING("contextmenu"), eventListener, PR_FALSE);
return NS_OK;
}

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

@ -42,11 +42,10 @@
/*
This file provides the implementation for xul popup listener which
tracks xul popups, context menus, and tooltips
tracks xul popups and context menus
*/
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsXULAtoms.h"
#include "nsIDOMElement.h"
#include "nsIDOMXULElement.h"
@ -54,9 +53,7 @@
#include "nsIDOMDocumentXBL.h"
#include "nsIXULPopupListener.h"
#include "nsIDOMMouseListener.h"
#include "nsIDOMMouseMotionListener.h"
#include "nsIDOMContextMenuListener.h"
#include "nsIDOMKeyListener.h"
#include "nsContentCID.h"
#include "nsIScriptGlobalObject.h"
@ -66,13 +63,11 @@
#include "nsIDocument.h"
#include "nsIContent.h"
#include "nsIDOMMouseEvent.h"
#include "nsITimer.h"
#include "nsIDOMNSUIEvent.h"
#include "nsIDOMEventTarget.h"
#include "nsIBoxObject.h"
#include "nsIPopupBoxObject.h"
#include "nsIMenuBoxObject.h"
// for event firing in context menus
#include "nsIPresContext.h"
@ -81,8 +76,6 @@
#include "nsIFrame.h"
#include "nsIStyleContext.h"
#include "nsIPref.h"
// on win32 and os/2, context menus come up on mouse up. On other platforms,
// they appear on mouse down. Certain bits of code care about this difference.
@ -100,13 +93,10 @@ static NS_DEFINE_IID(kXULPopupListenerCID, NS_XULPOPUPLISTENER_CID);
////////////////////////////////////////////////////////////////////////
// PopupListenerImpl
//
// This is the popup listener implementation for popup menus, context menus,
// and tooltips.
// This is the popup listener implementation for popup menus and context menus.
//
class XULPopupListenerImpl : public nsIXULPopupListener,
public nsIDOMMouseListener,
public nsIDOMKeyListener,
public nsIDOMMouseMotionListener,
public nsIDOMContextMenuListener
{
public:
@ -122,47 +112,26 @@ public:
// nsIDOMMouseListener
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseUp(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 MouseMove(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragMove(nsIDOMEvent* aMouseEvent) { return NS_OK; };
NS_IMETHOD MouseOut(nsIDOMEvent* aMouseEvent) { return NS_OK; };
// nsIDOMContextMenuListener
NS_IMETHOD ContextMenu(nsIDOMEvent* aContextMenuEvent);
// nsIDOMKeyListener
NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent) ;
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent) ;
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent) ;
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* anEvent) { return NS_OK; };
protected:
virtual void KillTooltipTimer ( ) ;
virtual nsresult LaunchPopup(nsIDOMEvent* anEvent);
virtual nsresult LaunchPopup(PRInt32 aClientX, PRInt32 aClientY) ;
virtual void ClosePopup ( ) ;
void CreateAutoHideTimer ( ) ;
nsresult FindDocumentForNode(nsIDOMNode* inNode, nsIDOMXULDocument** outDoc) ;
virtual void ClosePopup();
private:
// various delays for tooltips
enum {
kTooltipAutoHideTime = 5000, // 5000ms = 5 seconds
kTooltipShowTime = 500 // 500ms = 0.5 seconds
};
nsresult PreLaunchPopup(nsIDOMEvent* aMouseEvent);
nsresult FireFocusOnTargetContent(nsIDOMNode* aTargetNode);
@ -175,40 +144,12 @@ private:
// The type of the popup
XULPopupType popupType;
// a timer for determining if a tooltip should be displayed.
nsCOMPtr<nsITimer> mTooltipTimer;
static void sTooltipCallback ( nsITimer* aTimer, void* aListener ) ;
PRInt32 mMouseClientX, mMouseClientY; // mouse coordinates for tooltip event
// a timer for auto-hiding the tooltip after a certain delay
nsCOMPtr<nsITimer> mAutoHideTimer;
static void sAutoHideCallback ( nsITimer* aTimer, void* aListener ) ;
// pref callback for when the "show tooltips" pref changes
static int sTooltipPrefChanged ( const char*, void* );
// The following members are not used unless |popupType| is tooltip.
static PRBool sShowTooltips; // mirrors the "show tooltips" pref
// The node hovered over that fired the timer. This may turn into the node that
// triggered the tooltip, but only if the timer ever gets around to firing.
// This is a strong reference, because the tooltip content can be destroyed while we're
// waiting for the tooltip to pup up, and we need to detect that.
// It's set only when the tooltip timer is created and launched. The timer must
// either fire or be cancelled (or possibly released?), and we release this
// reference in each of those cases. So we don't leak.
nsCOMPtr<nsIDOMNode> mPossibleTooltipNode;
};
////////////////////////////////////////////////////////////////////////
PRBool XULPopupListenerImpl::sShowTooltips = PR_FALSE;
XULPopupListenerImpl::XULPopupListenerImpl(void)
: mElement(nsnull), mPopupContent(nsnull),
mMouseClientX(0), mMouseClientY(0)
: mElement(nsnull), mPopupContent(nsnull)
{
NS_INIT_REFCNT();
}
@ -230,9 +171,7 @@ NS_IMPL_RELEASE(XULPopupListenerImpl)
NS_INTERFACE_MAP_BEGIN(XULPopupListenerImpl)
NS_INTERFACE_MAP_ENTRY(nsIXULPopupListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseMotionListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMContextMenuListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULPopupListener)
NS_INTERFACE_MAP_END
@ -242,54 +181,12 @@ XULPopupListenerImpl::Init(nsIDOMElement* aElement, const XULPopupType& popup)
{
mElement = aElement; // Weak reference. Don't addref it.
popupType = popup;
static PRBool prefChangeRegistered = PR_FALSE;
nsresult rv = NS_OK;
// 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, &rv));
if ( prefs ) {
// get the initial value of the pref
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 rv;
}
//
// sTooltipPrefChanged
//
// Called when the tooltip pref changes. Refetch it.
int
XULPopupListenerImpl :: sTooltipPrefChanged (const char *, void * inData )
{
nsresult rv = NS_OK;
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID, &rv));
if ( prefs ) {
rv = prefs->GetBoolPref("browser.chrome.toolbar_tips", &sShowTooltips);
}
return NS_OK;
} // sTooltipPrefChanged
}
////////////////////////////////////////////////////////////////
// nsIDOMMouseListener
nsresult
XULPopupListenerImpl::MouseUp(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
nsresult
XULPopupListenerImpl::MouseDown(nsIDOMEvent* aMouseEvent)
{
@ -370,9 +267,7 @@ XULPopupListenerImpl::PreLaunchPopup(nsIDOMEvent* aMouseEvent)
}
// Store clicked-on node in xul document for context menus and menu popups.
// Tooltips are stored in tooltipNode instead.
if (popupType != eXULPopupType_tooltip)
xulDocument->SetPopupNode( targetNode );
xulDocument->SetPopupNode( targetNode );
switch (popupType) {
case eXULPopupType_popup:
@ -397,16 +292,6 @@ XULPopupListenerImpl::PreLaunchPopup(nsIDOMEvent* aMouseEvent)
aMouseEvent->PreventBubble();
aMouseEvent->PreventDefault();
break;
case eXULPopupType_tooltip:
// get rid of the tooltip on a mousedown.
ClosePopup();
break;
case eXULPopupType_blur:
// what on earth is this?!
break;
}
return NS_OK;
}
@ -468,180 +353,16 @@ XULPopupListenerImpl::FireFocusOnTargetContent(nsIDOMNode* aTargetNode)
return rv;
}
//
// MouseMove
//
// If we're a tooltip, fire off a timer to see if a tooltip should be shown.
//
nsresult
XULPopupListenerImpl::MouseMove(nsIDOMEvent* aMouseEvent)
{
// make sure we're a tooltip. if not, bail.
if ( popupType != eXULPopupType_tooltip )
return NS_OK;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
if (!mouseEvent)
return NS_OK;
// don't kick off the timer or do any hard work if the pref is turned off
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.
PRInt32 newMouseX, newMouseY;
mouseEvent->GetClientX(&newMouseX);
mouseEvent->GetClientY(&newMouseY);
if ( mMouseClientX == newMouseX && mMouseClientY == newMouseY )
return NS_OK;
mMouseClientX = newMouseX; mMouseClientY = newMouseY;
// 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 popup is up, don't do anything. We make it
// go away only if it times out or leaves the tooltip node. If nothing is
// showing, though, we have to do the work. We can tell if we have a popup
// showing because |mPopupContent| will be non-null.
if ( !mPopupContent ) {
mTooltipTimer = do_CreateInstance("@mozilla.org/timer;1");
if ( mTooltipTimer ) {
nsCOMPtr<nsIDOMEventTarget> eventTarget;
aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
if ( eventTarget )
mPossibleTooltipNode = do_QueryInterface(eventTarget);
if ( mPossibleTooltipNode ) {
nsresult rv = mTooltipTimer->Init(sTooltipCallback, this, kTooltipShowTime, NS_PRIORITY_HIGH);
if (NS_FAILED(rv))
mPossibleTooltipNode = nsnull;
}
}
else
NS_WARNING ( "Could not create a timer for tooltip tracking" );
}
return NS_OK;
} // MouseMove
//
// MouseOut
//
// If we're a tooltip, hide any tip that might be showing and remove any
// timer that is pending since the mouse is no longer over this area.
//
nsresult
XULPopupListenerImpl::MouseOut(nsIDOMEvent* aMouseEvent)
{
// make sure we're a tooltip. if not, bail.
if ( popupType != eXULPopupType_tooltip )
return NS_OK;
// mouse is leaving something which means it is in motion. Kill
// our timer, but don't close anything just yet. We need to wait
// and see if we're leaving the right node.
KillTooltipTimer();
// which node did the mouse leave?
nsCOMPtr<nsIDOMEventTarget> eventTarget;
aMouseEvent->GetTarget(getter_AddRefs(eventTarget));
nsCOMPtr<nsIDOMNode> eventNode ( do_QueryInterface(eventTarget) );
// which node is our tooltip on?
nsCOMPtr<nsIDOMXULDocument> doc;
FindDocumentForNode ( mElement, getter_AddRefs(doc) );
nsCOMPtr<nsIDOMNode> tooltipNode;
doc->GetTooltipNode ( getter_AddRefs(tooltipNode) );
// if they're the same, the mouse left the node the tooltip appeared on,
// close the popup.
if ( tooltipNode == eventNode )
ClosePopup();
return NS_OK;
} // MouseOut
//
// KeyDown
//
// If we're a tooltip, hide any tip that might be showing and remove any
// timer that is pending since the mouse is no longer over this area.
//
nsresult
XULPopupListenerImpl::KeyDown(nsIDOMEvent* aMouseEvent)
{
// make sure we're a tooltip. if not, bail.
if ( popupType != eXULPopupType_tooltip )
return NS_OK;
ClosePopup();
return NS_OK;
} // KeyDown
//
// KeyUp
// KeyPress
//
// We can ignore these as they are already handled by KeyDown
//
nsresult
XULPopupListenerImpl::KeyUp(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
} // KeyUp
nsresult
XULPopupListenerImpl::KeyPress(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
} // KeyPress
//
// KillTooltipTimer
//
// Stop the timer that would show a tooltip dead in its tracks
//
void
XULPopupListenerImpl :: KillTooltipTimer ( )
{
if ( mTooltipTimer ) {
mTooltipTimer->Cancel();
mTooltipTimer = nsnull;
mPossibleTooltipNode = nsnull; // release tooltip target
}
} // KillTooltipTimer
//
// ClosePopup
//
// Do everything needed to shut down the popup, including killing off all
// the timers that may be involved.
// Do everything needed to shut down the popup.
//
// NOTE: This routine is safe to call even if the popup is already closed.
//
void
XULPopupListenerImpl :: ClosePopup ( )
{
KillTooltipTimer();
if ( mAutoHideTimer ) {
mAutoHideTimer->Cancel();
mAutoHideTimer = nsnull;
}
if ( mPopupContent ) {
nsCOMPtr<nsIDOMXULElement> popupElement(do_QueryInterface(mPopupContent));
nsCOMPtr<nsIBoxObject> boxObject;
@ -652,52 +373,10 @@ XULPopupListenerImpl :: ClosePopup ( )
popupObject->HidePopup();
mPopupContent = nsnull; // release the popup
// clear out the tooltip node on the document
nsCOMPtr<nsIDOMXULDocument> doc;
FindDocumentForNode ( mElement, getter_AddRefs(doc) );
if ( doc )
doc->SetTooltipNode(nsnull);
}
} // ClosePopup
//
// FindDocumentForNode
//
// Given a DOM content node, finds the XUL document associated with it
//
nsresult
XULPopupListenerImpl :: FindDocumentForNode ( nsIDOMNode* inElement, nsIDOMXULDocument** outDoc )
{
nsresult rv = NS_OK;
if ( !outDoc || !inElement )
return NS_ERROR_INVALID_ARG;
// get the document associated with this content element
nsCOMPtr<nsIDocument> document;
nsCOMPtr<nsIContent> content = do_QueryInterface(inElement);
if ( !content || NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document))) ) {
NS_ERROR("Unable to retrieve the document.");
return rv;
}
nsCOMPtr<nsIDOMXULDocument> xulDocument = do_QueryInterface(document);
if ( !xulDocument ) {
NS_ERROR("Popup attached to an element that isn't in XUL!");
return NS_ERROR_FAILURE;
}
*outDoc = xulDocument;
NS_ADDREF ( *outDoc );
return rv;
} // FindDocumentForNode
//
// LaunchPopup
//
@ -795,7 +474,7 @@ static void ConvertPosition(nsIDOMElement* aPopupElt, nsString& aAnchor, nsStrin
// content.
//
// This looks for an attribute on |aElement| of the appropriate popup type
// (popup, context, tooltip) and uses that attribute's value as an ID for
// (popup, context) and uses that attribute's value as an ID for
// the popup content in the document.
//
nsresult
@ -813,8 +492,6 @@ XULPopupListenerImpl::LaunchPopup(PRInt32 aClientX, PRInt32 aClientY)
aClientX += 2;
aClientY += 2;
}
else if ( popupType == eXULPopupType_tooltip )
type.AssignWithConversion("tooltip");
nsAutoString identifier;
mElement->GetAttribute(type, identifier);
@ -828,9 +505,7 @@ XULPopupListenerImpl::LaunchPopup(PRInt32 aClientX, PRInt32 aClientY)
return rv;
}
// Try to find the popup content and the document. We don't use FindDocumentForNode()
// in this case because we need the nsIDocument interface anyway for the script
// context.
// Try to find the popup content and the document.
nsCOMPtr<nsIDocument> document;
nsCOMPtr<nsIContent> content = do_QueryInterface(mElement);
if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) {
@ -851,7 +526,7 @@ XULPopupListenerImpl::LaunchPopup(PRInt32 aClientX, PRInt32 aClientY)
if (identifier == NS_LITERAL_STRING("_child")) {
nsCOMPtr<nsIContent> popup;
nsIAtom* tag = (popupType == eXULPopupType_tooltip) ? nsXULAtoms::tooltip : nsXULAtoms::menupopup;
nsIAtom* tag = nsXULAtoms::menupopup;
GetImmediateChild(content, tag, getter_AddRefs(popup));
if (popup)
@ -925,95 +600,6 @@ XULPopupListenerImpl::LaunchPopup(PRInt32 aClientX, PRInt32 aClientY)
return NS_OK;
}
//
// sTooltipCallback
//
// A timer callback, fired when the mouse has hovered inside of a frame for the
// appropriate amount of time. Getting to this point means that we should show the
// toolip.
//
// This relies on certain things being cached into the |aPopupListener|
// object passed to us by the timer:
// -- the x/y coordinates of the mouse (mMouseClientY, mMouseClientX)
// -- the dom node the user hovered over (mPossibleTooltipNode)
//
void
XULPopupListenerImpl :: sTooltipCallback (nsITimer *aTimer, void *aPopupListener)
{
XULPopupListenerImpl* self = NS_STATIC_CAST(XULPopupListenerImpl*, aPopupListener);
if ( self && self->mPossibleTooltipNode ) {
// set the node in the document that triggered the tooltip and show it
nsCOMPtr<nsIDOMXULDocument> doc;
self->FindDocumentForNode ( self->mElement, getter_AddRefs(doc) );
if ( doc ) {
// Make sure the target node is still attached to some document. It might have been deleted.
nsCOMPtr<nsIDOMDocument> targetDoc;
self->mPossibleTooltipNode->GetOwnerDocument(getter_AddRefs(targetDoc));
if ( targetDoc ) {
doc->SetTooltipNode ( self->mPossibleTooltipNode );
doc->SetPopupNode ( self->mPossibleTooltipNode );
self->LaunchPopup ( self->mMouseClientX, self->mMouseClientY+21);
// at this point, |mPopupContent| holds the content node of
// the popup. If there is an attribute on the popup telling us
// not to create the auto-hide timer, don't.
if ( self->mPopupContent ) {
nsAutoString noAutoHide;
self->mPopupContent->GetAttribute ( NS_LITERAL_STRING("noautohide"), noAutoHide );
if ( noAutoHide != NS_LITERAL_STRING("true") )
self->CreateAutoHideTimer();
}
} // if tooltip target's document exists
} // if document
// release tooltip target if there is one, NO MATTER WHAT
self->mPossibleTooltipNode = nsnull;
} // if "self" data valid
} // sTooltipCallback
//
// CreateAutoHideTimer
//
// Create a new timer to see if we should auto-hide. It's ok if this fails.
//
void
XULPopupListenerImpl :: CreateAutoHideTimer ( )
{
// just to be anal (er, safe)
if ( mAutoHideTimer ) {
mAutoHideTimer->Cancel();
mAutoHideTimer = nsnull;
}
mAutoHideTimer = do_CreateInstance("@mozilla.org/timer;1");
if ( mAutoHideTimer )
mAutoHideTimer->Init(sAutoHideCallback, this, kTooltipAutoHideTime, NS_PRIORITY_HIGH);
} // CreateAutoHideTimer
//
// sAutoHideCallback
//
// This fires after a tooltip has been open for a certain length of time. Just tell
// the listener to close the popup. We don't have to worry, because ClosePopup() can
// be called multiple times, even if the popup has already been closed.
//
void
XULPopupListenerImpl :: sAutoHideCallback ( nsITimer *aTimer, void* aListener )
{
XULPopupListenerImpl* self = NS_STATIC_CAST(XULPopupListenerImpl*, aListener);
if ( self )
self->ClosePopup();
// NOTE: |aTimer| and |self->mAutoHideTimer| are invalid after calling ClosePopup();
} // sAutoHideCallback
////////////////////////////////////////////////////////////////
nsresult
NS_NewXULPopupListener(nsIXULPopupListener** pop)

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

@ -103,6 +103,7 @@
#include "nsRuleNode.h"
#include "nsIXULDocument.h"
#include "nsIPrintPreviewContext.h"
#include "nsIDOMMutationEvent.h"
static NS_DEFINE_CID(kTextNodeCID, NS_TEXTNODE_CID);
static NS_DEFINE_CID(kHTMLElementFactoryCID, NS_HTML_ELEMENT_FACTORY_CID);
@ -5522,6 +5523,21 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
isReplaced = PR_TRUE;
rv = NS_NewMenuPopupFrame(aPresShell, &newFrame);
if (aTag == nsXULAtoms::tooltip) {
nsAutoString defaultTooltip;
aContent->GetAttr(kNameSpaceID_None, nsXULAtoms::defaultz, defaultTooltip);
if (defaultTooltip.EqualsIgnoreCase("true")) {
// Locate the root frame and tell it about the tooltip.
nsIFrame* rootFrame = nsnull;
aState.mFrameManager->GetRootFrame(&rootFrame);
if (rootFrame)
rootFrame->FirstChild(aPresContext, nsnull, &rootFrame);
nsCOMPtr<nsIRootBox> rootBox(do_QueryInterface(rootFrame));
if (rootBox)
rootBox->SetDefaultTooltip(aContent);
}
}
// If a popup is inside a menu, then the menu understands the complex
// rules/behavior governing the cascade of multiple menu popups and can handle
// having the real popup frame placed under it as a child.
@ -5650,6 +5666,24 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
aFrameItems.AddChild(topFrame);
}
// register tooltip support if needed
nsAutoString value;
if (aTag == nsXULAtoms::outlinerbody || // outliners always need titletips
aContent->GetAttr(kNameSpaceID_None, nsXULAtoms::tooltiptext, value) !=
NS_CONTENT_ATTR_NOT_THERE ||
aContent->GetAttr(kNameSpaceID_None, nsXULAtoms::tooltip, value) !=
NS_CONTENT_ATTR_NOT_THERE)
{
nsIFrame* rootFrame = nsnull;
aState.mFrameManager->GetRootFrame(&rootFrame);
if (rootFrame)
rootFrame->FirstChild(aPresContext, nsnull, &rootFrame);
nsCOMPtr<nsIRootBox> rootBox(do_QueryInterface(rootFrame));
if (rootBox)
rootBox->AddTooltipSupport(aContent);
}
// addToHashTable:
if (topFrame) {
@ -10106,6 +10140,23 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext,
tag.get() == nsXULAtoms::treerow || tag.get() == nsXULAtoms::treecell))
return NS_OK;
}
if (aAttribute == nsXULAtoms::tooltiptext ||
aAttribute == nsXULAtoms::tooltip)
{
nsIFrame* rootFrame = nsnull;
shell->GetRootFrame(&rootFrame);
if (rootFrame)
rootFrame->FirstChild(aPresContext, nsnull, &rootFrame);
nsCOMPtr<nsIRootBox> rootBox(do_QueryInterface(rootFrame));
if (rootBox) {
if (aModType == nsIDOMMutationEvent::REMOVAL)
rootBox->RemoveTooltipSupport(aContent);
if (aModType == nsIDOMMutationEvent::ADDITION)
rootBox->AddTooltipSupport(aContent);
}
}
#endif // INCLUDE_XUL
// check for inline style. we need to clear the data at the style context's rule

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

@ -103,6 +103,7 @@
#include "nsRuleNode.h"
#include "nsIXULDocument.h"
#include "nsIPrintPreviewContext.h"
#include "nsIDOMMutationEvent.h"
static NS_DEFINE_CID(kTextNodeCID, NS_TEXTNODE_CID);
static NS_DEFINE_CID(kHTMLElementFactoryCID, NS_HTML_ELEMENT_FACTORY_CID);
@ -5522,6 +5523,21 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
isReplaced = PR_TRUE;
rv = NS_NewMenuPopupFrame(aPresShell, &newFrame);
if (aTag == nsXULAtoms::tooltip) {
nsAutoString defaultTooltip;
aContent->GetAttr(kNameSpaceID_None, nsXULAtoms::defaultz, defaultTooltip);
if (defaultTooltip.EqualsIgnoreCase("true")) {
// Locate the root frame and tell it about the tooltip.
nsIFrame* rootFrame = nsnull;
aState.mFrameManager->GetRootFrame(&rootFrame);
if (rootFrame)
rootFrame->FirstChild(aPresContext, nsnull, &rootFrame);
nsCOMPtr<nsIRootBox> rootBox(do_QueryInterface(rootFrame));
if (rootBox)
rootBox->SetDefaultTooltip(aContent);
}
}
// If a popup is inside a menu, then the menu understands the complex
// rules/behavior governing the cascade of multiple menu popups and can handle
// having the real popup frame placed under it as a child.
@ -5650,6 +5666,24 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
aFrameItems.AddChild(topFrame);
}
// register tooltip support if needed
nsAutoString value;
if (aTag == nsXULAtoms::outlinerbody || // outliners always need titletips
aContent->GetAttr(kNameSpaceID_None, nsXULAtoms::tooltiptext, value) !=
NS_CONTENT_ATTR_NOT_THERE ||
aContent->GetAttr(kNameSpaceID_None, nsXULAtoms::tooltip, value) !=
NS_CONTENT_ATTR_NOT_THERE)
{
nsIFrame* rootFrame = nsnull;
aState.mFrameManager->GetRootFrame(&rootFrame);
if (rootFrame)
rootFrame->FirstChild(aPresContext, nsnull, &rootFrame);
nsCOMPtr<nsIRootBox> rootBox(do_QueryInterface(rootFrame));
if (rootBox)
rootBox->AddTooltipSupport(aContent);
}
// addToHashTable:
if (topFrame) {
@ -10106,6 +10140,23 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext,
tag.get() == nsXULAtoms::treerow || tag.get() == nsXULAtoms::treecell))
return NS_OK;
}
if (aAttribute == nsXULAtoms::tooltiptext ||
aAttribute == nsXULAtoms::tooltip)
{
nsIFrame* rootFrame = nsnull;
shell->GetRootFrame(&rootFrame);
if (rootFrame)
rootFrame->FirstChild(aPresContext, nsnull, &rootFrame);
nsCOMPtr<nsIRootBox> rootBox(do_QueryInterface(rootFrame));
if (rootBox) {
if (aModType == nsIDOMMutationEvent::REMOVAL)
rootBox->RemoveTooltipSupport(aContent);
if (aModType == nsIDOMMutationEvent::ADDITION)
rootBox->AddTooltipSupport(aContent);
}
}
#endif // INCLUDE_XUL
// check for inline style. we need to clear the data at the style context's rule

Двоичные данные
layout/macbuild/layout.mcp

Двоичный файл не отображается.

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

@ -105,6 +105,7 @@ CPPSRCS = \
nsRepeatService.cpp \
nsTitleBarFrame.cpp \
nsResizerFrame.cpp \
nsXULTooltipListener.cpp \
$(NULL)
include $(topsrcdir)/config/config.mk

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

@ -103,6 +103,7 @@ CPPSRCS= \
nsPopupSetFrame.cpp \
nsTitleBarFrame.cpp \
nsResizerFrame.cpp \
nsXULTooltipListener.cpp \
$(NULL)
CPP_OBJS= \
@ -158,6 +159,7 @@ CPP_OBJS= \
.\$(OBJDIR)\nsMenuDismissalListener.obj \
.\$(OBJDIR)\nsTitleBarFrame.obj \
.\$(OBJDIR)\nsResizerFrame.obj \
.\$(OBJDIR)\nsXULTooltipListener.obj \
$(NULL)
LINCS= \

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

@ -53,6 +53,7 @@
#include "nsStyleConsts.h"
#include "nsIViewManager.h"
#include "nsHTMLAtoms.h"
#include "nsXULAtoms.h"
#include "nsIEventStateManager.h"
#include "nsIDeviceContext.h"
#include "nsIScrollableView.h"
@ -132,14 +133,22 @@ nsDocElementBoxFrame::CreateAnonymousContent(nsIPresContext* aPresContext,
doc->GetNodeInfoManager(*getter_AddRefs(nodeInfoManager));
NS_ENSURE_TRUE(nodeInfoManager, NS_ERROR_FAILURE);
// create the top-secret popupgroup node. shhhhh!
nsCOMPtr<nsINodeInfo> nodeInfo;
nodeInfoManager->GetNodeInfo(NS_LITERAL_STRING("popupgroup"), NS_LITERAL_STRING(""), NS_LITERAL_STRING("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"),
*getter_AddRefs(nodeInfo));
nsCOMPtr<nsIContent> content;
elementFactory->CreateInstanceByTag(nodeInfo, getter_AddRefs(content));
aAnonymousItems.AppendElement(content);
// create the top-secret default tooltip node. shhhhh!
nodeInfoManager->GetNodeInfo(NS_LITERAL_STRING("tooltip"), NS_LITERAL_STRING(""), NS_LITERAL_STRING("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"),
*getter_AddRefs(nodeInfo));
elementFactory->CreateInstanceByTag(nodeInfo, getter_AddRefs(content));
content->SetAttr(nsnull, nsXULAtoms::defaultz, NS_LITERAL_STRING("true"), PR_FALSE);
aAnonymousItems.AppendElement(content);
return NS_OK;
}

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

@ -42,6 +42,7 @@
#include "nsISupports.h"
class nsIFrame;
class nsIContent;
// {DF05F6AB-320B-4e06-AFB3-E39E632A7555}
#define NS_IROOTBOX_IID \
@ -54,6 +55,12 @@ public:
NS_IMETHOD GetPopupSetFrame(nsIFrame** aResult)=0;
NS_IMETHOD SetPopupSetFrame(nsIFrame* aPopupSet)=0;
NS_IMETHOD GetDefaultTooltip(nsIContent** aResult)=0;
NS_IMETHOD SetDefaultTooltip(nsIContent* aTooltip)=0;
NS_IMETHOD AddTooltipSupport(nsIContent* aNode)=0;
NS_IMETHOD RemoveTooltipSupport(nsIContent* aNode)=0;
};
#endif

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

@ -329,7 +329,7 @@ nsPopupSetFrame::ShowPopup(nsIContent* aElementContent, nsIContent* aPopupConten
const nsString& aPopupAlignment)
{
// First fire the popupshowing event.
if (!OnCreate(aPopupContent))
if (!OnCreate(aXPos, aYPos, aPopupContent))
return NS_OK;
// See if we already have an entry in our list. We must create a new one on a miss.
@ -373,7 +373,7 @@ nsPopupSetFrame::ShowPopup(nsIContent* aElementContent, nsIContent* aPopupConten
OpenPopup(entry, PR_TRUE);
// Now fire the popupshown event.
OnCreated(aPopupContent);
OnCreated(aXPos, aYPos, aPopupContent);
return NS_OK;
}
@ -520,7 +520,7 @@ nsPopupSetFrame::ActivatePopup(nsPopupFrameList* aEntry, PRBool aActivateFlag)
}
PRBool
nsPopupSetFrame::OnCreate(nsIContent* aPopupContent)
nsPopupSetFrame::OnCreate(PRInt32 aX, PRInt32 aY, nsIContent* aPopupContent)
{
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
@ -532,6 +532,8 @@ nsPopupSetFrame::OnCreate(nsIContent* aPopupContent)
event.isMeta = PR_FALSE;
event.clickCount = 0;
event.widget = nsnull;
event.point.x = aX;
event.point.y = aY;
if (aPopupContent) {
nsCOMPtr<nsIPresShell> shell;
@ -599,7 +601,7 @@ nsPopupSetFrame::OnCreate(nsIContent* aPopupContent)
}
PRBool
nsPopupSetFrame::OnCreated(nsIContent* aPopupContent)
nsPopupSetFrame::OnCreated(PRInt32 aX, PRInt32 aY, nsIContent* aPopupContent)
{
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
@ -611,6 +613,8 @@ nsPopupSetFrame::OnCreated(nsIContent* aPopupContent)
event.isMeta = PR_FALSE;
event.clickCount = 0;
event.widget = nsnull;
event.point.x = aX;
event.point.y = aY;
if (aPopupContent) {
nsCOMPtr<nsIPresShell> shell;

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

@ -99,9 +99,9 @@ public:
NS_IMETHOD AddPopupFrame(nsIFrame* aPopup);
NS_IMETHOD RemovePopupFrame(nsIFrame* aPopup);
PRBool OnCreate(nsIContent* aPopupContent);
PRBool OnCreate(PRInt32 aX, PRInt32 aY, nsIContent* aPopupContent);
PRBool OnDestroy(nsIContent* aPopupContent);
PRBool OnCreated(nsIContent* aPopupContent);
PRBool OnCreated(PRInt32 aX, PRInt32 aY, nsIContent* aPopupContent);
PRBool OnDestroyed(nsIContent* aPopupContent);
void ActivatePopup(nsPopupFrameList* aEntry, PRBool aActivateFlag);

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

@ -61,6 +61,8 @@
#include "nsBoxFrame.h"
#include "nsStackLayout.h"
#include "nsIRootBox.h"
#include "nsIContent.h"
#include "nsXULTooltipListener.h"
// Interface IDs
@ -77,6 +79,10 @@ public:
NS_IMETHOD GetPopupSetFrame(nsIFrame** aResult);
NS_IMETHOD SetPopupSetFrame(nsIFrame* aPopupSet);
NS_IMETHOD GetDefaultTooltip(nsIContent** aResult);
NS_IMETHOD SetDefaultTooltip(nsIContent* aTooltip);
NS_IMETHOD AddTooltipSupport(nsIContent* aNode);
NS_IMETHOD RemoveTooltipSupport(nsIContent* aNode);
NS_IMETHOD AppendFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
@ -123,6 +129,9 @@ public:
#endif
nsIFrame* mPopupSetFrame;
protected:
nsIContent* mDefaultTooltip;
};
//----------------------------------------------------------------------
@ -305,6 +314,41 @@ nsRootBoxFrame::SetPopupSetFrame(nsIFrame* aPopupSet)
return NS_OK;
}
NS_IMETHODIMP
nsRootBoxFrame::GetDefaultTooltip(nsIContent** aTooltip)
{
*aTooltip = mDefaultTooltip;
return NS_OK;
}
NS_IMETHODIMP
nsRootBoxFrame::SetDefaultTooltip(nsIContent* aTooltip)
{
mDefaultTooltip = aTooltip;
return NS_OK;
}
NS_IMETHODIMP
nsRootBoxFrame::AddTooltipSupport(nsIContent* aNode)
{
// listener will be refcounted by dom event targets that
// it will add itself to, and destroyed when those targets
// are destroyed
nsXULTooltipListener* listener = new nsXULTooltipListener();
listener->Init(aNode, this);
return NS_OK;
}
NS_IMETHODIMP
nsRootBoxFrame::RemoveTooltipSupport(nsIContent* aNode)
{
// XXjh yuck, I'll have to implement a way to get at
// the tooltip listener for a given node to make
// this work. Not crucial, we aren't removing
// tooltips from any nodes in the app just yet.
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP_(nsrefcnt)
nsRootBoxFrame::AddRef(void)
{

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

@ -136,6 +136,11 @@ interface nsIOutlinerBoxObject : nsISupports
void getCoordsForCellItem(in long row, in wstring colID, in wstring element,
out long x, out long y, out long width, out long height);
/**
* Determine if the text of a cell is being cropped or not.
*/
boolean isCellCropped(in long row, in AString colID);
/**
* The view is responsible for calling these notification methods when
* rows are added or removed. Index is the position at which the new

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

@ -1170,6 +1170,95 @@ nsOutlinerBodyFrame::GetItemWithinCellAt(PRInt32 aX, const nsRect& aCellRect,
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerBodyFrame::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool *_retval)
{
nsOutlinerColumn* currCol = nsnull;
// Keep looping until we find a column with a matching Id.
for (currCol = mColumns; currCol; currCol = currCol->GetNext()) {
nsAutoString colID;
currCol->GetID(colID);
if (colID.Equals(aColID))
break;
}
if (currCol) {
// The rect for the current cell.
nsRect cellRect(0, 0, currCol->GetWidth(), mRowHeight);
// Adjust borders and padding for the cell.
nsCOMPtr<nsIStyleContext> cellContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinercell, getter_AddRefs(cellContext));
AdjustForBorderPadding(cellContext, cellRect);
nscoord remainWidth = cellRect.width;
if (currCol->IsPrimary()) {
// If the current Column is a Primary, then we need to take into account
// the indentation and possibly a twisty.
// The amount of indentation is the indentation width (|mIndentation|) by the level.
PRInt32 level;
mView->GetLevel(aRow, &level);
remainWidth -= mIndentation * level;
// Find the twisty rect by computing its size.
nsCOMPtr<nsIStyleContext> twistyContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinertwisty, getter_AddRefs(twistyContext));
// |GetImageSize| returns the rect of the twisty image, including the
// borders and padding.
nsRect twistyImageRect = GetImageSize(aRow, currCol->GetID(), twistyContext);
// Add in the margins of the twisty element.
const nsStyleMargin* twistyMarginData = (const nsStyleMargin*) twistyContext->GetStyleData(eStyleStruct_Margin);
nsMargin twistyMargin;
twistyMarginData->GetMargin(twistyMargin);
twistyImageRect.Inflate(twistyMargin);
remainWidth -= twistyImageRect.width;
}
nsCOMPtr<nsIStyleContext> imageContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
// Account for the width of the cell image.
nsRect imageSize = GetImageSize(aRow, currCol->GetID(), imageContext);
remainWidth -= imageSize.width;
// Get the cell text.
nsXPIDLString text;
mView->GetCellText(aRow, currCol->GetID(), getter_Copies(text));
nsAutoString cellText(text);
nsCOMPtr<nsIStyleContext> textContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinercelltext, getter_AddRefs(textContext));
// Get the borders and padding for the text.
nsStyleBorderPadding borderPadding;
textContext->GetBorderPaddingFor(borderPadding);
nsMargin bp(0,0,0,0);
borderPadding.GetBorderPadding(bp);
// Get the font style for the text and pass it to the rendering context.
const nsStyleFont* fontStyle = (const nsStyleFont*) textContext->GetStyleData(eStyleStruct_Font);
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
nsCOMPtr<nsIRenderingContext> rc;
shell->CreateRenderingContext(this, getter_AddRefs(rc));
rc->SetFont(fontStyle->mFont);
// Get the width of the text itself
nscoord width;
rc->GetWidth(cellText, width);
nscoord totalTextWidth = width + bp.left + bp.right;
// If |totalTextWidth| is greater than |remainWidth|, then we are cropping.
*_retval = totalTextWidth > remainWidth;
}
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBodyFrame::RowCountChanged(PRInt32 aIndex, PRInt32 aCount)
{
@ -2441,7 +2530,10 @@ nsOutlinerBodyFrame::EnsureColumns()
frame->GetParent(&colContainer);
} while (!frame);
nsCOMPtr<nsIBox> colContainerBox(do_QueryInterface(colContainer));
if (!colContainer)
return;
nsCOMPtr<nsIBox> colContainerBox(do_QueryInterface(colContainer));
nsIBox* colBox = nsnull;
colContainerBox->GetChildBox(&colBox);

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

@ -354,6 +354,15 @@ nsOutlinerBoxObject::GetCoordsForCellItem(PRInt32 aRow, const PRUnichar *aColID,
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerBoxObject::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool *_retval)
{
nsIOutlinerBoxObject* body = GetOutlinerBody();
if (body)
return body->IsCellCropped(aRow, aColID, _retval);
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBoxObject::RowCountChanged(PRInt32 aIndex, PRInt32 aDelta)
{
nsIOutlinerBoxObject* body = GetOutlinerBody();

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

@ -136,6 +136,11 @@ interface nsIOutlinerBoxObject : nsISupports
void getCoordsForCellItem(in long row, in wstring colID, in wstring element,
out long x, out long y, out long width, out long height);
/**
* Determine if the text of a cell is being cropped or not.
*/
boolean isCellCropped(in long row, in AString colID);
/**
* The view is responsible for calling these notification methods when
* rows are added or removed. Index is the position at which the new

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

@ -1170,6 +1170,95 @@ nsOutlinerBodyFrame::GetItemWithinCellAt(PRInt32 aX, const nsRect& aCellRect,
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerBodyFrame::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool *_retval)
{
nsOutlinerColumn* currCol = nsnull;
// Keep looping until we find a column with a matching Id.
for (currCol = mColumns; currCol; currCol = currCol->GetNext()) {
nsAutoString colID;
currCol->GetID(colID);
if (colID.Equals(aColID))
break;
}
if (currCol) {
// The rect for the current cell.
nsRect cellRect(0, 0, currCol->GetWidth(), mRowHeight);
// Adjust borders and padding for the cell.
nsCOMPtr<nsIStyleContext> cellContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinercell, getter_AddRefs(cellContext));
AdjustForBorderPadding(cellContext, cellRect);
nscoord remainWidth = cellRect.width;
if (currCol->IsPrimary()) {
// If the current Column is a Primary, then we need to take into account
// the indentation and possibly a twisty.
// The amount of indentation is the indentation width (|mIndentation|) by the level.
PRInt32 level;
mView->GetLevel(aRow, &level);
remainWidth -= mIndentation * level;
// Find the twisty rect by computing its size.
nsCOMPtr<nsIStyleContext> twistyContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinertwisty, getter_AddRefs(twistyContext));
// |GetImageSize| returns the rect of the twisty image, including the
// borders and padding.
nsRect twistyImageRect = GetImageSize(aRow, currCol->GetID(), twistyContext);
// Add in the margins of the twisty element.
const nsStyleMargin* twistyMarginData = (const nsStyleMargin*) twistyContext->GetStyleData(eStyleStruct_Margin);
nsMargin twistyMargin;
twistyMarginData->GetMargin(twistyMargin);
twistyImageRect.Inflate(twistyMargin);
remainWidth -= twistyImageRect.width;
}
nsCOMPtr<nsIStyleContext> imageContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
// Account for the width of the cell image.
nsRect imageSize = GetImageSize(aRow, currCol->GetID(), imageContext);
remainWidth -= imageSize.width;
// Get the cell text.
nsXPIDLString text;
mView->GetCellText(aRow, currCol->GetID(), getter_Copies(text));
nsAutoString cellText(text);
nsCOMPtr<nsIStyleContext> textContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinercelltext, getter_AddRefs(textContext));
// Get the borders and padding for the text.
nsStyleBorderPadding borderPadding;
textContext->GetBorderPaddingFor(borderPadding);
nsMargin bp(0,0,0,0);
borderPadding.GetBorderPadding(bp);
// Get the font style for the text and pass it to the rendering context.
const nsStyleFont* fontStyle = (const nsStyleFont*) textContext->GetStyleData(eStyleStruct_Font);
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
nsCOMPtr<nsIRenderingContext> rc;
shell->CreateRenderingContext(this, getter_AddRefs(rc));
rc->SetFont(fontStyle->mFont);
// Get the width of the text itself
nscoord width;
rc->GetWidth(cellText, width);
nscoord totalTextWidth = width + bp.left + bp.right;
// If |totalTextWidth| is greater than |remainWidth|, then we are cropping.
*_retval = totalTextWidth > remainWidth;
}
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBodyFrame::RowCountChanged(PRInt32 aIndex, PRInt32 aCount)
{
@ -2441,7 +2530,10 @@ nsOutlinerBodyFrame::EnsureColumns()
frame->GetParent(&colContainer);
} while (!frame);
nsCOMPtr<nsIBox> colContainerBox(do_QueryInterface(colContainer));
if (!colContainer)
return;
nsCOMPtr<nsIBox> colContainerBox(do_QueryInterface(colContainer));
nsIBox* colBox = nsnull;
colContainerBox->GetChildBox(&colBox);

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

@ -354,6 +354,15 @@ nsOutlinerBoxObject::GetCoordsForCellItem(PRInt32 aRow, const PRUnichar *aColID,
return NS_OK;
}
NS_IMETHODIMP
nsOutlinerBoxObject::IsCellCropped(PRInt32 aRow, const nsAString& aColID, PRBool *_retval)
{
nsIOutlinerBoxObject* body = GetOutlinerBody();
if (body)
return body->IsCellCropped(aRow, aColID, _retval);
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBoxObject::RowCountChanged(PRInt32 aIndex, PRInt32 aDelta)
{
nsIOutlinerBoxObject* body = GetOutlinerBody();