look in associated command object while building for attribute changes and dispatching. rewrite to use nsIContent and atoms instead of nsIDOMNode and strings. r=saari/sr=sfraser. bug 71470

This commit is contained in:
pinkerton%netscape.com 2001-03-22 03:53:57 +00:00
Родитель ac07ded896
Коммит 7f51023c63
13 изменённых файлов: 843 добавлений и 1050 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -35,7 +35,6 @@
class nsIMenuBar;
class nsIMenuListener;
class nsIDOMElement;
// temporary hack to get apple menu -- sfraser, approved saari
@ -68,14 +67,14 @@ public:
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow,
void * menuNode, void * aWebShell);
void* unused, void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
nsEventStatus CheckRebuild(PRBool & aMenuEvent);
nsEventStatus SetRebuild(PRBool aMenuEvent);
// nsIMenu Methods
NS_IMETHOD Create ( nsISupports * aParent, const nsAReadableString &aLabel, const nsAReadableString &aAccessKey,
nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode ) ;
nsIChangeManager* aManager, nsIWebShell* aShell, nsIContent* aNode ) ;
NS_IMETHOD GetParent(nsISupports *&aParent);
NS_IMETHOD GetLabel(nsString &aText);
NS_IMETHOD SetLabel(const nsAReadableString &aText);
@ -92,7 +91,7 @@ public:
NS_IMETHOD SetNativeData(void* aData);
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD GetDOMNode(nsIDOMNode ** aMenuNode);
NS_IMETHOD GetMenuContent(nsIContent ** aMenuNode);
NS_IMETHOD SetEnabled(PRBool aIsEnabled);
NS_IMETHOD GetEnabled(PRBool* aIsEnabled);
NS_IMETHOD IsHelpMenu(PRBool* aIsEnabled);
@ -112,13 +111,12 @@ public:
protected:
nsString mLabel;
PRUint32 mNumMenuItems;
nsSupportsArray mMenuItemsArray; // array holds refs
nsSupportsArray mMenuItemsArray; // array holds refs
nsIMenu* mMenuParent; // weak, my parent owns me
nsIMenuBar* mMenuBarParent;
nsIChangeManager* mManager; // weak ref, it will outlive us
nsISupports* mParent; // weak, my parent owns me
nsIChangeManager* mManager; // weak ref, it will outlive us
nsWeakPtr mWebShellWeakRef; // weak ref to webshell
nsCOMPtr<nsIDOMNode> mDOMNode; //strong ref
nsCOMPtr<nsIContent> mMenuContent; // the |menu| tag, strong ref
nsCOMPtr<nsIMenuListener> mListener;
bool mConstructed;
@ -135,17 +133,16 @@ protected:
nsresult GetNextVisibleMenu(nsIMenu** outNextVisibleMenu);
// fetch the content node associated with the menupopup item
void GetMenuPopupElement ( nsIDOMNode** aResult ) ;
void GetMenuPopupContent ( nsIContent** aResult ) ;
// fire handlers for oncreate/ondestroy
PRBool OnDestroy() ;
PRBool OnCreate() ;
void LoadMenuItem( nsIMenu * pParentMenu, nsIDOMElement * menuitemElement,
nsIDOMNode * menuitemNode, nsIWebShell * aWebShell);
void LoadSubMenu( nsIMenu * pParentMenu, nsIDOMElement * menuElement, nsIDOMNode * menuNode);
void LoadMenuItem ( nsIMenu* pParentMenu, nsIContent* menuitemContent);
void LoadSubMenu( nsIMenu * pParentMenu, nsIContent* menuitemContent);
nsEventStatus HelpMenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow,
void* menuNode, void* aWebShell);
void* unused, void* aWebShell);
MenuHandle NSStringNewMenu(short menuID, nsString& menuTitle);

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

@ -40,6 +40,8 @@
#include "nsIDocumentViewer.h"
#include "nsIDocumentObserver.h"
#include "nsWidgetAtoms.h"
#include "nsIDOMXULDocument.h"
#include <Menus.h>
@ -69,9 +71,7 @@ MenuHandle gLevel3HierMenu = nsnull;
MenuHandle gLevel4HierMenu = nsnull;
MenuHandle gLevel5HierMenu = nsnull;
#if !TARGET_CARBON
extern nsMenuStack gPreviousMenuStack;
#endif
extern PRInt16 gCurrentMenuDepth;
// #if APPLE_MENU_HACK
@ -96,22 +96,19 @@ NS_IMPL_ISUPPORTS5(nsMenuBar, nsIMenuBar, nsIMenuListener, nsIDocumentObserver,
// nsMenuBar constructor
//
nsMenuBar::nsMenuBar()
{
{
gCurrentMenuDepth = 1;
#if !TARGET_CARBON
nsPreviousMenuStackUnwind(nsnull, nsnull);
#endif
NS_INIT_REFCNT();
mNumMenus = 0;
mParent = nsnull;
mIsMenuBarAdded = PR_FALSE;
mUnicodeTextRunConverter = nsnull;
#if !TARGET_CARBON
MenuDefUPP mdef = NewMenuDefProc( nsDynamicMDEFMain );
InstallDefProc((short)nsMacResources::GetLocalResourceFile(), (ResType)'MDEF', (short)128, (Ptr) mdef );
#endif
mOriginalMacMBarHandle = nsnull;
mMacMBarHandle = nsnull;
@ -199,13 +196,9 @@ nsMenuBar::MenuSelected(const nsMenuEvent & aMenuEvent)
nsEventStatus eventStatus = nsEventStatus_eIgnore;
nsCOMPtr<nsIMenuListener> menuListener;
//((nsISupports*)mMenuVoidArray[i-1])->QueryInterface(NS_GET_IID(nsIMenuListener), (void**)&menuListener);
//printf("gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count());
#if !TARGET_CARBON
nsCOMPtr<nsIMenu> theMenu;
gPreviousMenuStack.GetMenuAt(gPreviousMenuStack.Count() - 1, getter_AddRefs(theMenu));
menuListener = do_QueryInterface(theMenu);
#endif
if (menuListener) {
//TODO: MenuSelected is the right thing to call...
//eventStatus = menuListener->MenuSelected(aMenuEvent);
@ -299,8 +292,9 @@ nsMenuBar::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWind
void * menubarNode, void * aWebShell )
{
mWebShellWeakRef = getter_AddRefs(NS_GetWeakReference(NS_STATIC_CAST(nsIWebShell*, aWebShell)));
mDOMNode = NS_STATIC_CAST(nsIDOMNode*, menubarNode); // strong ref
nsIDOMNode* aDOMNode = NS_STATIC_CAST(nsIDOMNode*, menubarNode);
mMenuBarContent = do_QueryInterface(aDOMNode); // strong ref
if(gFirstMenuBar) {
gOriginalMenuBar = getter_AddRefs(NS_GetWeakReference((nsIMenuBar *)this));
@ -310,7 +304,6 @@ nsMenuBar::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWind
MenuHandle macMenuHandle = ::NewMenu(2, "\psubmenu");
if(macMenuHandle) {
gLevel2HierMenu = macMenuHandle;
#if !TARGET_CARBON
SInt8 state = ::HGetState((Handle)macMenuHandle);
::HLock((Handle)macMenuHandle);
gSystemMDEFHandle = (**macMenuHandle).menuProc;
@ -318,14 +311,12 @@ nsMenuBar::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWind
(**macMenuHandle).menuWidth = -1;
(**macMenuHandle).menuHeight = -1;
::HSetState((Handle)macMenuHandle, state);
#endif
::InsertMenu(macMenuHandle, hierMenu);
}
macMenuHandle = ::NewMenu(3, "\psubmenu");
if(macMenuHandle) {
gLevel3HierMenu = macMenuHandle;
#if !TARGET_CARBON
SInt8 state = ::HGetState((Handle)macMenuHandle);
::HLock((Handle)macMenuHandle);
gSystemMDEFHandle = (**macMenuHandle).menuProc;
@ -333,14 +324,12 @@ nsMenuBar::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWind
(**macMenuHandle).menuWidth = -1;
(**macMenuHandle).menuHeight = -1;
::HSetState((Handle)macMenuHandle, state);
#endif
::InsertMenu(macMenuHandle, hierMenu);
}
macMenuHandle = ::NewMenu(4, "\psubmenu");
if(macMenuHandle) {
gLevel4HierMenu = macMenuHandle;
#if !TARGET_CARBON
SInt8 state = ::HGetState((Handle)macMenuHandle);
::HLock((Handle)macMenuHandle);
gSystemMDEFHandle = (**macMenuHandle).menuProc;
@ -348,14 +337,12 @@ nsMenuBar::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWind
(**macMenuHandle).menuWidth = -1;
(**macMenuHandle).menuHeight = -1;
::HSetState((Handle)macMenuHandle, state);
#endif
::InsertMenu(macMenuHandle, hierMenu);
}
macMenuHandle = ::NewMenu(5, "\psubmenu");
if(macMenuHandle) {
gLevel5HierMenu = macMenuHandle;
#if !TARGET_CARBON
SInt8 state = ::HGetState((Handle)macMenuHandle);
::HLock((Handle)macMenuHandle);
gSystemMDEFHandle = (**macMenuHandle).menuProc;
@ -363,7 +350,6 @@ nsMenuBar::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWind
(**macMenuHandle).menuWidth = -1;
(**macMenuHandle).menuHeight = -1;
::HSetState((Handle)macMenuHandle, state);
#endif
::InsertMenu(macMenuHandle, hierMenu);
}
} else {
@ -375,50 +361,45 @@ nsMenuBar::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWind
Create(aParentWindow);
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
if (webShell)
RegisterAsDocumentObserver(webShell);
// set this as a nsMenuListener on aParentWindow
aParentWindow->AddMenuListener((nsIMenuListener *)this);
nsCOMPtr<nsIDOMNode> menuNode;
mDOMNode->GetFirstChild(getter_AddRefs(menuNode));
while (menuNode)
{
nsCOMPtr<nsIDOMElement> menuElement(do_QueryInterface(menuNode));
if (menuElement)
{
nsAutoString menuNodeType;
nsAutoString menuName;
nsAutoString menuAccessKey(NS_LITERAL_STRING(" "));
menuElement->GetNodeName(menuNodeType);
if (menuNodeType == NS_LITERAL_STRING("menu")) {
menuElement->GetAttribute(NS_LITERAL_STRING("label"), menuName);
menuElement->GetAttribute(NS_LITERAL_STRING("accesskey"), menuAccessKey);
PRInt32 count;
mMenuBarContent->ChildCount(count);
for ( int i = 0; i < count; ++i ) {
nsCOMPtr<nsIContent> menu;
mMenuBarContent->ChildAt ( i, *getter_AddRefs(menu) );
if ( menu ) {
nsCOMPtr<nsIAtom> tag;
menu->GetTag ( *getter_AddRefs(tag) );
if (tag == nsWidgetAtoms::menu) {
nsAutoString menuName;
nsAutoString menuAccessKey(NS_LITERAL_STRING(" "));
menu->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::label, menuName);
menu->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::accesskey, menuAccessKey);
// Don't create the whole menu yet, just add in the top level names
// Create nsMenu, the menubar will own it
nsCOMPtr<nsIMenu> pnsMenu ( do_CreateInstance(kMenuCID) );
if ( pnsMenu )
{
if ( pnsMenu ) {
pnsMenu->Create(NS_STATIC_CAST(nsIMenuBar*, this), menuName, menuAccessKey,
NS_STATIC_CAST(nsIChangeManager *, this),
NS_REINTERPRET_CAST(nsIWebShell*, aWebShell), menuNode);
NS_REINTERPRET_CAST(nsIWebShell*, aWebShell), menu);
// Make nsMenu a child of nsMenuBar. nsMenuBar takes ownership
AddMenu(pnsMenu);
nsAutoString menuIDstring;
menuElement->GetAttribute(NS_LITERAL_STRING("id"), menuIDstring);
if(menuIDstring == NS_LITERAL_STRING("menu_Help")) {
menu->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::id, menuIDstring);
if ( menuIDstring == NS_LITERAL_STRING("menu_Help") ) {
nsMenuEvent event;
MenuHandle handle = nsnull;
#if !(defined(RHAPSODY) || defined(TARGET_CARBON))
::HMGetHelpMenuHandle(&handle);
#endif
event.mCommand = (unsigned int) handle;
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(pnsMenu));
listener->MenuSelected(event);
@ -426,18 +407,14 @@ nsMenuBar::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWind
}
}
}
nsCOMPtr<nsIDOMNode> tempNode = menuNode;
tempNode->GetNextSibling(getter_AddRefs(menuNode));
} // end while (nsnull != menuNode)
} // for each menu
// Give the aParentWindow this nsMenuBar to hold onto.
// The parent takes ownership
aParentWindow->SetMenuBar(this);
#ifdef XP_MAC
Handle tempMenuBar = ::GetMenuBar(); // Get a copy of the menu list
SetNativeData((void*)tempMenuBar);
#endif
return nsEventStatus_eIgnore;
}
@ -493,18 +470,21 @@ NS_METHOD nsMenuBar::AddMenu(nsIMenu * aMenu)
if (appleMenu)
{
// this code reads the "label" attribute from the <menuitem/> with
// id="aboutName" and puts its value in the Apple Menu
// id="aboutName" and puts its label in the Apple Menu
nsAutoString label;
nsCOMPtr<nsIDOMNode> domNode;
aMenu->GetDOMNode(getter_AddRefs(domNode));
if (domNode) {
nsCOMPtr<nsIDOMDocument> domDoc;
domNode->GetOwnerDocument(getter_AddRefs(domDoc));
if (domDoc) {
nsCOMPtr<nsIDOMElement> aboutMenuItem;
domDoc->GetElementById(NS_LITERAL_STRING("aboutName"), getter_AddRefs(aboutMenuItem));
if (aboutMenuItem)
aboutMenuItem->GetAttribute(NS_LITERAL_STRING("label"), label);
nsCOMPtr<nsIContent> menu;
aMenu->GetMenuContent(getter_AddRefs(menu));
if (menu) {
nsCOMPtr<nsIDocument> doc;
menu->GetDocument(*getter_AddRefs(doc));
if (doc) {
nsCOMPtr<nsIDOMDocument> domdoc ( do_QueryInterface(doc) );
if ( domdoc ) {
nsCOMPtr<nsIDOMElement> aboutMenuItem;
domdoc->GetElementById(NS_LITERAL_STRING("aboutName"), getter_AddRefs(aboutMenuItem));
if (aboutMenuItem)
aboutMenuItem->GetAttribute(NS_LITERAL_STRING("label"), label);
}
}
}
@ -524,11 +504,10 @@ NS_METHOD nsMenuBar::AddMenu(nsIMenu * aMenu)
PRBool helpMenu;
aMenu->IsHelpMenu(&helpMenu);
if(!helpMenu) {
nsCOMPtr<nsIDOMNode> domNode;
aMenu->GetDOMNode(getter_AddRefs(domNode));
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(domNode);
nsCOMPtr<nsIContent> menu;
aMenu->GetMenuContent(getter_AddRefs(menu));
nsAutoString menuHidden;
domElement->GetAttribute(NS_LITERAL_STRING("hidden"), menuHidden);
menu->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::hidden, menuHidden);
if( menuHidden != NS_LITERAL_STRING("true"))
::InsertMenu(menuHandle, 0);
}
@ -615,10 +594,9 @@ NS_METHOD nsMenuBar::Paint()
if (isHelpMenu)
{
MenuHandle helpMenuHandle = nil;
#if !TARGET_CARBON
::HMGetHelpMenuHandle(&helpMenuHandle);
menu->SetNativeData((void*)helpMenuHandle);
#endif
nsMenuEvent event;
event.mCommand = (unsigned int) helpMenuHandle;
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(menu);
@ -725,8 +703,7 @@ NS_IMETHODIMP
nsMenuBar::ContentAppended( nsIDocument * aDocument, nsIContent * aContainer,
PRInt32 aNewIndexInContainer)
{
nsCOMPtr<nsIContent> me ( do_QueryInterface(mDOMNode) );
if ( aContainer == me.get() ) {
if ( aContainer == mMenuBarContent ) {
//Register(aContainer, );
//InsertMenu ( aNewIndexInContainer );
}
@ -819,8 +796,7 @@ NS_IMETHODIMP
nsMenuBar::ContentRemoved( nsIDocument * aDocument, nsIContent * aContainer,
nsIContent * aChild, PRInt32 aIndexInContainer )
{
nsCOMPtr<nsIContent> me ( do_QueryInterface(mDOMNode) );
if ( aContainer == me.get() ) {
if ( aContainer == mMenuBarContent ) {
Unregister(aChild);
RemoveMenu ( aIndexInContainer );
}
@ -846,8 +822,7 @@ NS_IMETHODIMP
nsMenuBar::ContentInserted( nsIDocument * aDocument, nsIContent * aContainer,
nsIContent * aChild, PRInt32 aIndexInContainer )
{
nsCOMPtr<nsIContent> me ( do_QueryInterface(mDOMNode) );
if ( aContainer == me.get() ) {
if ( aContainer == mMenuBarContent ) {
//Register(aChild, );
//InsertMenu ( aIndexInContainer );
}

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

@ -82,7 +82,7 @@ public:
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow,
void * menuNode, void * aWebShell);
void* aDOMNode, void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
nsEventStatus CheckRebuild(PRBool & aMenuEvent);
nsEventStatus SetRebuild(PRBool aMenuEvent);
@ -164,7 +164,7 @@ protected:
PRUint32 mNumMenus;
nsSupportsArray mMenusArray; // holds refs
nsCOMPtr<nsIDOMNode> mDOMNode;
nsCOMPtr<nsIContent> mMenuBarContent; // menubar content node, strong ref
nsIWidget * mParent; // weak ref
PRBool mIsMenuBarAdded;

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

@ -42,6 +42,7 @@
#include "nsIDocumentObserver.h"
#include "nsIDOMXULDocument.h"
#include "nsWidgetAtoms.h"
#include <Menus.h>
#include <TextUtils.h>
@ -232,67 +233,63 @@ nsEventStatus
nsMenuBarX::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow,
void * menubarNode, void * aWebShell )
{
mWebShellWeakRef = getter_AddRefs(NS_GetWeakReference(NS_STATIC_CAST(nsIWebShell*, aWebShell)));
mDOMNode = NS_STATIC_CAST(nsIDOMNode*, menubarNode); // strong ref
mWebShellWeakRef = getter_AddRefs(NS_GetWeakReference(NS_STATIC_CAST(nsIWebShell*, aWebShell)));
mDOMNode = NS_STATIC_CAST(nsIDOMNode*, menubarNode); // strong ref
Create(aParentWindow);
Create(aParentWindow);
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
if (webShell) RegisterAsDocumentObserver(webShell);
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
if (webShell) RegisterAsDocumentObserver(webShell);
// set this as a nsMenuListener on aParentWindow
aParentWindow->AddMenuListener((nsIMenuListener *)this);
// set this as a nsMenuListener on aParentWindow
aParentWindow->AddMenuListener((nsIMenuListener *)this);
nsCOMPtr<nsIDOMNode> menuNode;
mDOMNode->GetFirstChild(getter_AddRefs(menuNode));
while (menuNode) {
nsCOMPtr<nsIDOMElement> menuElement(do_QueryInterface(menuNode));
if (menuElement) {
nsAutoString menuNodeType;
nsAutoString menuName;
nsAutoString menuAccessKey; menuAccessKey.AssignWithConversion(" ");
PRInt32 count;
mMenuBarContent->ChildCount(count);
for ( int i = 0; i < count; ++i ) {
nsCOMPtr<nsIContent> menu;
mMenuBarContent->ChildAt ( i, *getter_AddRefs(menu) );
if ( menu ) {
nsCOMPtr<nsIAtom> tag;
menu->GetTag ( *getter_AddRefs(tag) );
if (tag == nsWidgetAtoms::menu) {
nsAutoString menuName;
nsAutoString menuAccessKey(NS_LITERAL_STRING(" "));
menu->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::label, menuName);
menu->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::accesskey, menuAccessKey);
// Don't create the whole menu yet, just add in the top level names
// Create nsMenu, the menubar will own it
nsCOMPtr<nsIMenu> pnsMenu ( do_CreateInstance(kMenuCID) );
if ( pnsMenu ) {
pnsMenu->Create(NS_STATIC_CAST(nsIMenuBar*, this), menuName, menuAccessKey,
NS_STATIC_CAST(nsIChangeManager *, this),
NS_REINTERPRET_CAST(nsIWebShell*, aWebShell), menu);
menuElement->GetNodeName(menuNodeType);
if (menuNodeType == NS_LITERAL_STRING("menu")) {
menuElement->GetAttribute(NS_LITERAL_STRING("label"), menuName);
menuElement->GetAttribute(NS_LITERAL_STRING("accesskey"), menuAccessKey);
// Don't create the whole menu yet, just add in the top level names
// Create nsMenu, the menubar will own it
nsCOMPtr<nsIMenu> pnsMenu ( do_CreateInstance(kMenuCID) );
if ( pnsMenu ) {
pnsMenu->Create(NS_STATIC_CAST(nsIMenuBar*, this), menuName, menuAccessKey,
NS_STATIC_CAST(nsIChangeManager *, this),
NS_REINTERPRET_CAST(nsIWebShell*, aWebShell), menuNode);
// Make nsMenu a child of nsMenuBarX. nsMenuBarX takes ownership
AddMenu(pnsMenu);
nsAutoString menuIDstring;
menuElement->GetAttribute(NS_LITERAL_STRING("id"), menuIDstring);
if (menuIDstring == NS_LITERAL_STRING("menu_Help")) {
nsMenuEvent event;
MenuHandle handle = nsnull;
#if !(defined(RHAPSODY) || defined(TARGET_CARBON))
::HMGetHelpMenuHandle(&handle);
#endif
event.mCommand = (unsigned int) handle;
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(pnsMenu));
listener->MenuSelected(event);
}
}
}
// Make nsMenu a child of nsMenuBar. nsMenuBar takes ownership
AddMenu(pnsMenu);
nsAutoString menuIDstring;
menu->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::id, menuIDstring);
if ( menuIDstring == NS_LITERAL_STRING("menu_Help") ) {
nsMenuEvent event;
MenuHandle handle = nsnull;
::HMGetHelpMenuHandle(&handle);
event.mCommand = (unsigned int) handle;
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(pnsMenu));
listener->MenuSelected(event);
}
}
nsCOMPtr<nsIDOMNode> tempNode = menuNode;
tempNode->GetNextSibling(getter_AddRefs(menuNode));
} // end while (nsnull != menuNode)
}
}
} // for each menu
// Give the aParentWindow this nsMenuBarX to hold onto.
// The parent takes ownership
aParentWindow->SetMenuBar(this);
// Give the aParentWindow this nsMenuBarX to hold onto.
// The parent takes ownership
aParentWindow->SetMenuBar(this);
return nsEventStatus_eIgnore;
return nsEventStatus_eIgnore;
}
@ -332,30 +329,29 @@ NS_METHOD nsMenuBarX::SetParent(nsIWidget *aParent)
//-------------------------------------------------------------------------
NS_METHOD nsMenuBarX::AddMenu(nsIMenu * aMenu)
{
// keep track of all added menus.
mMenusArray.AppendElement(aMenu); // owner
// keep track of all added menus.
mMenusArray.AppendElement(aMenu); // owner
MenuRef menuRef = nsnull;
aMenu->GetNativeData((void**)&menuRef);
MenuRef menuRef = nsnull;
aMenu->GetNativeData((void**)&menuRef);
mNumMenus++;
PRBool helpMenu;
aMenu->IsHelpMenu(&helpMenu);
if(!helpMenu) {
nsCOMPtr<nsIDOMNode> domNode;
aMenu->GetDOMNode(getter_AddRefs(domNode));
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(domNode);
nsAutoString menuHidden;
domElement->GetAttribute(NS_LITERAL_STRING("hidden"), menuHidden);
if (menuHidden != NS_LITERAL_STRING("true")) {
Str255 title;
::InsertMenuItem(mRootMenu, ::GetMenuTitle(menuRef, title), mNumMenus);
OSStatus status = ::SetMenuItemHierarchicalMenu(mRootMenu, mNumMenus, menuRef);
NS_ASSERTION(status == noErr, "nsMenuBarX::AddMenu: SetMenuItemHierarchicalMenu failed.");
}
mNumMenus++;
PRBool helpMenu;
aMenu->IsHelpMenu(&helpMenu);
if(!helpMenu) {
nsCOMPtr<nsIContent> menu;
aMenu->GetMenuContent(getter_AddRefs(menu));
nsAutoString menuHidden;
menu->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::hidden, menuHidden);
if( menuHidden != NS_LITERAL_STRING("true"))
Str255 title;
::InsertMenuItem(mRootMenu, ::GetMenuTitle(menuRef, title), mNumMenus);
OSStatus status = ::SetMenuItemHierarchicalMenu(mRootMenu, mNumMenus, menuRef);
NS_ASSERTION(status == noErr, "nsMenuBarX::AddMenu: SetMenuItemHierarchicalMenu failed.");
}
}
return NS_OK;
return NS_OK;
}

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

@ -162,7 +162,7 @@ protected:
PRUint32 mNumMenus;
nsSupportsArray mMenusArray; // holds refs
nsCOMPtr<nsIDOMNode> mDOMNode;
nsCOMPtr<nsIContent> mMenuBarContent; // menubar content node, strong ref
nsIWidget* mParent; // weak ref
PRBool mIsMenuBarAdded;

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

@ -35,6 +35,13 @@
#include "nsStringUtil.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsINameSpaceManager.h"
#include "nsWidgetAtoms.h"
#include "nsIServiceManager.h"
#if DEBUG
nsInstanceCounter gMenuItemCounter("nsMenuItem");
@ -66,13 +73,7 @@ nsMenuItem::nsMenuItem()
//
nsMenuItem::~nsMenuItem()
{
//printf("nsMenuItem::~nsMenuItem() called \n");
// if we're a radio menu, we've been registered to get AttributeChanged, so
// make sure we unregister when we go away.
//if (mMenuType == eRadio) {
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
mManager->Unregister(content);
//}
mManager->Unregister(mContent);
#if DEBUG
--gMenuItemCounter;
@ -82,22 +83,19 @@ nsMenuItem::~nsMenuItem()
NS_METHOD nsMenuItem::Create ( nsIMenu* aParent, const nsString & aLabel, PRBool aIsSeparator,
EMenuItemType aItemType, PRBool aEnabled,
nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode )
nsIChangeManager* aManager, nsIWebShell* aShell, nsIContent* aNode )
{
mDOMNode = aNode; // addref
mContent = aNode; // addref
mMenuParent = aParent; // weak
mWebShellWeakRef = getter_AddRefs(NS_GetWeakReference(aShell));
mEnabled = aEnabled;
mMenuType = aItemType;
// if we're a radio menu, register for AttributeChanged messages
// register for AttributeChanged messages
mManager = aManager;
//if ( aItemType == eRadio ) {
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
nsCOMPtr<nsIChangeObserver> obs = do_QueryInterface(NS_STATIC_CAST(nsIChangeObserver*,this));
mManager->Register(content, obs); // does not addref this
//}
nsCOMPtr<nsIChangeObserver> obs = do_QueryInterface(NS_STATIC_CAST(nsIChangeObserver*,this));
mManager->Register(mContent, obs); // does not addref this
mIsSeparator = aIsSeparator;
mLabel = aLabel;
@ -126,8 +124,8 @@ NS_METHOD nsMenuItem::SetChecked(PRBool aIsEnabled)
// update the content model. This will also handle unchecking our siblings
// if we are a radiomenu
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
domElement->SetAttribute(NS_LITERAL_STRING("checked"), mIsChecked ? NS_LITERAL_STRING("true") : NS_LITERAL_STRING("false"));
mContent->SetAttribute(kNameSpaceID_None, nsWidgetAtoms::checked,
mIsChecked ? NS_LITERAL_STRING("true") : NS_LITERAL_STRING("false"), PR_TRUE);
return NS_OK;
}
@ -272,12 +270,9 @@ NS_METHOD nsMenuItem::DoCommand()
nsresult rv = NS_ERROR_FAILURE;
nsCOMPtr<nsIPresContext> presContext;
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
if (!webShell)
{
NS_ERROR("No web shell");
return nsEventStatus_eConsumeNoDefault;
}
MenuHelpers::WebShellToPresContext(webShell, getter_AddRefs(presContext));
nsEventStatus status = nsEventStatus_eIgnore;
@ -285,50 +280,58 @@ NS_METHOD nsMenuItem::DoCommand()
event.eventStructType = NS_MOUSE_EVENT;
event.message = NS_MENU_ACTION;
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(mDOMNode);
if (!contentNode) {
NS_ERROR("DOM Node doesn't support the nsIContent interface required to handle DOM events.");
return rv;
// See if we have a command element. If so, we execute on the command instead
// of on our content element.
nsAutoString command;
mContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::command, command);
if (!command.IsEmpty()) {
nsCOMPtr<nsIDocument> doc;
mContent->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
nsCOMPtr<nsIDOMElement> commandElt;
domDoc->GetElementById(command, getter_AddRefs(commandElt));
nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt));
if (commandContent)
commandContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
}
rv = contentNode->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
else
mContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
return nsEventStatus_eConsumeNoDefault;
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetModifiers(PRUint8 * aModifiers)
{
nsresult res = NS_OK;
*aModifiers = mModifiers;
return res;
nsresult res = NS_OK;
*aModifiers = mModifiers;
return res;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetModifiers(PRUint8 aModifiers)
{
nsresult res = NS_OK;
mModifiers = aModifiers;
return res;
nsresult res = NS_OK;
mModifiers = aModifiers;
return res;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetShortcutChar(const nsString &aText)
{
nsresult res = NS_OK;
mKeyEquivalent = aText;
return res;
nsresult res = NS_OK;
mKeyEquivalent = aText;
return res;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetShortcutChar(nsString &aText)
{
nsresult res = NS_OK;
aText = mKeyEquivalent;
return res;
nsresult res = NS_OK;
aText = mKeyEquivalent;
return res;
}
//
@ -338,39 +341,33 @@ NS_METHOD nsMenuItem::GetShortcutChar(nsString &aText)
// uncheck them all.
//
void
nsMenuItem :: UncheckRadioSiblings(nsIDOMElement* inCheckedElement)
nsMenuItem :: UncheckRadioSiblings ( nsIContent* inCheckedContent )
{
nsCOMPtr<nsIDOMNode> checkedNode = do_QueryInterface(inCheckedElement);
nsAutoString myGroupName;
inCheckedElement->GetAttribute(NS_LITERAL_STRING("name"), myGroupName);
inCheckedContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::name, myGroupName);
if ( ! myGroupName.Length() ) // no groupname, nothing to do
return;
nsCOMPtr<nsIDOMNode> parent;
checkedNode->GetParentNode(getter_AddRefs(parent));
if (!parent )
nsCOMPtr<nsIContent> parent;
inCheckedContent->GetParent(*getter_AddRefs(parent));
if ( !parent )
return;
nsCOMPtr<nsIDOMNode> currSibling;
parent->GetFirstChild(getter_AddRefs(currSibling));
while ( currSibling ) {
// skip this node
if ( currSibling.get() != checkedNode ) {
nsCOMPtr<nsIDOMElement> currElement = do_QueryInterface(currSibling);
if ( !currElement )
break;
// if the current sibling is in the same group, clear it
nsAutoString currGroupName;
currElement->GetAttribute(NS_LITERAL_STRING("name"), currGroupName);
if ( currGroupName == myGroupName )
currElement->SetAttribute(NS_LITERAL_STRING("checked"), NS_LITERAL_STRING("false"));
}
// advance to the next node
nsIDOMNode* next;
currSibling->GetNextSibling(&next);
currSibling = dont_AddRef(next);
// loop over siblings
PRInt32 count;
parent->ChildCount(count);
for ( PRInt32 i = 0; i < count; ++i ) {
nsCOMPtr<nsIContent> sibling;
parent->ChildAt(i, *getter_AddRefs(sibling));
if ( sibling ) {
if ( sibling.get() != inCheckedContent ) { // skip this node
// if the current sibling is in the same group, clear it
nsAutoString currGroupName;
sibling->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::name, currGroupName);
if ( currGroupName == myGroupName )
sibling->SetAttribute(kNameSpaceID_None, nsWidgetAtoms::checked, NS_LITERAL_STRING("false"), PR_TRUE);
}
}
} // for each sibling
} // UncheckRadioSiblings
@ -384,32 +381,24 @@ nsMenuItem :: UncheckRadioSiblings(nsIDOMElement* inCheckedElement)
NS_IMETHODIMP
nsMenuItem :: AttributeChanged ( nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom *aAttribute,
PRInt32 aHint)
{
nsCOMPtr<nsIAtom> checkedAtom = NS_NewAtom("checked");
nsCOMPtr<nsIAtom> disabledAtom = NS_NewAtom("disabled");
nsCOMPtr<nsIAtom> labelAtom = NS_NewAtom("label");
nsCOMPtr<nsIAtom> hiddenAtom = NS_NewAtom("hidden");
nsCOMPtr<nsIAtom> collapsedAtom = NS_NewAtom("collapsed");
if (aAttribute == checkedAtom.get())
{
PRInt32 aHint )
{
if (aAttribute == nsWidgetAtoms::checked) {
// if we're a radio menu, uncheck our sibling radio items. No need to
// do any of this if we're just a normal check menu.
if ( mMenuType == eRadio ) {
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
nsAutoString checked;
domElement->GetAttribute(NS_LITERAL_STRING("checked"), checked);
mContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::checked, checked);
if (checked == NS_LITERAL_STRING("true") )
UncheckRadioSiblings(domElement);
UncheckRadioSiblings(mContent);
}
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
} else if (aAttribute == disabledAtom.get() ||
aAttribute == hiddenAtom.get() ||
aAttribute == collapsedAtom.get() ) {
}
else if (aAttribute == nsWidgetAtoms::disabled || aAttribute == nsWidgetAtoms::hidden ||
aAttribute == nsWidgetAtoms::collapsed ) {
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
}
@ -421,8 +410,7 @@ nsMenuItem :: AttributeChanged ( nsIDocument *aDocument, PRInt32 aNameSpaceID, n
NS_IMETHODIMP
nsMenuItem :: ContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer)
{
{
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
return NS_OK;
@ -432,9 +420,8 @@ nsMenuItem :: ContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32
NS_IMETHODIMP
nsMenuItem :: ContentInserted(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer)
{
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
return NS_OK;
} // ContentInserted
} // ContentInserted

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

@ -54,7 +54,7 @@ public:
// nsIMenuItem Methods
NS_IMETHOD Create ( nsIMenu* aParent, const nsString & aLabel, PRBool aIsSeparator,
EMenuItemType aItemType, PRBool aEnabled,
nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode ) ;
nsIChangeManager* aManager, nsIWebShell* aShell, nsIContent* aNode ) ;
NS_IMETHOD GetLabel(nsString &aText);
NS_IMETHOD SetShortcutChar(const nsString &aText);
NS_IMETHOD GetShortcutChar(nsString &aText);
@ -84,7 +84,7 @@ public:
protected:
void UncheckRadioSiblings ( nsIDOMElement* inCheckedElement ) ;
void UncheckRadioSiblings ( nsIContent* inCheckedElement ) ;
nsString mLabel;
nsString mKeyEquivalent;
@ -96,7 +96,7 @@ protected:
nsCOMPtr<nsIMenuListener> mXULCommandListener;
nsWeakPtr mWebShellWeakRef; // weak ref to webshell
nsCOMPtr<nsIDOMNode> mDOMNode;
nsCOMPtr<nsIContent> mContent;
PRUint8 mModifiers;
PRPackedBool mIsSeparator;

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

@ -32,6 +32,9 @@
#include "nsIWidget.h"
#include "nsIMenuListener.h"
#include "nsDynamicMDEF.h"
#include "nsINameSpaceManager.h"
#include "nsWidgetAtoms.h"
#include "nsIServiceManager.h"
#include "nsStringUtil.h"
@ -66,13 +69,7 @@ nsMenuItemX::nsMenuItemX()
//
nsMenuItemX::~nsMenuItemX()
{
//printf("nsMenuItemX::~nsMenuItemX() called \n");
// if we're a radio menu, we've been registered to get AttributeChanged, so
// make sure we unregister when we go away.
//if (mMenuType == eRadio) {
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
mManager->Unregister(content);
//}
mManager->Unregister(mContent);
#if DEBUG
--gMenuItemCounterX;
@ -82,22 +79,19 @@ nsMenuItemX::~nsMenuItemX()
NS_METHOD nsMenuItemX::Create ( nsIMenu* aParent, const nsString & aLabel, PRBool aIsSeparator,
EMenuItemType aItemType, PRBool aEnabled,
nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode )
nsIChangeManager* aManager, nsIWebShell* aShell, nsIContent* aNode )
{
mDOMNode = aNode; // addref
mContent = aNode; // addref
mMenuParent = aParent; // weak
mWebShellWeakRef = getter_AddRefs(NS_GetWeakReference(aShell));
mEnabled = aEnabled;
mMenuType = aItemType;
// if we're a radio menu, register for AttributeChanged messages
// register for AttributeChanged messages
mManager = aManager;
//if ( aItemType == eRadio ) {
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
nsCOMPtr<nsIChangeObserver> obs = do_QueryInterface(NS_STATIC_CAST(nsIChangeObserver*,this));
mManager->Register(content, obs); // does not addref this
//}
nsCOMPtr<nsIChangeObserver> obs = do_QueryInterface(NS_STATIC_CAST(nsIChangeObserver*,this));
mManager->Register(mContent, obs); // does not addref this
mIsSeparator = aIsSeparator;
mLabel = aLabel;
@ -126,8 +120,8 @@ NS_METHOD nsMenuItemX::SetChecked(PRBool aIsEnabled)
// update the content model. This will also handle unchecking our siblings
// if we are a radiomenu
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
domElement->SetAttribute(NS_LITERAL_STRING("checked"), mIsChecked ? NS_LITERAL_STRING("true") : NS_LITERAL_STRING("false"));
mContent->SetAttribute(kNameSpaceID_None, nsWidgetAtoms::checked,
mIsChecked ? NS_LITERAL_STRING("true") : NS_LITERAL_STRING("false"), PR_TRUE);
return NS_OK;
}
@ -272,29 +266,34 @@ NS_METHOD nsMenuItemX::DoCommand()
nsresult rv = NS_ERROR_FAILURE;
nsCOMPtr<nsIPresContext> presContext;
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
if (!webShell)
{
NS_ERROR("No web shell");
return nsEventStatus_eConsumeNoDefault;
}
MenuHelpersX::WebShellToPresContext(webShell, getter_AddRefs(presContext));
MenuHelpers::WebShellToPresContext(webShell, getter_AddRefs(presContext));
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_MOUSE_EVENT;
event.message = NS_MENU_ACTION;
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(mDOMNode);
if (!contentNode) {
NS_ERROR("DOM Node doesn't support the nsIContent interface required to handle DOM events.");
return rv;
// See if we have a command element. If so, we execute on the command instead
// of on our content element.
nsAutoString command;
mContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::command, command);
if (!command.IsEmpty()) {
nsCOMPtr<nsIDocument> doc;
mContent->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
nsCOMPtr<nsIDOMElement> commandElt;
domDoc->GetElementById(command, getter_AddRefs(commandElt));
nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt));
if (commandContent)
commandContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
}
rv = contentNode->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
else
mContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
return nsEventStatus_eConsumeNoDefault;
}
@ -340,37 +339,31 @@ NS_METHOD nsMenuItemX::GetShortcutChar(nsString &aText)
void
nsMenuItemX :: UncheckRadioSiblings(nsIDOMElement* inCheckedElement)
{
nsCOMPtr<nsIDOMNode> checkedNode = do_QueryInterface(inCheckedElement);
nsAutoString myGroupName;
inCheckedElement->GetAttribute(NS_LITERAL_STRING("name"), myGroupName);
inCheckedContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::name, myGroupName);
if ( ! myGroupName.Length() ) // no groupname, nothing to do
return;
nsCOMPtr<nsIDOMNode> parent;
checkedNode->GetParentNode(getter_AddRefs(parent));
if (!parent )
nsCOMPtr<nsIContent> parent;
inCheckedContent->GetParent(*getter_AddRefs(parent));
if ( !parent )
return;
nsCOMPtr<nsIDOMNode> currSibling;
parent->GetFirstChild(getter_AddRefs(currSibling));
while ( currSibling ) {
// skip this node
if ( currSibling.get() != checkedNode ) {
nsCOMPtr<nsIDOMElement> currElement = do_QueryInterface(currSibling);
if ( !currElement )
break;
// if the current sibling is in the same group, clear it
nsAutoString currGroupName;
currElement->GetAttribute(NS_LITERAL_STRING("name"), currGroupName);
if ( currGroupName == myGroupName )
currElement->SetAttribute(NS_LITERAL_STRING("checked"), NS_LITERAL_STRING("false"));
}
// advance to the next node
nsIDOMNode* next;
currSibling->GetNextSibling(&next);
currSibling = dont_AddRef(next);
// loop over siblings
PRInt32 count;
parent->ChildCount(count);
for ( PRInt32 i = 0; i < count; ++i ) {
nsCOMPtr<nsIContent> sibling;
parent->ChildAt(i, *getter_AddRefs(sibling));
if ( sibling ) {
if ( sibling.get() != inCheckedContent ) { // skip this node
// if the current sibling is in the same group, clear it
nsAutoString currGroupName;
sibling->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::name, currGroupName);
if ( currGroupName == myGroupName )
sibling->SetAttribute(kNameSpaceID_None, nsWidgetAtoms::checked, NS_LITERAL_STRING("false"), PR_TRUE);
}
}
} // for each sibling
} // UncheckRadioSiblings
@ -386,36 +379,28 @@ NS_IMETHODIMP
nsMenuItemX :: AttributeChanged ( nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom *aAttribute,
PRInt32 aHint)
{
nsCOMPtr<nsIAtom> checkedAtom = NS_NewAtom("checked");
nsCOMPtr<nsIAtom> disabledAtom = NS_NewAtom("disabled");
nsCOMPtr<nsIAtom> labelAtom = NS_NewAtom("label");
nsCOMPtr<nsIAtom> hiddenAtom = NS_NewAtom("hidden");
nsCOMPtr<nsIAtom> collapsedAtom = NS_NewAtom("collapsed");
if (aAttribute == checkedAtom.get())
{
if (aAttribute == nsWidgetAtoms::checked) {
// if we're a radio menu, uncheck our sibling radio items. No need to
// do any of this if we're just a normal check menu.
if ( mMenuType == eRadio ) {
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
nsAutoString checked;
domElement->GetAttribute(NS_LITERAL_STRING("checked"), checked);
mContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::checked, checked);
if (checked == NS_LITERAL_STRING("true") )
UncheckRadioSiblings(domElement);
UncheckRadioSiblings(mContent);
}
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
} else if (aAttribute == disabledAtom.get() ||
aAttribute == hiddenAtom.get() ||
aAttribute == collapsedAtom.get() ) {
}
else if (aAttribute == nsWidgetAtoms::disabled || aAttribute == nsWidgetAtoms::hidden ||
aAttribute == nsWidgetAtoms::collapsed ) {
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
}
return NS_OK;
} // AttributeChanged
@ -437,4 +422,4 @@ nsMenuItemX :: ContentInserted(nsIDocument *aDocument, nsIContent *aChild, PRInt
listener->SetRebuild(PR_TRUE);
return NS_OK;
} // ContentInserted
} // ContentInserted

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

@ -54,7 +54,7 @@ public:
// nsIMenuItem Methods
NS_IMETHOD Create ( nsIMenu* aParent, const nsString & aLabel, PRBool aIsSeparator,
EMenuItemType aItemType, PRBool aEnabled,
nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode ) ;
nsIChangeManager* aManager, nsIWebShell* aShell, nsIContent* aNode ) ;
NS_IMETHOD GetLabel(nsString &aText);
NS_IMETHOD SetShortcutChar(const nsString &aText);
NS_IMETHOD GetShortcutChar(nsString &aText);
@ -96,7 +96,7 @@ protected:
nsCOMPtr<nsIMenuListener> mXULCommandListener;
nsWeakPtr mWebShellWeakRef; // weak ref to webshell
nsCOMPtr<nsIDOMNode> mDOMNode;
nsCOMPtr<nsIContent> mContent;
PRUint8 mModifiers;
PRPackedBool mIsSeparator;

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

@ -40,6 +40,11 @@
#include "nsString.h"
#include "nsStringUtil.h"
#include "nsINameSpaceManager.h"
#include "nsWidgetAtoms.h"
#include "nsIXBLService.h"
#include "nsIServiceManager.h"
#include <Appearance.h>
#include <TextUtils.h>
#include <ToolUtils.h>
@ -112,8 +117,7 @@ nsMenuX::~nsMenuX()
::ReleaseMenu(mMacMenuHandle);
// alert the change notifier we don't care no more
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
mManager->Unregister(content);
mManager->Unregister(mMenuContent);
#if DEBUG
--gMenuCounterX;
@ -126,18 +130,17 @@ nsMenuX::~nsMenuX()
//
NS_METHOD
nsMenuX::Create(nsISupports * aParent, const nsAReadableString &aLabel, const nsAReadableString &aAccessKey,
nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode )
nsIChangeManager* aManager, nsIWebShell* aShell, nsIContent* aNode )
{
mWebShellWeakRef = getter_AddRefs(NS_GetWeakReference(aShell));
mDOMNode = aNode; // strong ref
mMenuContent = aNode;
// register this menu to be notified when changes are made to our content object
mManager = aManager; // weak ref
nsCOMPtr<nsIContent> content (do_QueryInterface(aNode));
nsCOMPtr<nsIChangeObserver> changeObs ( do_QueryInterface(NS_STATIC_CAST(nsIChangeObserver*, this)) );
mManager->Register(content, changeObs);
mManager->Register(mMenuContent, changeObs);
NS_ASSERTION ( mDOMNode, "Menu not given a dom node at creation time" );
NS_ASSERTION ( mMenuContent, "Menu not given a dom node at creation time" );
NS_ASSERTION ( mManager, "No change manager given, can't tell content model updates" );
mParent = aParent;
@ -179,27 +182,24 @@ NS_METHOD nsMenuX::SetLabel(const nsAReadableString &aText)
mLabel = aText;
#if !TARGET_CARBON
// Look at the label and figure out if it is the "Help" menu
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
if(domElement) {
nsAutoString menuIDstring;
domElement->GetAttribute(NS_LITERAL_STRING("id"), menuIDstring);
if (menuIDstring == NS_LITERAL_STRING("menu_Help"))
nsAutoString menuIDstring;
mMenuContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::id, menuIDstring);
if(menuIDstring == NS_LITERAL_STRING("menu_Help"))
{
mIsHelpMenu = PR_TRUE;
::HMGetHelpMenuHandle(&mMacMenuHandle);
mMacMenuID = kHMHelpMenuID;
int numHelpItems = ::CountMenuItems(mMacMenuHandle);
if (mHelpMenuOSItemsCount == 0)
mHelpMenuOSItemsCount = numHelpItems;
for (int i=0; i < numHelpItems; ++i)
{
mIsHelpMenu = PR_TRUE;
::HMGetHelpMenuHandle(&mMacMenuHandle);
mMacMenuID = kHMHelpMenuID;
int numHelpItems = ::CountMenuItems(mMacMenuHandle);
if (mHelpMenuOSItemsCount == 0)
mHelpMenuOSItemsCount = numHelpItems;
for (int i=0; i < numHelpItems; ++i)
{
mMenuItemsArray.AppendElement(&gDummyMenuItemX); // owned
}
return NS_OK;
nsDummyMenuItem* dummyItem = new nsDummyMenuItem;
mMenuItemsArray.AppendElement(dummyItem); // owned
}
return NS_OK;
}
#endif
@ -619,8 +619,8 @@ nsEventStatus nsMenuX::MenuDeselected(const nsMenuEvent & aMenuEvent)
nsEventStatus nsMenuX::MenuConstruct(
const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menuNode,
void * aWebShell)
void * /* menuNode */,
void * aWebShell)
{
mConstructed = false;
gConstructingMenu = PR_TRUE;
@ -631,38 +631,30 @@ nsEventStatus nsMenuX::MenuConstruct(
//printf("nsMenuX::MenuConstruct called for %s = %d \n", mLabel.ToNewCString(), mMacMenuHandle);
// Begin menuitem inner loop
// Now get the kids. Retrieve our menupopup child.
nsCOMPtr<nsIDOMNode> menuPopupNode;
GetMenuPopupElement(getter_AddRefs(menuPopupNode));
if (!menuPopupNode)
// Retrieve our menupopup.
nsCOMPtr<nsIContent> menuPopup;
GetMenuPopupContent(getter_AddRefs(menuPopup));
if (!menuPopup)
return nsEventStatus_eIgnore;
// Now get the kids
nsCOMPtr<nsIDOMNode> menuitemNode;
menuPopupNode->GetFirstChild(getter_AddRefs(menuitemNode));
while (menuitemNode)
{
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
if (menuitemElement) {
nsAutoString label;
menuitemElement->GetAttribute(NS_LITERAL_STRING("label"), label);
//printf("label = %s \n", label.ToNewCString());
// Iterate over the kids
PRInt32 count;
menuPopup->ChildCount(count);
for ( PRInt32 i = 0; i < count; ++i ) {
nsCOMPtr<nsIContent> child;
menuPopup->ChildAt(i, *getter_AddRefs(child));
if ( child ) {
// depending on the type, create a menu item, separator, or submenu
nsAutoString menuitemNodeType;
nsAutoString menuitemName;
menuitemElement->GetNodeName(menuitemNodeType);
if (menuitemNodeType == NS_LITERAL_STRING("menuitem"))
LoadMenuItem(this, menuitemElement, menuitemNode, (nsIWebShell*)aWebShell);
else if (menuitemNodeType == NS_LITERAL_STRING("menuseparator"))
nsCOMPtr<nsIAtom> tag;
child->GetTag ( *getter_AddRefs(tag) );
if ( tag == nsWidgetAtoms::menuitem )
LoadMenuItem(this, child);
else if ( tag == nsWidgetAtoms::menuseparator )
AddSeparator();
else if (menuitemNodeType == NS_LITERAL_STRING("menu"))
LoadSubMenu(this, menuitemElement, menuitemNode);
else if ( tag == nsWidgetAtoms::menu )
LoadSubMenu(this, child);
}
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
} // end menu item innner loop
} // for each menu item
gConstructingMenu = PR_FALSE;
mNeedsRebuild = PR_FALSE;
@ -675,59 +667,42 @@ nsEventStatus nsMenuX::MenuConstruct(
nsEventStatus nsMenuX::HelpMenuConstruct(
const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menuNode,
void * /* menuNode */,
void * aWebShell)
{
//printf("nsMenuX::MenuConstruct called for %s = %d \n", mLabel.ToNewCString(), mMacMenuHandle);
// Begin menuitem inner loop
int numHelpItems = ::CountMenuItems(mMacMenuHandle);
for (int i=0; i < numHelpItems; ++i)
{
for (int i=0; i < numHelpItems; ++i) {
mMenuItemsArray.AppendElement(&gDummyMenuItemX);
}
// Now get the kids. Retrieve our menupopup child.
nsCOMPtr<nsIDOMNode> menuPopupNode;
GetMenuPopupElement ( getter_AddRefs(menuPopupNode) );
if (!menuPopupNode)
// Retrieve our menupopup.
nsCOMPtr<nsIContent> menuPopup;
GetMenuPopupContent(getter_AddRefs(menuPopup));
if (!menuPopup)
return nsEventStatus_eIgnore;
// Now get the kids
nsCOMPtr<nsIDOMNode> menuitemNode;
menuPopupNode->GetFirstChild(getter_AddRefs(menuitemNode));
while (menuitemNode)
{
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
if (menuitemElement) {
nsAutoString menuitemNodeType;
nsAutoString menuitemName;
nsAutoString label;
menuitemElement->GetAttribute(NS_LITERAL_STRING("label"), label);
//printf("label = %s \n", label.ToNewCString());
menuitemElement->GetNodeName(menuitemNodeType);
if (menuitemNodeType == NS_LITERAL_STRING("menuitem")) {
// LoadMenuItem
LoadMenuItem(this, menuitemElement, menuitemNode, (nsIWebShell*)aWebShell);
} else if (menuitemNodeType == NS_LITERAL_STRING("menuseparator")) {
// Iterate over the kids
PRInt32 count;
menuPopup->ChildCount(count);
for ( PRInt32 i = 0; i < count; ++i ) {
nsCOMPtr<nsIContent> child;
menuPopup->ChildAt(i, *getter_AddRefs(child));
if ( child ) {
// depending on the type, create a menu item, separator, or submenu
nsCOMPtr<nsIAtom> tag;
child->GetTag ( *getter_AddRefs(tag) );
if ( tag == nsWidgetAtoms::menuitem )
LoadMenuItem(this, child);
else if ( tag == nsWidgetAtoms::menuseparator )
AddSeparator();
} else if (menuitemNodeType == NS_LITERAL_STRING("menu")) {
// Load a submenu
LoadSubMenu(this, menuitemElement, menuitemNode);
}
}
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
} // end menu item innner loop
else if ( tag == nsWidgetAtoms::menu )
LoadSubMenu(this, child);
}
} // for each menu item
//printf(" Done building, mMenuItemVoidArray.Count() = %d \n", mMenuItemVoidArray.Count());
//PreviousMenuStackUnwind(this, mMacMenuHandle);
//PushMenu(this);
return nsEventStatus_eIgnore;
}
@ -747,23 +722,7 @@ nsEventStatus nsMenuX::MenuDestruct(const nsMenuEvent & aMenuEvent)
// Close the node.
mNeedsRebuild = PR_TRUE;
}
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
if(!domElement) {
NS_ERROR("Unable to QI dom element.");
return nsEventStatus_eIgnore;
}
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(domElement);
if (!contentNode) {
NS_ERROR("DOM Node doesn't support the nsIContent interface required to handle DOM events.");
return nsEventStatus_eIgnore;
}
nsCOMPtr<nsIDocument> document;
contentNode->GetDocument(*getter_AddRefs(document));
if(document)
domElement->RemoveAttribute(NS_LITERAL_STRING("open"));
mMenuContent->UnsetAttribute(kNameSpaceID_None, nsWidgetAtoms::open, PR_TRUE);
}
return nsEventStatus_eIgnore;
@ -831,16 +790,17 @@ NS_METHOD nsMenuX::IsHelpMenu(PRBool* aIsHelpMenu)
//-------------------------------------------------------------------------
/**
* Get DOMNode
* Get GetMenuContent
*
*/
NS_METHOD nsMenuX::GetDOMNode(nsIDOMNode ** aMenuNode)
NS_METHOD nsMenu::GetMenuContent(nsIContent ** aMenuContent)
{
NS_ENSURE_ARG_POINTER(aMenuNode);
NS_IF_ADDREF(*aMenuNode = mDOMNode);
NS_ENSURE_ARG_POINTER(aMenuContent);
NS_IF_ADDREF(*aMenuContent = mMenuContent);
return NS_OK;
}
/*
Support for Carbon Menu Manager.
*/
@ -914,46 +874,34 @@ MenuHandle nsMenuX::NSStringNewMenu(short menuID, nsString& menuTitle)
//----------------------------------------
void nsMenuX::LoadMenuItem(
nsIMenu * pParentMenu,
nsIDOMElement * menuitemElement,
nsIDOMNode * menuitemNode,
nsIWebShell * aWebShell)
void nsMenuX::LoadMenuItem( nsIMenu* inParentMenu, nsIContent* inMenuItemContent )
{
nsAutoString disabled;
nsAutoString checked;
nsAutoString type;
nsAutoString menuitemName;
nsAutoString menuitemCmd;
nsAutoString hidden;
if ( !inMenuItemContent )
return;
// if menu should be hidden, bail
menuitemElement->GetAttribute(NS_LITERAL_STRING("hidden"), hidden);
nsAutoString hidden;
inMenuItemContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::hidden, hidden);
if ( hidden == NS_LITERAL_STRING("true") )
return;
menuitemElement->GetAttribute(NS_LITERAL_STRING("disabled"), disabled);
menuitemElement->GetAttribute(NS_LITERAL_STRING("checked"), checked);
menuitemElement->GetAttribute(NS_LITERAL_STRING("type"), type);
menuitemElement->GetAttribute(NS_LITERAL_STRING("label"), menuitemName);
menuitemElement->GetAttribute(NS_LITERAL_STRING("cmd"), menuitemCmd);
// Create nsMenuItem
nsCOMPtr<nsIMenuItem> pnsMenuItem = do_CreateInstance ( kMenuItemCID ) ;
if ( pnsMenuItem ) {
//printf("menuitem %s \n", menuitemName.ToNewCString());
// Create MenuDelegate - this is the intermediator inbetween
// the DOM node and the nsIMenuItem
// The nsWebShellWindow wacthes for Document changes and then notifies the
// the appropriate nsMenuDelegate object
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(menuitemNode));
if (!domElement) {
#if DEBUG_saari
SysBeep(30);
#endif
return;
}
nsAutoString disabled;
nsAutoString checked;
nsAutoString type;
nsAutoString menuitemName;
nsAutoString menuitemCmd;
inMenuItemContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::disabled, disabled);
inMenuItemContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::checked, checked);
inMenuItemContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::type, type);
inMenuItemContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::label, menuitemName);
inMenuItemContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::command, menuitemCmd);
//printf("menuitem %s \n", menuitemName.ToNewCString());
PRBool enabled = ! (disabled == NS_LITERAL_STRING("true"));
nsIMenuItem::EMenuItemType itemType = nsIMenuItem::eRegular;
@ -963,54 +911,42 @@ void nsMenuX::LoadMenuItem(
itemType = nsIMenuItem::eRadio;
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
if (!webShell) {
NS_ERROR("No webshell");
if (!webShell)
return;
}
// Create the item. DO NOT use passed in webshell because of messed up windows dynamic loading
// code.
pnsMenuItem->Create(pParentMenu, menuitemName, PR_FALSE, itemType,
enabled, mManager, webShell, menuitemNode);
// Create the item.
pnsMenuItem->Create(inParentMenu, menuitemName, PR_FALSE, itemType,
enabled, mManager, webShell, inMenuItemContent);
//
// Set key shortcut and modifiers
//
nsAutoString keyAtom; keyAtom.AssignWithConversion("key");
nsAutoString keyValue;
domElement->GetAttribute(keyAtom, keyValue);
inMenuItemContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::key, keyValue);
// Try to find the key node.
// Try to find the key node. Get the document so we can do |GetElementByID|
nsCOMPtr<nsIDocument> document;
nsCOMPtr<nsIContent> content = do_QueryInterface(domElement);
content->GetDocument(*getter_AddRefs(document));
if ( !document ) {
NS_ERROR("Unable to retrieve the document.");
inMenuItemContent->GetDocument(*getter_AddRefs(document));
if ( !document )
return;
}
// Turn the document into a XUL document so we can use getElementById
nsCOMPtr<nsIDOMXULDocument> xulDocument = do_QueryInterface(document);
if ( !xulDocument ) {
NS_ERROR("not XUL!");
if ( !xulDocument )
return;
}
nsCOMPtr<nsIDOMElement> keyElement;
if (!keyValue.IsEmpty())
xulDocument->GetElementById(keyValue, getter_AddRefs(keyElement));
if ( keyElement ) {
nsCOMPtr<nsIContent> keyContent ( do_QueryInterface(keyElement) );
nsAutoString keyChar; keyChar.AssignWithConversion(" ");
nsAutoString keyAtom; keyAtom.AssignWithConversion("key");
keyElement->GetAttribute(keyAtom, keyChar);
keyContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::key, keyChar);
if(keyChar != NS_LITERAL_STRING(" "))
pnsMenuItem->SetShortcutChar(keyChar);
PRUint8 modifiers = knsMenuItemNoModifier;
nsAutoString modifiersStr;
keyElement->GetAttribute(NS_LITERAL_STRING("modifiers"), modifiersStr);
keyContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::modifiers, modifiersStr);
char* str = modifiersStr.ToNewCString();
char* newStr;
char* token = nsCRT::strtok( str, ", ", &newStr );
@ -1033,53 +969,49 @@ void nsMenuX::LoadMenuItem(
pnsMenuItem->SetModifiers ( modifiers );
}
if(checked == NS_LITERAL_STRING("true"))
if ( checked == NS_LITERAL_STRING("true") )
pnsMenuItem->SetChecked(PR_TRUE);
else
pnsMenuItem->SetChecked(PR_FALSE);
nsCOMPtr<nsISupports> supports ( do_QueryInterface(pnsMenuItem) );
pParentMenu->AddItem(supports); // Parent now owns menu item
inParentMenu->AddItem(supports); // Parent now owns menu item
}
}
void
nsMenuX::LoadSubMenu( nsIMenu * pParentMenu, nsIDOMElement * menuElement, nsIDOMNode * menuNode )
nsMenuX::LoadSubMenu( nsIMenu * pParentMenu, nsIContent* inMenuItemContent )
{
// if menu should be hidden, bail
nsAutoString hidden;
menuElement->GetAttribute(NS_LITERAL_STRING("hidden"), hidden);
inMenuItemContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::hidden, hidden);
if ( hidden == NS_LITERAL_STRING("true") )
return;
nsAutoString menuName;
menuElement->GetAttribute(NS_LITERAL_STRING("label"), menuName);
inMenuItemContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::label, menuName);
//printf("Creating Menu [%s] \n", menuName.ToNewCString()); // this leaks
// Create nsMenuX
// Create nsMenu
nsCOMPtr<nsIMenu> pnsMenu ( do_CreateInstance(kMenuCID) );
if (pnsMenu)
{
if (pnsMenu) {
// Call Create
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
if (!webShell) {
NS_ERROR("No web shell");
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
if (!webShell)
return;
}
nsCOMPtr<nsISupports> supports(do_QueryInterface(pParentMenu));
pnsMenu->Create(supports, menuName, NS_LITERAL_STRING(""), mManager, webShell, menuNode);
pnsMenu->Create(supports, menuName, NS_LITERAL_STRING(""), mManager, webShell, inMenuItemContent);
// set if it's enabled or disabled
nsAutoString disabled;
menuElement->GetAttribute(NS_LITERAL_STRING("disabled"), disabled);
inMenuItemContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::disabled, disabled);
if ( disabled == NS_LITERAL_STRING("true") )
pnsMenu->SetEnabled ( PR_FALSE );
else
pnsMenu->SetEnabled ( PR_TRUE );
// Make nsMenuX a child of parent nsMenuX. The parent takes ownership
// Make nsMenu a child of parent nsMenu. The parent takes ownership
nsCOMPtr<nsISupports> supports2 ( do_QueryInterface(pnsMenu) );
pParentMenu->AddItem(supports2);
}
@ -1107,30 +1039,75 @@ nsMenuX::OnCreate()
event.clickCount = 0;
event.widget = nsnull;
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
nsCOMPtr<nsIContent> popupContent;
GetMenuPopupContent(getter_AddRefs(popupContent));
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
if (!webShell) {
NS_ERROR("No web shell");
return PR_FALSE;
}
nsCOMPtr<nsIPresContext> presContext;
MenuHelpersX::WebShellToPresContext(webShell, getter_AddRefs(presContext) );
if ( presContext )
{
MenuHelpers::WebShellToPresContext(webShell, getter_AddRefs(presContext) );
if ( presContext ) {
nsresult rv = NS_OK;
nsCOMPtr<nsIDOMNode> menuPopup;
GetMenuPopupElement(getter_AddRefs(menuPopup));
nsCOMPtr<nsIContent> popupContent ( do_QueryInterface(menuPopup) );
if ( popupContent )
rv = popupContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
else {
nsCOMPtr<nsIContent> me (do_QueryInterface(mDOMNode));
if ( me )
rv = me->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
}
nsIContent* dispatchTo = popupContent ? popupContent : mMenuContent;
rv = dispatchTo->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
if ( NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault )
return PR_FALSE;
}
// the menu is going to show and the oncreate handler has executed. We
// now need to walk our menu items, checking to see if any of them have
// a command attribute. If so, several apptributes must potentially
// be updated.
if (popupContent) {
nsCOMPtr<nsIDocument> doc;
popupContent->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
PRInt32 count;
popupContent->ChildCount(count);
for (PRInt32 i = 0; i < count; i++) {
nsCOMPtr<nsIContent> grandChild;
popupContent->ChildAt(i, *getter_AddRefs(grandChild));
nsCOMPtr<nsIAtom> tag;
grandChild->GetTag(*getter_AddRefs(tag));
if (tag.get() == nsWidgetAtoms::menuitem) {
// See if we have a command attribute.
nsAutoString command;
grandChild->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::command, command);
if (!command.IsEmpty()) {
// We do! Look it up in our document
nsCOMPtr<nsIDOMElement> commandElt;
domDoc->GetElementById(command, getter_AddRefs(commandElt));
nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt));
nsAutoString commandDisabled, menuDisabled;
commandContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::disabled, commandDisabled);
grandChild->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::disabled, menuDisabled);
if (!commandDisabled.Equals(menuDisabled)) {
// The menu's disabled state needs to be updated to match the command.
if (commandDisabled.IsEmpty())
grandChild->UnsetAttribute(kNameSpaceID_None, nsWidgetAtoms::disabled, PR_TRUE);
else grandChild->SetAttribute(kNameSpaceID_None, nsWidgetAtoms::disabled, commandDisabled, PR_TRUE);
}
nsAutoString commandValue, menuValue;
commandContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::label, commandValue);
grandChild->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::label, menuValue);
if (!commandValue.Equals(menuValue)) {
// The menu's label state needs to be updated to match the command.
// Note that (unlike the disabled state) if the command has *no* label, we
// assume the menu is supplying its own.
if (!commandValue.IsEmpty())
grandChild->SetAttribute(kNameSpaceID_None, nsWidgetAtoms::label, commandValue, PR_TRUE);
}
}
}
}
}
return PR_TRUE;
}
@ -1164,21 +1141,15 @@ nsMenuX::OnDestroy()
return PR_FALSE;
}
nsCOMPtr<nsIContent> popupContent;
GetMenuPopupContent(getter_AddRefs(popupContent));
nsCOMPtr<nsIPresContext> presContext;
MenuHelpersX::WebShellToPresContext (webShell, getter_AddRefs(presContext) );
if (presContext )
{
nsresult rv;
nsCOMPtr<nsIDOMNode> menuPopup;
GetMenuPopupElement(getter_AddRefs(menuPopup));
nsCOMPtr<nsIContent> popupContent ( do_QueryInterface(menuPopup) );
if ( popupContent )
rv = popupContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
else {
nsCOMPtr<nsIContent> me ( do_QueryInterface(mDOMNode) );
if ( me )
rv = me->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
}
MenuHelpers::WebShellToPresContext (webShell, getter_AddRefs(presContext) );
if (presContext ) {
nsresult rv = NS_OK;
nsIContent* dispatchTo = popupContent ? popupContent : mMenuContent;
rv = dispatchTo->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
mDestroyHandlerCalled = PR_TRUE;
@ -1190,37 +1161,41 @@ nsMenuX::OnDestroy()
//
// GetMenuPopupElement
// GetMenuPopupContent
//
// Find the |menupopup| child from the node representing this menu. It should be one
// Find the |menupopup| child in the |popup| representing this menu. It should be one
// of a very few children so we won't be iterating over a bazillion menu items to find
// it (so the strcmp won't kill us).
//
void
nsMenuX::GetMenuPopupElement(nsIDOMNode** aResult)
nsMenu::GetMenuPopupContent(nsIContent** aResult)
{
if (!aResult )
return;
*aResult = nsnull;
nsCOMPtr<nsIDOMNode> menuPopupNode;
mDOMNode->GetFirstChild(getter_AddRefs(menuPopupNode));
while (menuPopupNode)
{
nsCOMPtr<nsIDOMElement> menuPopupElement(do_QueryInterface(menuPopupNode));
if (menuPopupElement) {
nsAutoString menuPopupNodeType;
menuPopupElement->GetNodeName(menuPopupNodeType);
if (menuPopupNodeType == NS_LITERAL_STRING("menupopup")) {
*aResult = menuPopupNode.get();
NS_ADDREF(*aResult);
return;
}
nsresult rv;
NS_WITH_SERVICE(nsIXBLService, xblService, "@mozilla.org/xbl;1", &rv);
if ( !xblService )
return;
PRInt32 count;
mMenuContent->ChildCount(count);
for (PRInt32 i = 0; i < count; i++) {
PRInt32 dummy;
nsCOMPtr<nsIContent> child;
mMenuContent->ChildAt(i, *getter_AddRefs(child));
nsCOMPtr<nsIAtom> tag;
xblService->ResolveTag(child, &dummy, getter_AddRefs(tag));
if (tag && tag.get() == nsWidgetAtoms::menupopup) {
*aResult = child.get();
NS_ADDREF(*aResult);
return;
}
nsCOMPtr<nsIDOMNode> oldMenuPopupNode(menuPopupNode);
oldMenuPopupNode->GetNextSibling(getter_AddRefs(menuPopupNode));
}
} // GetMenuPopupElement
} // GetMenuPopupContent
nsresult
@ -1243,16 +1218,13 @@ nsMenuX::GetNextVisibleMenu(nsIMenu** outNextVisibleMenu)
menubarParent->GetMenuAt(i, *getter_AddRefs(thisMenu));
if (!thisMenu) continue;
if (gotThisMenu) // we're looking for the next visible
{
nsCOMPtr<nsIDOMNode> menuNode;
thisMenu->GetDOMNode(getter_AddRefs(menuNode));
nsCOMPtr<nsIDOMElement> menuElement = do_QueryInterface(menuNode);
if (!menuElement) continue;
if (gotThisMenu) { // we're looking for the next visible
nsCOMPtr<nsIContent> menuContent;
thisMenu->GetMenuContent(getter_AddRefs(menuContent));
nsAutoString hiddenValue, collapsedValue;
menuElement->GetAttribute(NS_LITERAL_STRING("hidden"), hiddenValue);
menuElement->GetAttribute(NS_LITERAL_STRING("collapsed"), collapsedValue);
menuContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::hidden, hiddenValue);
menuContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::collapsed, collapsedValue);
if ( hiddenValue != NS_LITERAL_STRING("true") && collapsedValue != NS_LITERAL_STRING("true"))
{
NS_IF_ADDREF(*outNextVisibleMenu = thisMenu);
@ -1260,10 +1232,8 @@ nsMenuX::GetNextVisibleMenu(nsIMenu** outNextVisibleMenu)
}
}
else // we're still looking for this
{
if (thisMenu.get() == (nsIMenu *)this)
{
else { // we're still looking for this
if (thisMenu.get() == (nsIMenu *)this) {
gotThisMenu = PR_TRUE;
thisMenuIndex = i;
}
@ -1288,25 +1258,12 @@ nsMenuX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom
return NS_OK;
// ignore the |open| attribute, which is by far the most common
nsCOMPtr<nsIAtom> openAtom = NS_NewAtom("open");
if ( aAttribute == openAtom.get() )
if ( aAttribute == nsWidgetAtoms::open )
return NS_OK;
nsCOMPtr<nsIAtom> disabledAtom = NS_NewAtom("disabled");
nsCOMPtr<nsIAtom> labelAtom = NS_NewAtom("label");
nsCOMPtr<nsIAtom> hiddenAtom = NS_NewAtom("hidden");
nsCOMPtr<nsIAtom> collapsedAtom = NS_NewAtom("collapsed");
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
if(!domElement) {
NS_ERROR("Unable to QI dom element.");
return NS_OK;
}
nsCOMPtr<nsIMenuBar> menubarParent = do_QueryInterface(mParent);
if (aAttribute == disabledAtom.get()) // disabled
{
if(aAttribute == nsWidgetAtoms::disabled) {
mNeedsRebuild = PR_TRUE;
nsAutoString valueString;
@ -1318,8 +1275,7 @@ nsMenuX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom
::DrawMenuBar();
}
else if (aAttribute == labelAtom.get()) // value
{
else if(aAttribute == nsWidgetAtoms::label) {
mNeedsRebuild = PR_TRUE;
domElement->GetAttribute(NS_LITERAL_STRING("label"), mLabel);
@ -1336,13 +1292,12 @@ nsMenuX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom
::DrawMenuBar();
}
else if(aAttribute == hiddenAtom.get() || aAttribute == collapsedAtom.get()) // hidden of collapsed
{
else if(aAttribute == nsWidgetAtoms::hidden || aAttribute == nsWidgetAtoms::collapsed) {
mNeedsRebuild = PR_TRUE;
nsAutoString hiddenValue, collapsedValue;
domElement->GetAttribute(NS_LITERAL_STRING("hidden"), hiddenValue);
domElement->GetAttribute(NS_LITERAL_STRING("collapsed"), collapsedValue);
mMenuContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::hidden, hiddenValue);
mMenuContent->GetAttribute(kNameSpaceID_None, nsWidgetAtoms::collapsed, collapsedValue);
if (hiddenValue == NS_LITERAL_STRING("true") || collapsedValue == NS_LITERAL_STRING("true")) {
// hide this menu
NS_ASSERTION(PR_FALSE, "nsMenuX::AttributeChanged: WRITE HIDE CODE.");

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

@ -35,7 +35,6 @@
class nsIMenuBar;
class nsIMenuListener;
class nsIDOMElement;
//static PRInt16 mMacMenuIDCount; // use GetUniqueMenuID()
@ -67,7 +66,7 @@ public:
// nsIMenu Methods
NS_IMETHOD Create ( nsISupports * aParent, const nsAReadableString &aLabel, const nsAReadableString &aAccessKey,
nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode ) ;
nsIChangeManager* aManager, nsIWebShell* aShell, nsIContent* aNode ) ;
NS_IMETHOD GetParent(nsISupports *&aParent);
NS_IMETHOD GetLabel(nsString &aText);
NS_IMETHOD SetLabel(const nsAReadableString &aText);
@ -84,7 +83,7 @@ public:
NS_IMETHOD SetNativeData(void* aData);
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD GetDOMNode(nsIDOMNode ** aMenuNode);
NS_IMETHOD GetMenuContent(nsIContent ** aMenuNode);
NS_IMETHOD SetEnabled(PRBool aIsEnabled);
NS_IMETHOD GetEnabled(PRBool* aIsEnabled);
NS_IMETHOD IsHelpMenu(PRBool* aIsEnabled);
@ -97,17 +96,16 @@ protected:
nsresult GetNextVisibleMenu(nsIMenu** outNextVisibleMenu);
// fetch the content node associated with the menupopup item
void GetMenuPopupElement ( nsIDOMNode** aResult ) ;
void GetMenuPopupContent ( nsIContent** aResult ) ;
// fire handlers for oncreate/ondestroy
PRBool OnDestroy() ;
PRBool OnCreate() ;
void LoadMenuItem( nsIMenu * pParentMenu, nsIDOMElement * menuitemElement,
nsIDOMNode * menuitemNode, nsIWebShell * aWebShell);
void LoadSubMenu( nsIMenu * pParentMenu, nsIDOMElement * menuElement, nsIDOMNode * menuNode);
void LoadMenuItem ( nsIMenu* pParentMenu, nsIContent* menuitemContent);
void LoadSubMenu( nsIMenu * pParentMenu, nsIContent* menuitemContent);
nsEventStatus HelpMenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow,
void* menuNode, void* aWebShell);
void* unused, void* aWebShell);
MenuHandle NSStringNewMenu(short menuID, nsString& menuTitle);
@ -121,7 +119,7 @@ protected:
// nsIMenuBar* mMenuBarParent;
nsIChangeManager* mManager; // weak ref, it will outlive us
nsWeakPtr mWebShellWeakRef; // weak ref to webshell
nsCOMPtr<nsIDOMNode> mDOMNode; // strong ref
nsCOMPtr<nsIContent> mMenuContent; // the |menu| tag, strong ref
nsCOMPtr<nsIMenuListener> mListener; // strong ref
// MacSpecific

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

@ -23,6 +23,7 @@
#include "nsToolkit.h"
#include "nsWindow.h"
#include "nsGUIEvent.h"
#include "nsWidgetAtoms.h"
#include <Gestalt.h>
#include <Appearance.h>
@ -161,7 +162,9 @@ nsToolkit::nsToolkit() : mInited(false)
//
//-------------------------------------------------------------------------
nsToolkit::~nsToolkit()
{
{
nsWidgetAtoms::ReleaseAtoms();
/* StopPumping decrements a refcount on gEventQueueHandler; a prelude toward
stopping event handling. This is not something you want to do unless you've
bloody well started event handling and incremented the refcount. That's
@ -185,6 +188,9 @@ NS_IMETHODIMP nsToolkit::Init(PRThread */*aThread*/)
{
if (gEventQueueHandler)
gEventQueueHandler->StartPumping();
nsWidgetAtoms::AddRefAtoms();
mInited = true;
return NS_OK;
}