diff --git a/mozilla/widget/macbuild/widget.mcp b/mozilla/widget/macbuild/widget.mcp index 22ff8de1423..07ddd08820f 100644 Binary files a/mozilla/widget/macbuild/widget.mcp and b/mozilla/widget/macbuild/widget.mcp differ diff --git a/mozilla/widget/macbuild/widgetIDL.mcp b/mozilla/widget/macbuild/widgetIDL.mcp index 09849338ba9..32c481259bb 100644 Binary files a/mozilla/widget/macbuild/widgetIDL.mcp and b/mozilla/widget/macbuild/widgetIDL.mcp differ diff --git a/mozilla/widget/public/nsIMenu.h b/mozilla/widget/public/nsIMenu.h index fb45e35a042..5d535a7b1ba 100644 --- a/mozilla/widget/public/nsIMenu.h +++ b/mozilla/widget/public/nsIMenu.h @@ -33,6 +33,7 @@ class nsIMenuBar; class nsIMenu; class nsIMenuItem; class nsIMenuListener; +class nsIChangeManager; // {35A3DEC1-4992-11d2-8DBA-00609703C14E} #define NS_IMENU_IID \ @@ -52,7 +53,8 @@ class nsIMenu : public nsISupports { * Creates the Menu * */ - NS_IMETHOD Create(nsISupports * aParent, const nsString &aLabel) = 0; + NS_IMETHOD Create ( nsISupports * aParent, const nsString &aLabel, const nsString &aAccessKey, + nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode ) = 0; /** * Get the Menu's Parent @@ -168,29 +170,12 @@ class nsIMenu : public nsISupports { */ NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener) = 0; - /** - * Set DOMNode - * - */ - NS_IMETHOD SetDOMNode(nsIDOMNode * aMenuNode) = 0; - /** * Get DOMNode * */ NS_IMETHOD GetDOMNode(nsIDOMNode ** aMenuNode) = 0; - /** - * Set DOMElement - * - */ - NS_IMETHOD SetDOMElement(nsIDOMElement * aMenuElement) = 0; - - /** - * Set WebShell - * - */ - NS_IMETHOD SetWebShell(nsIWebShell * aWebShell) = 0; }; #endif diff --git a/mozilla/widget/public/nsIMenuItem.h b/mozilla/widget/public/nsIMenuItem.h index 197ed3db22a..32ab8a95fcd 100644 --- a/mozilla/widget/public/nsIMenuItem.h +++ b/mozilla/widget/public/nsIMenuItem.h @@ -30,6 +30,7 @@ #include "nsIWebShell.h" #include "nsIDOMElement.h" + // {7F045771-4BEB-11d2-8DBB-00609703C14E} #define NS_IMENUITEM_IID \ { 0x7f045771, 0x4beb, 0x11d2, \ @@ -39,6 +40,7 @@ class nsIMenu; class nsIPopUpMenu; class nsIWidget; class nsIMenuListener; +class nsIChangeManager; enum { knsMenuItemNoModifier = 0, @@ -62,9 +64,9 @@ class nsIMenuItem : public nsISupports { * Creates the MenuItem * */ - NS_IMETHOD Create(nsISupports * aParent, - const nsString & aLabel, - PRBool isSeparator) = 0; + NS_IMETHOD Create ( nsIMenu* aParent, const nsString & aLabel, PRBool isSeparator, + EMenuItemType aItemType, PRBool aEnabled, + nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode ) = 0; /** * Get the MenuItem label @@ -72,12 +74,6 @@ class nsIMenuItem : public nsISupports { */ NS_IMETHOD GetLabel(nsString &aText) = 0; - /** - * Get the MenuItem label - * - */ - NS_IMETHOD SetLabel(nsString &aText) = 0; - /** * Set the Menu shortcut char * @@ -89,11 +85,6 @@ class nsIMenuItem : public nsISupports { * */ NS_IMETHOD GetShortcutChar(nsString &aText) = 0; - /** - * Sets whether the item is enabled or disabled - * - */ - NS_IMETHOD SetEnabled(PRBool aIsEnabled) = 0; /** * Gets whether the item is enabled or disabled @@ -113,24 +104,12 @@ class nsIMenuItem : public nsISupports { */ NS_IMETHOD GetChecked(PRBool *aIsEnabled) = 0; - /** - * Sets whether the item is a checkbox or radio - * - */ - NS_IMETHOD SetMenuItemType(EMenuItemType aType) = 0; - /** * Gets whether the item is a checkbox or radio * */ NS_IMETHOD GetMenuItemType(EMenuItemType *aType) = 0; - /** - * Gets the MenuItem Command identifier - * - */ - NS_IMETHOD GetCommand(PRUint32 & aCommand) = 0; - /** * Gets the target for MenuItem * @@ -161,25 +140,12 @@ class nsIMenuItem : public nsISupports { */ NS_IMETHOD IsSeparator(PRBool & aIsSep) = 0; - /** - * Sets the JavaScript Command to be invoked when a "gui" event occurs on a source widget - * @param aStrCmd the JS command to be cached for later execution - * @return NS_OK - */ - NS_IMETHOD SetCommand(const nsString & aStrCmd) = 0; - /** * Executes the "cached" JavaScript Command * @return NS_OK if the command was executed properly, otherwise an error code */ NS_IMETHOD DoCommand() = 0; - NS_IMETHOD SetDOMNode(nsIDOMNode * aDOMNode) = 0; - NS_IMETHOD GetDOMNode(nsIDOMNode ** aDOMNode) = 0; - NS_IMETHOD SetDOMElement(nsIDOMElement * aDOMElement) = 0; - NS_IMETHOD GetDOMElement(nsIDOMElement ** aDOMElement) = 0; - NS_IMETHOD SetWebShell(nsIWebShell * aWebShell) = 0; - /** * */ diff --git a/mozilla/widget/src/mac/nsDynamicMDEF.cpp b/mozilla/widget/src/mac/nsDynamicMDEF.cpp index 267760e0262..451bde4c068 100644 --- a/mozilla/widget/src/mac/nsDynamicMDEF.cpp +++ b/mozilla/widget/src/mac/nsDynamicMDEF.cpp @@ -43,7 +43,7 @@ RoutineDescriptorPtr gmdefUPP; nsVoidArray gPreviousMenuHandleStack; nsVoidArray gPreviousMenuStack; // Strong references kept! -nsIMenuBar * gCachedMacMenubar; +nsCOMPtr gPreviousMenuBar; MenuHandle gSizedMenu = nsnull; @@ -333,8 +333,8 @@ void nsBuildMenu(MenuHandle theMenu, PRBool isChild) menubar->GetMenuCount(numMenus); numMenus--; for(PRInt32 i = numMenus; i >= 0; i--) { - nsIMenu * menu = nsnull; - menubar->GetMenuAt(i, menu); + nsCOMPtr menu; + menubar->GetMenuAt(i, *getter_AddRefs(menu)); if(menu) { nsCOMPtr listener(do_QueryInterface(menu)); if(listener) { @@ -343,16 +343,15 @@ void nsBuildMenu(MenuHandle theMenu, PRBool isChild) nsEventStatus status = listener->MenuSelected(mevent); if(status != nsEventStatus_eIgnore) { - nsPostBuild(menu, theMenu, isChild); + nsPostBuild(menu, theMenu, isChild); gPreviousTopLevelMenuHandle = theMenu; gPreviousTopLevelMenu = menu; + gPreviousMenuBar = menubar; - NS_RELEASE(menu); //printf("exit BuildMenu \n"); return; } } - NS_RELEASE(menu); } } } else { @@ -441,6 +440,8 @@ void nsPopMenu(nsIMenu ** aMenu) //------------------------------------------------------------------------------ void nsPreviousMenuStackUnwind(nsIMenu * aMenuJustBuilt, MenuHandle aMenuHandleJustBuilt) { + PRBool shouldReleaseMenubar = PR_FALSE; + //printf("PreviousMenuStackUnwind called \n"); //printf("%d items on gPreviousMenuStack \n", gPreviousMenuStack.Count()); while (gPreviousMenuHandleStack.Count()) { @@ -452,38 +453,42 @@ void nsPreviousMenuStackUnwind(nsIMenu * aMenuJustBuilt, MenuHandle aMenuHandleJ if( menu && menuHandle ) { - if( menuHandle != aMenuHandleJustBuilt ) { - - nsCOMPtr listener(do_QueryInterface(menu)); - if(listener) { - //printf("MenuPop \n"); - - nsMenuEvent mevent; - mevent.message = NS_MENU_SELECTED; - mevent.eventStructType = NS_MENU_EVENT; - mevent.point.x = 0; - mevent.point.y = 0; - mevent.widget = nsnull; - mevent.time = PR_IntervalNow(); - mevent.mCommand = (PRUint32) nsnull; - - // UNDO - listener->MenuDeselected(mevent); - - gPreviousMenuStack.RemoveElementAt(gPreviousMenuStack.Count() - 1); - NS_IF_RELEASE(menu); - - //printf("%d items now on gPreviousMenuStack \n", gPreviousMenuStack.Count()); - gPreviousMenuHandleStack.RemoveElementAt(gPreviousMenuHandleStack.Count() - 1); - - } - } else { - //printf(" gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count()); - //printf(" gPreviousMenuHandleStack.Count() = %d \n", gPreviousMenuHandleStack.Count()); - return; + if( menuHandle != aMenuHandleJustBuilt ) { + nsCOMPtr listener(do_QueryInterface(menu)); + if(listener) { + nsMenuEvent mevent; + mevent.message = NS_MENU_SELECTED; + mevent.eventStructType = NS_MENU_EVENT; + mevent.point.x = 0; + mevent.point.y = 0; + mevent.widget = nsnull; + mevent.time = PR_IntervalNow(); + mevent.mCommand = (PRUint32) nsnull; + + // UNDO + listener->MenuDeselected(mevent); + + gPreviousMenuStack.RemoveElementAt(gPreviousMenuStack.Count() - 1); + NS_IF_RELEASE(menu); + shouldReleaseMenubar = PR_TRUE; + + //printf("%d items now on gPreviousMenuStack \n", gPreviousMenuStack.Count()); + gPreviousMenuHandleStack.RemoveElementAt(gPreviousMenuHandleStack.Count() - 1); + } + } + else { + //printf(" gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count()); + //printf(" gPreviousMenuHandleStack.Count() = %d \n", gPreviousMenuHandleStack.Count()); + return; + } } - } - } + } + + // relinquish hold of the menubar _after_ releasing the menu so it can finish + // unregistering itself. + if ( shouldReleaseMenubar ) + gPreviousMenuBar = nsnull; + //printf(" gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count()); //printf(" gPreviousMenuHandleStack.Count() = %d \n", gPreviousMenuHandleStack.Count()); } diff --git a/mozilla/widget/src/mac/nsMenu.cpp b/mozilla/widget/src/mac/nsMenu.cpp index aac1af8b41c..fc9e629f53f 100644 --- a/mozilla/widget/src/mac/nsMenu.cpp +++ b/mozilla/widget/src/mac/nsMenu.cpp @@ -75,19 +75,19 @@ static NS_DEFINE_CID(kMenuCID, NS_MENU_CID); static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID); //------------------------------------------------------------------------- -NS_IMPL_ISUPPORTS3(nsMenu, nsIMenu, nsIMenuListener, nsIDocumentObserver) +NS_IMPL_ISUPPORTS3(nsMenu, nsIMenu, nsIMenuListener, nsIChangeObserver) + -//------------------------------------------------------------------------- // // nsMenu constructor // -//------------------------------------------------------------------------- -nsMenu::nsMenu() : nsIMenu() +nsMenu::nsMenu() { NS_INIT_REFCNT(); mNumMenuItems = 0; mMenuParent = nsnull; mMenuBarParent = nsnull; + mManager = nsnull; mMacMenuID = 0; mMacMenuHandle = nsnull; @@ -130,35 +130,16 @@ nsMenu::nsMenu() : nsIMenu() } -//------------------------------------------------------------------------- + // // nsMenu destructor // -//------------------------------------------------------------------------- nsMenu::~nsMenu() { //printf("nsMenu::~nsMenu() called \n"); OSErr err; NS_IF_RELEASE(mListener); - - nsCOMPtr docShell(do_QueryInterface(mWebShell)); - - nsCOMPtr cv; - docShell->GetContentViewer(getter_AddRefs(cv)); - if (cv) { - - nsCOMPtr docv(do_QueryInterface(cv)); - if (!docv) - return; - - nsCOMPtr doc; - docv->GetDocument(*getter_AddRefs(doc)); - if (!doc) - return; - - doc->RemoveObserver(NS_STATIC_CAST(nsIDocumentObserver*, this)); - } RemoveAll(); @@ -171,18 +152,37 @@ nsMenu::~nsMenu() ::DeleteMenu(mMacMenuID); } + // alert the change notifier we don't care no more + nsCOMPtr content ( do_QueryInterface(mDOMNode) ); + mManager->Unregister ( content ); + mDOMNode = nsnull; } -//------------------------------------------------------------------------- + // -// Create the proper widget +// Create // -//------------------------------------------------------------------------- -NS_METHOD nsMenu::Create(nsISupports *aParent, const nsString &aLabel) +NS_METHOD +nsMenu :: Create ( nsISupports * aParent, const nsString &aLabel, const nsString &aAccessKey, + nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode ) { - if(aParent) - { + mWebShell = aShell; + mDOMNode = aNode; + mDOMElement = do_QueryInterface ( aNode ); + + // register this menu to be notified when changes are made to our content object + mManager = aManager; + nsCOMPtr content ( do_QueryInterface(aNode) ); + nsCOMPtr changeObs ( do_QueryInterface(NS_STATIC_CAST(nsIChangeObserver*,this)) ); + mManager->Register ( content, changeObs ); + + NS_ASSERTION ( mDOMNode, "Menu not given a dom node at creation time" ); + NS_ASSERTION ( mDOMElement, "Unable to convert from DOMNode to DOMElement" ); + NS_ASSERTION ( mManager, "No change manager given, can't tell content model updates" ); + + // our parent could be either a menu bar (if we're toplevel) or a menu (if we're a submenu) + if ( aParent ) { nsCOMPtr menubar ( do_QueryInterface(aParent) ); if ( menubar ) mMenuBarParent = menubar; @@ -193,6 +193,10 @@ NS_METHOD nsMenu::Create(nsISupports *aParent, const nsString &aLabel) mMenuParent = menu; } } + NS_ASSERTION ( mMenuParent || mMenuBarParent, "Menu parent not a menu bar or menu!" ); + + SetLabel ( aLabel ); + SetAccessKey ( aAccessKey ); return NS_OK; } @@ -200,7 +204,6 @@ NS_METHOD nsMenu::Create(nsISupports *aParent, const nsString &aLabel) //------------------------------------------------------------------------- NS_METHOD nsMenu::GetParent(nsISupports*& aParent) { - aParent = nsnull; if ( mMenuParent ) return mMenuParent->QueryInterface(NS_GET_IID(nsISupports),(void**)&aParent); @@ -842,16 +845,14 @@ nsEventStatus nsMenu::MenuConstruct( menuitemElement->GetAttribute(NS_ConvertASCIItoUCS2("value"), label); //printf("label = %s \n", label.ToNewCString()); + // depending on the type, create a menu item, separator, or submenu menuitemElement->GetNodeName(menuitemNodeType); - if (menuitemNodeType.EqualsWithConversion("menuitem")) { - // LoadMenuItem + if (menuitemNodeType.EqualsWithConversion("menuitem")) LoadMenuItem(this, menuitemElement, menuitemNode, menuIndex, (nsIWebShell*)aWebShell); - } else if (menuitemNodeType.EqualsWithConversion("menuseparator")) { + else if (menuitemNodeType.EqualsWithConversion("menuseparator")) AddSeparator(); - } else if (menuitemNodeType.EqualsWithConversion("menu")) { - // Load a submenu + else if (menuitemNodeType.EqualsWithConversion("menu")) LoadSubMenu(this, menuitemElement, menuitemNode); - } } ++menuIndex; nsCOMPtr oldmenuitemNode(menuitemNode); @@ -1021,16 +1022,6 @@ NS_METHOD nsMenu::IsHelpMenu(PRBool* aIsHelpMenu) return NS_OK; } -//------------------------------------------------------------------------- -/** -* Set DOMNode -* -*/ -NS_METHOD nsMenu::SetDOMNode(nsIDOMNode * aMenuNode) -{ - mDOMNode = aMenuNode; - return NS_OK; -} //------------------------------------------------------------------------- /** @@ -1046,50 +1037,7 @@ NS_METHOD nsMenu::GetDOMNode(nsIDOMNode ** aMenuNode) return NS_OK; } -//------------------------------------------------------------------------- -/** -* Set DOMElement -* -*/ -NS_METHOD nsMenu::SetDOMElement(nsIDOMElement * aMenuElement) -{ - mDOMElement = aMenuElement; - return NS_OK; -} - -//------------------------------------------------------------------------- -/** -* Set WebShell -* -*/ -NS_METHOD nsMenu::SetWebShell(nsIWebShell * aWebShell) -{ - mWebShell = aWebShell; - - // add ourself as a document observer - nsCOMPtr docShell(do_QueryInterface(mWebShell)); - nsCOMPtr cv; - docShell->GetContentViewer(getter_AddRefs(cv)); - if (cv) { - - nsCOMPtr docv(do_QueryInterface(cv)); - if (!docv) - return NS_OK; - - nsCOMPtr doc; - docv->GetDocument(*getter_AddRefs(doc)); - if (!doc) - return NS_OK; - - nsCOMPtr observer = do_QueryInterface(NS_STATIC_CAST(nsIMenu*, this)); - if(observer){ - doc->AddObserver(observer); - } - } - - return NS_OK; -} //------------------------------------------------------------------------- void nsMenu::NSStringSetMenuItemText(MenuHandle macMenuHandle, short menuItem, nsString& menuString) { @@ -1279,10 +1227,8 @@ void nsMenu::LoadMenuItem( menuitemElement->GetAttribute(NS_ConvertASCIItoUCS2("value"), menuitemName); menuitemElement->GetAttribute(NS_ConvertASCIItoUCS2("cmd"), menuitemCmd); // Create nsMenuItem - nsIMenuItem * pnsMenuItem = nsnull; - nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID, nsnull, NS_GET_IID(nsIMenuItem), (void**)&pnsMenuItem); - if (NS_OK == rv) { - pnsMenuItem->Create(pParentMenu, menuitemName, 0); + nsCOMPtr pnsMenuItem = do_CreateInstance ( kMenuItemCID ) ; + if ( pnsMenuItem ) { //printf("menuitem %s \n", menuitemName.ToNewCString()); // Create MenuDelegate - this is the intermediator inbetween @@ -1297,21 +1243,23 @@ void nsMenu::LoadMenuItem( return; } - nsAutoString cmdAtom; cmdAtom.AssignWithConversion("oncommand"); - nsString cmdName; + PRBool enabled = ! (disabled.EqualsWithConversion(NS_STRING_TRUE)); + + nsIMenuItem::EMenuItemType itemType = nsIMenuItem::eRegular; + if ( type.EqualsWithConversion("checkbox") ) + itemType = nsIMenuItem::eCheckbox; + else if ( type.EqualsWithConversion("radio") ) + itemType = nsIMenuItem::eRadio; + + // 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, mWebShell, menuitemNode); - domElement->GetAttribute(cmdAtom, cmdName); - //printf("%s \n", cmdName.ToNewCString()); - - pnsMenuItem->SetCommand(cmdName); - // DO NOT use passed in wehshell because of messed up windows dynamic loading - // code. - pnsMenuItem->SetWebShell(mWebShell); - pnsMenuItem->SetDOMElement(domElement); - pnsMenuItem->SetDOMNode(menuitemNode); - - //NS_ASSERTION(false, "get debugger"); + // // Set key shortcut and modifiers + // + nsAutoString keyAtom; keyAtom.AssignWithConversion("key"); nsString keyValue; domElement->GetAttribute(keyAtom, keyValue); @@ -1319,105 +1267,86 @@ void nsMenu::LoadMenuItem( // Try to find the key node. nsCOMPtr document; nsCOMPtr content = do_QueryInterface(domElement); - if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) { + content->GetDocument(*getter_AddRefs(document)); + if ( !document ) { NS_ERROR("Unable to retrieve the document."); - return; //rv; + return;; } // Turn the document into a XUL document so we can use getElementById nsCOMPtr xulDocument = do_QueryInterface(document); - if (xulDocument == nsnull) { + if ( !xulDocument ) { NS_ERROR("not XUL!"); - return; //NS_ERROR_FAILURE; + return; } nsIDOMElement * keyElement = nsnull; xulDocument->GetElementById(keyValue, &keyElement); - if(keyElement){ - PRUint8 modifiers = knsMenuItemNoModifier; - nsAutoString shiftAtom; shiftAtom.AssignWithConversion("shift"); - nsAutoString altAtom; altAtom.AssignWithConversion("alt"); - nsAutoString commandAtom; commandAtom.AssignWithConversion("command"); - nsString shiftValue; - nsString altValue; - nsString commandValue; - nsString controlValue; - nsString keyChar; keyChar.AssignWithConversion(" "); + if ( keyElement ) { + PRUint8 modifiers = knsMenuItemNoModifier; + nsAutoString shiftAtom; shiftAtom.AssignWithConversion("shift"); + nsAutoString altAtom; altAtom.AssignWithConversion("alt"); + nsAutoString commandAtom; commandAtom.AssignWithConversion("command"); + nsString shiftValue; + nsString altValue; + nsString commandValue; + nsString controlValue; + nsString keyChar; keyChar.AssignWithConversion(" "); - keyElement->GetAttribute(keyAtom, keyChar); - keyElement->GetAttribute(shiftAtom, shiftValue); - keyElement->GetAttribute(altAtom, altValue); - keyElement->GetAttribute(commandAtom, commandValue); + keyElement->GetAttribute(keyAtom, keyChar); + keyElement->GetAttribute(shiftAtom, shiftValue); + keyElement->GetAttribute(altAtom, altValue); + keyElement->GetAttribute(commandAtom, commandValue); nsAutoString xulkey; keyElement->GetAttribute(NS_ConvertASCIItoUCS2("xulkey"), xulkey); if (xulkey.EqualsWithConversion("true")) modifiers |= knsMenuItemCommandModifier; - if(!keyChar.EqualsWithConversion(" ")) - pnsMenuItem->SetShortcutChar(keyChar); - - if(shiftValue.EqualsWithConversion("true")) - modifiers |= knsMenuItemShiftModifier; - - if(altValue.EqualsWithConversion("true")) - modifiers |= knsMenuItemAltModifier; - - if(commandValue.EqualsWithConversion("true")) - modifiers |= knsMenuItemCommandModifier; + if(!keyChar.EqualsWithConversion(" ")) + pnsMenuItem->SetShortcutChar(keyChar); + + if(shiftValue.EqualsWithConversion("true")) + modifiers |= knsMenuItemShiftModifier; - if(controlValue.EqualsWithConversion("true")) - modifiers |= knsMenuItemControlModifier; - - pnsMenuItem->SetModifiers(modifiers); + if(altValue.EqualsWithConversion("true")) + modifiers |= knsMenuItemAltModifier; + + if(commandValue.EqualsWithConversion("true")) + modifiers |= knsMenuItemCommandModifier; + + if(controlValue.EqualsWithConversion("true")) + modifiers |= knsMenuItemControlModifier; + + pnsMenuItem->SetModifiers ( modifiers ); } - if(disabled.EqualsWithConversion(NS_STRING_TRUE)) - pnsMenuItem->SetEnabled(PR_FALSE); - else - pnsMenuItem->SetEnabled(PR_TRUE); - - if(checked.EqualsWithConversion(NS_STRING_TRUE)) + if(checked.EqualsWithConversion(NS_STRING_TRUE)) pnsMenuItem->SetChecked(PR_TRUE); else pnsMenuItem->SetChecked(PR_FALSE); - if(type.EqualsWithConversion("checkbox")) - pnsMenuItem->SetMenuItemType(nsIMenuItem::eCheckbox); - else if ( type.EqualsWithConversion("radio") ) - pnsMenuItem->SetMenuItemType(nsIMenuItem::eRadio); - - nsISupports * supports = nsnull; - pnsMenuItem->QueryInterface(NS_GET_IID(nsISupports), (void**) &supports); - pParentMenu->AddItem(supports); // Parent should now own menu item - NS_RELEASE(supports); + nsCOMPtr supports ( do_QueryInterface(pnsMenuItem) ); + pParentMenu->AddItem(supports); // Parent now owns menu item + } - NS_RELEASE(pnsMenuItem); - } - return; } -//---------------------------------------- -void nsMenu::LoadSubMenu( - nsIMenu * pParentMenu, - nsIDOMElement * menuElement, - nsIDOMNode * menuNode) + +void +nsMenu::LoadSubMenu( nsIMenu * pParentMenu, nsIDOMElement * menuElement, nsIDOMNode * menuNode ) { nsString menuName; menuElement->GetAttribute(NS_ConvertASCIItoUCS2("value"), menuName); //printf("Creating Menu [%s] \n", menuName.ToNewCString()); // this leaks // Create nsMenu - nsCOMPtr pnsMenu; - nsresult rv = nsComponentManager::CreateInstance(kMenuCID, nsnull, NS_GET_IID(nsIMenu), getter_AddRefs(pnsMenu)); + nsCOMPtr pnsMenu ( do_CreateInstance(kMenuCID) ); if ( pnsMenu ) { // Call Create nsCOMPtr supports ( do_QueryInterface(pParentMenu) ); - pnsMenu->Create(supports, menuName); - - // Set nsMenu Name - pnsMenu->SetLabel(menuName); + pnsMenu->Create(supports, menuName, NS_ConvertASCIItoUCS2(""), mManager, mWebShell, menuNode); // set if it's enabled or disabled nsAutoString disabled; @@ -1429,290 +1358,10 @@ void nsMenu::LoadSubMenu( // Make nsMenu a child of parent nsMenu. The parent takes ownership nsCOMPtr supports2 ( do_QueryInterface(pnsMenu) ); - pParentMenu->AddItem(supports2); - - pnsMenu->SetWebShell(mWebShell); - pnsMenu->SetDOMNode(menuNode); - pnsMenu->SetDOMElement(menuElement); - + pParentMenu->AddItem(supports2); } -}/////////////////////////////////////////////////////////////// -// nsIDocumentObserver -// this is needed for menubar changes -/////////////////////////////////////////////////////////////// -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::BeginUpdate( - nsIDocument * aDocument) -{ - return NS_OK; } -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::EndUpdate( - nsIDocument * aDocument) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::BeginLoad( - nsIDocument * aDocument) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::EndLoad( - nsIDocument * aDocument) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::BeginReflow( - nsIDocument * aDocument, - nsIPresShell * aShell) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::EndReflow( - nsIDocument * aDocument, - nsIPresShell * aShell) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::ContentChanged( - nsIDocument * aDocument, - nsIContent * aContent, - nsISupports * aSubContent) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::ContentStatesChanged( - nsIDocument * aDocument, - nsIContent * aContent1, - nsIContent * aContent2) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::AttributeChanged( - nsIDocument * aDocument, - nsIContent * aContent, - PRInt32 aNameSpaceID, - nsIAtom * aAttribute, - PRInt32 aHint) -{ - //printf("AttributeChanged\n"); - - if(gConstructingMenu) - return NS_OK; - nsCOMPtr openAtom = NS_NewAtom("open"); - if(aAttribute != openAtom.get()) { - - nsCOMPtr element(do_QueryInterface(mDOMNode)); - if(!element) { - NS_ERROR("Unable to QI dom element."); - return NS_OK; - } - - nsCOMPtr contentNode; - contentNode = do_QueryInterface(element); - if (!contentNode) { - NS_ERROR("DOM Node doesn't support the nsIContent interface required to handle DOM events."); - return NS_OK; - } - - if(aContent == contentNode.get()){ - nsCOMPtr disabledAtom = NS_NewAtom("disabled"); - nsCOMPtr valueAtom = NS_NewAtom("value"); - nsCOMPtr hiddenAtom = NS_NewAtom("hidden"); - - if(aAttribute == disabledAtom.get()) { - nsCOMPtr element(do_QueryInterface(aContent)); - nsString valueString; - element->GetAttribute(NS_ConvertASCIItoUCS2("disabled"), valueString); - if(valueString.EqualsWithConversion("true")) - SetEnabled(PR_FALSE); - else - SetEnabled(PR_TRUE); - - ::DrawMenuBar(); - } else if(aAttribute == valueAtom.get()) { - nsCOMPtr element(do_QueryInterface(aContent)); - element->GetAttribute(NS_ConvertASCIItoUCS2("value"), mLabel); - ::DeleteMenu(mMacMenuID); - - mMacMenuHandle = NSStringNewMenu(mMacMenuID, mLabel); - - // Replace standard MDEF with our stub MDEF -#if !TARGET_CARBON - if(mMacMenuHandle) { - SInt8 state = ::HGetState((Handle)mMacMenuHandle); - ::HLock((Handle)mMacMenuHandle); - //gSystemMDEFHandle = (**mMacMenuHandle).menuProc; - (**mMacMenuHandle).menuProc = gMDEF; - ::HSetState((Handle)mMacMenuHandle, state); - } - ::InsertMenu(mMacMenuHandle, mMacMenuID+1); - if(mMenuBarParent) { - mMenuBarParent->SetNativeData(::GetMenuBar()); - ::DrawMenuBar(); - } -#endif - } else if(aAttribute == hiddenAtom.get()) { - nsCOMPtr element(do_QueryInterface(aContent)); - nsString valueString; - element->GetAttribute(NS_ConvertASCIItoUCS2("hidden"), valueString); - if(valueString.EqualsWithConversion("true")) { - // hide this menu - ::DeleteMenu(mMacMenuID); - } else { - // show this menu - ::InsertMenu(mMacMenuHandle, mMacMenuID+1); - } - if(mMenuBarParent) { - mMenuBarParent->SetNativeData(::GetMenuBar()); - ::DrawMenuBar(); - } - } - } - } - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::ContentAppended( - nsIDocument * aDocument, - nsIContent * aContainer, - PRInt32 aNewIndexInContainer) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::ContentInserted( - nsIDocument * aDocument, - nsIContent * aContainer, - nsIContent * aChild, - PRInt32 aIndexInContainer) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::ContentReplaced( - nsIDocument * aDocument, - nsIContent * aContainer, - nsIContent * aOldChild, - nsIContent * aNewChild, - PRInt32 aIndexInContainer) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::ContentRemoved( - nsIDocument * aDocument, - nsIContent * aContainer, - nsIContent * aChild, - PRInt32 aIndexInContainer) -{ - if(gConstructingMenu) - return NS_OK; - - nsCOMPtr element(do_QueryInterface(mDOMNode)); - if(!element) { - NS_ERROR("Unable to QI dom element."); - return NS_OK; - } - - nsCOMPtr contentNode; - contentNode = do_QueryInterface(element); - if (!contentNode) { - NS_ERROR("DOM Node doesn't support the nsIContent interface required to handle DOM events."); - return NS_OK; - } - - if(aChild == contentNode.get()) { - if(mMenuParent) { - mMenuParent->RemoveItem(aIndexInContainer); - } else if(mMenuBarParent) { - mMenuBarParent->RemoveMenu(aIndexInContainer); - } - } - - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::StyleSheetAdded( - nsIDocument * aDocument, - nsIStyleSheet * aStyleSheet) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::StyleSheetRemoved( - nsIDocument * aDocument, - nsIStyleSheet * aStyleSheet) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::StyleSheetDisabledStateChanged( - nsIDocument * aDocument, - nsIStyleSheet * aStyleSheet, - PRBool aDisabled) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::StyleRuleChanged( - nsIDocument * aDocument, - nsIStyleSheet * aStyleSheet, - nsIStyleRule * aStyleRule, - PRInt32 aHint) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::StyleRuleAdded( - nsIDocument * aDocument, - nsIStyleSheet * aStyleSheet, - nsIStyleRule * aStyleRule) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::StyleRuleRemoved( - nsIDocument * aDocument, - nsIStyleSheet * aStyleSheet, - nsIStyleRule * aStyleRule) -{ - return NS_OK; -} -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsMenu::DocumentWillBeDestroyed( - nsIDocument * aDocument) -{ - return NS_OK; -} // @@ -1837,6 +1486,102 @@ nsMenu::GetMenuPopupElement(nsIDOMNode** aResult) } // GetMenuPopupElement +#pragma mark - + +// +// nsIChangeObserver +// + + +NS_IMETHODIMP +nsMenu :: AttributeChanged ( nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom *aAttribute, + PRInt32 aHint) +{ + if(gConstructingMenu) + return NS_OK; + + // ignore the |open| attribute, which is by far the most common + nsCOMPtr openAtom = NS_NewAtom("open"); + if ( aAttribute == openAtom.get() ) + return NS_OK; + + nsCOMPtr element(do_QueryInterface(mDOMNode)); + if(!element) { + NS_ERROR("Unable to QI dom element."); + return NS_OK; + } + + nsCOMPtr disabledAtom = NS_NewAtom("disabled"); + nsCOMPtr valueAtom = NS_NewAtom("value"); + nsCOMPtr hiddenAtom = NS_NewAtom("hidden"); + + if(aAttribute == disabledAtom.get()) { + nsString valueString; + mDOMElement->GetAttribute(NS_ConvertASCIItoUCS2("disabled"), valueString); + if(valueString.EqualsWithConversion("true")) + SetEnabled(PR_FALSE); + else + SetEnabled(PR_TRUE); + + ::DrawMenuBar(); + } + else if(aAttribute == valueAtom.get()) { + mDOMElement->GetAttribute(NS_ConvertASCIItoUCS2("value"), mLabel); + ::DeleteMenu(mMacMenuID); + + mMacMenuHandle = NSStringNewMenu(mMacMenuID, mLabel); + + // Replace standard MDEF with our stub MDEF +#if !TARGET_CARBON + if(mMacMenuHandle) { + SInt8 state = ::HGetState((Handle)mMacMenuHandle); + ::HLock((Handle)mMacMenuHandle); + //gSystemMDEFHandle = (**mMacMenuHandle).menuProc; + (**mMacMenuHandle).menuProc = gMDEF; + ::HSetState((Handle)mMacMenuHandle, state); + } + ::InsertMenu(mMacMenuHandle, mMacMenuID+1); + if(mMenuBarParent) { + mMenuBarParent->SetNativeData(::GetMenuBar()); + ::DrawMenuBar(); + } +#endif + } + else if(aAttribute == hiddenAtom.get()) { + nsString valueString; + mDOMElement->GetAttribute(NS_ConvertASCIItoUCS2("hidden"), valueString); + if(valueString.EqualsWithConversion("true")) { + // hide this menu + ::DeleteMenu(mMacMenuID); + } else { + // show this menu + ::InsertMenu(mMacMenuHandle, mMacMenuID+1); + } + if(mMenuBarParent) { + mMenuBarParent->SetNativeData(::GetMenuBar()); + ::DrawMenuBar(); + } + } + + return NS_OK; + +} // AttributeChanged + + +NS_IMETHODIMP +nsMenu :: ContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer) +{ + if(gConstructingMenu) + return NS_OK; + + RemoveItem(aIndexInContainer); + mManager->Unregister ( aChild ); + + return NS_OK; + +} // ContentRemoved + + #pragma mark - diff --git a/mozilla/widget/src/mac/nsMenu.h b/mozilla/widget/src/mac/nsMenu.h index fa75ae0ee1a..56ce9674555 100644 --- a/mozilla/widget/src/mac/nsMenu.h +++ b/mozilla/widget/src/mac/nsMenu.h @@ -23,16 +23,18 @@ #ifndef nsMenu_h__ #define nsMenu_h__ +#include "nsCOMPtr.h" #include "nsIMenu.h" #include "nsVoidArray.h" #include "nsIMenuListener.h" -#include "nsIDocumentObserver.h" +#include "nsIChangeManager.h" #include #include class nsIMenuBar; class nsIMenuListener; +class nsIDOMElement; // temporary hack to get apple menu -- sfraser, approved saari @@ -54,7 +56,7 @@ namespace MenuHelpers } -class nsMenu : public nsIMenu, public nsIMenuListener, public nsIDocumentObserver +class nsMenu : public nsIMenu, public nsIMenuListener, public nsIChangeObserver { public: @@ -62,20 +64,19 @@ public: virtual ~nsMenu(); NS_DECL_ISUPPORTS + NS_DECL_NSICHANGEOBSERVER // nsIMenuListener methods nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent); nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent); nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent); - nsEventStatus MenuConstruct( - const nsMenuEvent & aMenuEvent, - nsIWidget * aParentWindow, - void * menuNode, - void * aWebShell); + nsEventStatus MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow, + void * menuNode, void * aWebShell); nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent); // nsIMenu Methods - NS_IMETHOD Create(nsISupports * aParent, const nsString &aLabel); + NS_IMETHOD Create ( nsISupports * aParent, const nsString &aLabel, const nsString &aAccessKey, + nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode ) ; NS_IMETHOD GetParent(nsISupports *&aParent); NS_IMETHOD GetLabel(nsString &aText); NS_IMETHOD SetLabel(const nsString &aText); @@ -92,10 +93,7 @@ public: NS_IMETHOD SetNativeData(void* aData); NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener); NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener); - NS_IMETHOD SetDOMNode(nsIDOMNode * aMenuNode); NS_IMETHOD GetDOMNode(nsIDOMNode ** aMenuNode); - NS_IMETHOD SetDOMElement(nsIDOMElement * aMenuElement); - NS_IMETHOD SetWebShell(nsIWebShell * aWebShell); NS_IMETHOD SetEnabled(PRBool aIsEnabled); NS_IMETHOD GetEnabled(PRBool* aIsEnabled); NS_IMETHOD IsHelpMenu(PRBool* aIsEnabled); @@ -104,58 +102,6 @@ public: NS_IMETHOD AddMenuItem(nsIMenuItem * aMenuItem); NS_IMETHOD AddMenu(nsIMenu * aMenu); - // nsIDocumentObserver - NS_IMETHOD BeginUpdate(nsIDocument *aDocument); - NS_IMETHOD EndUpdate(nsIDocument *aDocument); - NS_IMETHOD BeginLoad(nsIDocument *aDocument); - NS_IMETHOD EndLoad(nsIDocument *aDocument); - NS_IMETHOD BeginReflow(nsIDocument *aDocument, nsIPresShell* aShell); - NS_IMETHOD EndReflow(nsIDocument *aDocument, nsIPresShell* aShell); - NS_IMETHOD ContentChanged(nsIDocument *aDocument, - nsIContent* aContent, - nsISupports* aSubContent); - NS_IMETHOD ContentStatesChanged(nsIDocument *aDocument, - nsIContent* aContent1, - nsIContent* aContent2); - NS_IMETHOD AttributeChanged(nsIDocument *aDocument, - nsIContent* aContent, - PRInt32 aNameSpaceID, - nsIAtom* aAttribute, - PRInt32 aHint); - NS_IMETHOD ContentAppended(nsIDocument *aDocument, - nsIContent* aContainer, - PRInt32 aNewIndexInContainer); - NS_IMETHOD ContentInserted(nsIDocument *aDocument, - nsIContent* aContainer, - nsIContent* aChild, - PRInt32 aIndexInContainer); - NS_IMETHOD ContentReplaced(nsIDocument *aDocument, - nsIContent* aContainer, - nsIContent* aOldChild, - nsIContent* aNewChild, - PRInt32 aIndexInContainer); - NS_IMETHOD ContentRemoved(nsIDocument *aDocument, - nsIContent* aContainer, - nsIContent* aChild, - PRInt32 aIndexInContainer); - NS_IMETHOD StyleSheetAdded(nsIDocument *aDocument, - nsIStyleSheet* aStyleSheet); - NS_IMETHOD StyleSheetRemoved(nsIDocument *aDocument, - nsIStyleSheet* aStyleSheet); - NS_IMETHOD StyleSheetDisabledStateChanged(nsIDocument *aDocument, - nsIStyleSheet* aStyleSheet, - PRBool aDisabled); - NS_IMETHOD StyleRuleChanged(nsIDocument *aDocument, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - PRInt32 aHint); - NS_IMETHOD StyleRuleAdded(nsIDocument *aDocument, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule); - NS_IMETHOD StyleRuleRemoved(nsIDocument *aDocument, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule); - NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument); // MacSpecific static PRInt16 GetUniqueMenuID() { if (mMacMenuIDCount == 32767) @@ -168,12 +114,13 @@ protected: PRUint32 mNumMenuItems; nsVoidArray mMenuItemVoidArray; - nsIMenu * mMenuParent; + nsIMenu * mMenuParent; // weak, my parent owns me nsIMenuBar * mMenuBarParent; - nsIDOMNode * mDOMNode; - nsIDOMElement * mDOMElement; - nsIWebShell * mWebShell; + nsIDOMNode* mDOMNode; // weak ref, content model outlives us + nsCOMPtr mDOMElement; // for convenience; strong ref to manage the QI + nsIWebShell* mWebShell; + nsIChangeManager* mManager; // weak ref, it will outlive us bool mConstructed; // MacSpecific @@ -193,27 +140,16 @@ protected: PRBool OnDestroy() ; PRBool OnCreate() ; - void LoadMenuItem( - nsIMenu * pParentMenu, - nsIDOMElement * menuitemElement, - nsIDOMNode * menuitemNode, - unsigned short menuitemIndex, - nsIWebShell * aWebShell); - - void LoadSubMenu( - nsIMenu * pParentMenu, - nsIDOMElement * menuElement, - nsIDOMNode * menuNode); - - nsEventStatus HelpMenuConstruct( - const nsMenuEvent & aMenuEvent, - nsIWidget * aParentWindow, - void * menuNode, - void * aWebShell); + void LoadMenuItem( nsIMenu * pParentMenu, nsIDOMElement * menuitemElement, + nsIDOMNode * menuitemNode, unsigned short menuitemIndex, + nsIWebShell * aWebShell); + void LoadSubMenu( nsIMenu * pParentMenu, nsIDOMElement * menuElement, nsIDOMNode * menuNode); + nsEventStatus HelpMenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow, + void* menuNode, void* aWebShell); -void NSStringSetMenuItemText(MenuHandle macMenuHandle, short menuItem, nsString& nsString); -MenuHandle NSStringNewMenu(short menuID, nsString& menuTitle); -MenuHandle NSStringNewChildMenu(short menuID, nsString& menuTitle); + void NSStringSetMenuItemText(MenuHandle macMenuHandle, short menuItem, nsString& nsString); + MenuHandle NSStringNewMenu(short menuID, nsString& menuTitle); + MenuHandle NSStringNewChildMenu(short menuID, nsString& menuTitle); private: diff --git a/mozilla/widget/src/mac/nsMenuBar.cpp b/mozilla/widget/src/mac/nsMenuBar.cpp index 7d7c271b879..167a9e46233 100644 --- a/mozilla/widget/src/mac/nsMenuBar.cpp +++ b/mozilla/widget/src/mac/nsMenuBar.cpp @@ -25,6 +25,7 @@ #include "nsIComponentManager.h" #include "nsIMenu.h" #include "nsIMenuItem.h" +#include "nsIContent.h" #include "nsMenuBar.h" #include "nsDynamicMDEF.h" @@ -34,6 +35,10 @@ #include "nsString.h" #include "nsStringUtil.h" #include "nsIStringBundle.h" +#include "nsIDocument.h" +#include "nsIDocShell.h" +#include "nsIDocumentViewer.h" +#include "nsIDocumentObserver.h" #include "nsIDOMXULDocument.h" @@ -83,23 +88,13 @@ static NS_DEFINE_CID(kMenuBarCID, NS_MENUBAR_CID); static NS_DEFINE_CID(kMenuCID, NS_MENU_CID); static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID); -void InstallDefProc( - short dpPath, - ResType dpType, - short dpID, - Ptr dpAddr); - -//------------------------------------------------------------------------- -NS_IMPL_ISUPPORTS2(nsMenuBar, nsIMenuBar, nsIMenuListener) +void InstallDefProc( short dpPath, ResType dpType, short dpID, Ptr dpAddr); -//------------------------------------------------------------------------- -// -// nsMenuListener interface -// -//------------------------------------------------------------------------- +NS_IMPL_ISUPPORTS4(nsMenuBar, nsIMenuBar, nsIMenuListener, nsIDocumentObserver, nsIChangeManager) -//------------------------------------------------------------------------- -nsEventStatus nsMenuBar::MenuItemSelected(const nsMenuEvent & aMenuEvent) + +nsEventStatus +nsMenuBar::MenuItemSelected(const nsMenuEvent & aMenuEvent) { // Dispatch menu event nsEventStatus eventStatus = nsEventStatus_eIgnore; @@ -118,8 +113,9 @@ nsEventStatus nsMenuBar::MenuItemSelected(const nsMenuEvent & aMenuEvent) return eventStatus; } -//------------------------------------------------------------------------- -nsEventStatus nsMenuBar::MenuSelected(const nsMenuEvent & aMenuEvent) + +nsEventStatus +nsMenuBar::MenuSelected(const nsMenuEvent & aMenuEvent) { // Dispatch event nsEventStatus eventStatus = nsEventStatus_eIgnore; @@ -156,18 +152,47 @@ nsEventStatus nsMenuBar::MenuSelected(const nsMenuEvent & aMenuEvent) return eventStatus; } -//------------------------------------------------------------------------- -nsEventStatus nsMenuBar::MenuDeselected(const nsMenuEvent & aMenuEvent) + +nsEventStatus +nsMenuBar::MenuDeselected(const nsMenuEvent & aMenuEvent) { return nsEventStatus_eIgnore; } -//------------------------------------------------------------------------- -nsEventStatus nsMenuBar::MenuConstruct( - const nsMenuEvent & aMenuEvent, - nsIWidget * aParentWindow, - void * menubarNode, - void * aWebShell) + +// +// RegisterAsDocumentObserver +// +// Name says it all. +// +void +nsMenuBar :: RegisterAsDocumentObserver ( nsIWebShell* inWebShell ) +{ + nsCOMPtr docShell ( do_QueryInterface(inWebShell) ); + nsCOMPtr cv; + docShell->GetContentViewer(getter_AddRefs(cv)); + if (cv) { + + // get the document + nsCOMPtr docv(do_QueryInterface(cv)); + if (!docv) + return; + nsCOMPtr doc; + docv->GetDocument(*getter_AddRefs(doc)); + if (!doc) + return; + + // register ourselves + nsCOMPtr observer ( do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)) ); + doc->AddObserver(observer); + } + +} // RegisterAsDocumentObesrver + + +nsEventStatus +nsMenuBar::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow, + void * menubarNode, void * aWebShell ) { mWebShell = (nsIWebShell*) aWebShell; NS_ADDREF(mWebShell); @@ -246,8 +271,8 @@ nsEventStatus nsMenuBar::MenuConstruct( ::InsertMenu(gLevel5HierMenu, hierMenu); } - nsresult rv; pnsMenuBar->Create(aParentWindow); + RegisterAsDocumentObserver ( mWebShell ); // set pnsMenuBar as a nsMenuListener on aParentWindow nsCOMPtr menuListener; @@ -272,25 +297,14 @@ nsEventStatus nsMenuBar::MenuConstruct( // Don't create the whole menu yet, just add in the top level names - // Create nsMenu - nsIMenu * pnsMenu = nsnull; - rv = nsComponentManager::CreateInstance(kMenuCID, nsnull, NS_GET_IID(nsIMenu), (void**)&pnsMenu); - if (NS_OK == rv) { - // Call Create - nsISupports * supports = nsnull; - pnsMenuBar->QueryInterface(NS_GET_IID(nsISupports), (void**) &supports); - pnsMenu->Create(supports, menuName); - NS_RELEASE(supports); + // Create nsMenu, the menubar will own it + nsCOMPtr pnsMenu ( do_CreateInstance(kMenuCID) ); + if ( pnsMenu ) { + nsCOMPtr supports ( do_QueryInterface(pnsMenuBar) ); + nsCOMPtr manager ( do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)) ); + pnsMenu->Create(supports, menuName, menuAccessKey, manager, + NS_REINTERPRET_CAST(nsIWebShell*, aWebShell), menuNode); - // Set JavaScript execution parameters - pnsMenu->SetDOMNode(menuNode); - pnsMenu->SetDOMElement(menuElement); - pnsMenu->SetWebShell((nsIWebShell*)aWebShell); - - // Set nsMenu Name - pnsMenu->SetLabel(menuName); - // Set the access key - pnsMenu->SetAccessKey(menuAccessKey); // Make nsMenu a child of nsMenuBar. nsMenuBar takes ownership pnsMenuBar->AddMenu(pnsMenu); @@ -305,10 +319,7 @@ nsEventStatus nsMenuBar::MenuConstruct( event.mCommand = (unsigned int) handle; nsCOMPtr listener(do_QueryInterface(pnsMenu)); listener->MenuSelected(event); - } - - // Release the menu now that the menubar owns it - NS_RELEASE(pnsMenu); + } } } } @@ -328,18 +339,18 @@ nsEventStatus nsMenuBar::MenuConstruct( return nsEventStatus_eIgnore; } -//------------------------------------------------------------------------- -nsEventStatus nsMenuBar::MenuDestruct(const nsMenuEvent & aMenuEvent) + +nsEventStatus +nsMenuBar::MenuDestruct(const nsMenuEvent & aMenuEvent) { return nsEventStatus_eIgnore; } -//------------------------------------------------------------------------- + // // nsMenuBar constructor // -//------------------------------------------------------------------------- -nsMenuBar::nsMenuBar() : nsIMenuBar(), nsIMenuListener() +nsMenuBar :: nsMenuBar() { gCurrentMenuDepth = 1; #if !TARGET_CARBON @@ -375,12 +386,11 @@ nsMenuBar::nsMenuBar() : nsIMenuBar(), nsIMenuListener() NS_ASSERTION(err==noErr,"nsMenu::nsMenu: CreateUnicodeToTextRunInfoByScriptCode failed."); } -//------------------------------------------------------------------------- + // // nsMenuBar destructor // -//------------------------------------------------------------------------- -nsMenuBar::~nsMenuBar() +nsMenuBar :: ~nsMenuBar() { //NS_IF_RELEASE(mParent); @@ -393,11 +403,11 @@ nsMenuBar::~nsMenuBar() OSErr err = ::DisposeUnicodeToTextRunInfo(&mUnicodeTextRunConverter); NS_ASSERTION(err==noErr,"nsMenu::~nsMenu: DisposeUnicodeToTextRunInfo failed."); - ::SetMenuBar(mOriginalMacMBarHandle); ::DisposeHandle(mMacMBarHandle); ::DisposeHandle(mOriginalMacMBarHandle); } + //------------------------------------------------------------------------- // // Create the proper widget @@ -503,8 +513,10 @@ NS_METHOD nsMenuBar::AddMenu(nsIMenu * aMenu) return NS_OK; } -//------------------------------------------------------------------------- -void nsMenuBar::NSStringSetMenuItemText(MenuHandle macMenuHandle, short menuItem, nsString& menuString) + + +void +nsMenuBar::NSStringSetMenuItemText(MenuHandle macMenuHandle, short menuItem, nsString& menuString) { OSErr err; const PRUnichar* unicodeText; @@ -671,3 +683,205 @@ void InstallDefProc( HLockHi((Handle)jH); } + + +#pragma mark - + +// +// nsIDocumentObserver +// this is needed for menubar changes +// + + +NS_IMETHODIMP +nsMenuBar::BeginUpdate( nsIDocument * aDocument ) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::EndUpdate( nsIDocument * aDocument ) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::BeginLoad( nsIDocument * aDocument ) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::EndLoad( nsIDocument * aDocument ) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::BeginReflow( nsIDocument * aDocument, nsIPresShell * aShell) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::EndReflow( nsIDocument * aDocument, nsIPresShell * aShell) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::ContentChanged( nsIDocument * aDocument, nsIContent * aContent, nsISupports * aSubContent) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::ContentStatesChanged( nsIDocument * aDocument, nsIContent * aContent1, nsIContent * aContent2) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::ContentAppended( nsIDocument * aDocument, nsIContent * aContainer, + PRInt32 aNewIndexInContainer) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::ContentInserted( nsIDocument * aDocument, nsIContent * aContainer, + nsIContent * aChild, PRInt32 aIndexInContainer) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::ContentReplaced( nsIDocument * aDocument, nsIContent * aContainer, nsIContent * aOldChild, + nsIContent * aNewChild, PRInt32 aIndexInContainer) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::StyleSheetAdded( nsIDocument * aDocument, nsIStyleSheet * aStyleSheet) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::StyleSheetRemoved(nsIDocument * aDocument, nsIStyleSheet * aStyleSheet) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::StyleSheetDisabledStateChanged(nsIDocument * aDocument, nsIStyleSheet * aStyleSheet, + PRBool aDisabled) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::StyleRuleChanged( nsIDocument * aDocument, nsIStyleSheet * aStyleSheet, + nsIStyleRule * aStyleRule, PRInt32 aHint) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::StyleRuleAdded( nsIDocument * aDocument, nsIStyleSheet * aStyleSheet, + nsIStyleRule * aStyleRule) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::StyleRuleRemoved(nsIDocument * aDocument, nsIStyleSheet * aStyleSheet, + nsIStyleRule * aStyleRule) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::DocumentWillBeDestroyed( nsIDocument * aDocument ) +{ + return NS_OK; +} + + +NS_IMETHODIMP +nsMenuBar::AttributeChanged( nsIDocument * aDocument, nsIContent * aContent, PRInt32 aNameSpaceID, + nsIAtom * aAttribute, PRInt32 aHint) +{ + // lookup and dispatch to registered thang. + nsCOMPtr obs; + Lookup ( aContent, getter_AddRefs(obs) ); + if ( obs ) + obs->AttributeChanged ( aDocument, aNameSpaceID, aAttribute, aHint ); + + return NS_OK; +} + +NS_IMETHODIMP +nsMenuBar::ContentRemoved( nsIDocument * aDocument, nsIContent * aContainer, + nsIContent * aChild, PRInt32 aIndexInContainer ) +{ + nsCOMPtr me ( do_QueryInterface(mDOMNode) ); + if ( aContainer == me.get() ) { + Unregister(aChild); + RemoveMenu ( aIndexInContainer ); + } + else { + nsCOMPtr obs; + Lookup ( aContainer, getter_AddRefs(obs) ); + if ( obs ) + obs->ContentRemoved ( aDocument, aChild, aIndexInContainer ); + } + return NS_OK; +} + + +#pragma mark - + +// +// nsIChangeManager +// +// We don't use a |nsSupportsHashtable| because we know that the lifetime of all these items +// is bouded by the lifetime of the menubar. No need to add any more strong refs to the +// picture because the containment hierarchy already uses strong refs. +// + +NS_IMETHODIMP +nsMenuBar :: Register ( nsIContent *aContent, nsIChangeObserver *aMenuObject ) +{ + nsVoidKey key ( aContent ); + mObserverTable.Put ( &key, aMenuObject ); + + return NS_OK; +} + + +NS_IMETHODIMP +nsMenuBar :: Unregister ( nsIContent *aContent ) +{ + nsVoidKey key ( aContent ); + mObserverTable.Remove ( &key ); + + return NS_OK; +} + + +NS_IMETHODIMP +nsMenuBar :: Lookup ( nsIContent *aContent, nsIChangeObserver **_retval ) +{ + *_retval = nsnull; + + nsVoidKey key ( aContent ); + *_retval = NS_REINTERPRET_CAST(nsIChangeObserver*, mObserverTable.Get(&key)); + NS_IF_ADDREF ( *_retval ); + + return NS_OK; +} + + + diff --git a/mozilla/widget/src/mac/nsMenuBar.h b/mozilla/widget/src/mac/nsMenuBar.h index f3b7749e941..e56fb4e3574 100644 --- a/mozilla/widget/src/mac/nsMenuBar.h +++ b/mozilla/widget/src/mac/nsMenuBar.h @@ -25,7 +25,10 @@ #include "nsIMenuBar.h" #include "nsIMenuListener.h" +#include "nsIDocumentObserver.h" +#include "nsIChangeManager.h" #include "nsVoidArray.h" +#include "nsHashtable.h" #include "Types.h" #include @@ -38,26 +41,77 @@ class nsIWidget; * Native Mac MenuBar wrapper */ -class nsMenuBar : public nsIMenuBar, public nsIMenuListener +class nsMenuBar : public nsIMenuBar, public nsIMenuListener, public nsIDocumentObserver, + public nsIChangeManager { - public: + + nsMenuBar(); + virtual ~nsMenuBar(); + NS_DECL_ISUPPORTS + NS_DECL_NSICHANGEMANAGER // nsIMenuListener interface nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent); nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent); nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent); - nsEventStatus MenuConstruct( - const nsMenuEvent & aMenuEvent, - nsIWidget * aParentWindow, - void * menuNode, - void * aWebShell); + nsEventStatus MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow, + void * menuNode, void * aWebShell); nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent); - - nsMenuBar(); - virtual ~nsMenuBar(); + // nsIDocumentObserver + NS_IMETHOD BeginUpdate(nsIDocument *aDocument); + NS_IMETHOD EndUpdate(nsIDocument *aDocument); + NS_IMETHOD BeginLoad(nsIDocument *aDocument); + NS_IMETHOD EndLoad(nsIDocument *aDocument); + NS_IMETHOD BeginReflow(nsIDocument *aDocument, nsIPresShell* aShell); + NS_IMETHOD EndReflow(nsIDocument *aDocument, nsIPresShell* aShell); + NS_IMETHOD ContentChanged(nsIDocument *aDocument, + nsIContent* aContent, + nsISupports* aSubContent); + NS_IMETHOD ContentStatesChanged(nsIDocument *aDocument, + nsIContent* aContent1, + nsIContent* aContent2); + NS_IMETHOD AttributeChanged(nsIDocument *aDocument, + nsIContent* aContent, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aHint); + NS_IMETHOD ContentAppended(nsIDocument *aDocument, + nsIContent* aContainer, + PRInt32 aNewIndexInContainer); + NS_IMETHOD ContentInserted(nsIDocument *aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer); + NS_IMETHOD ContentReplaced(nsIDocument *aDocument, + nsIContent* aContainer, + nsIContent* aOldChild, + nsIContent* aNewChild, + PRInt32 aIndexInContainer); + NS_IMETHOD ContentRemoved(nsIDocument *aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer); + NS_IMETHOD StyleSheetAdded(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet); + NS_IMETHOD StyleSheetRemoved(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet); + NS_IMETHOD StyleSheetDisabledStateChanged(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet, + PRBool aDisabled); + NS_IMETHOD StyleRuleChanged(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet, + nsIStyleRule* aStyleRule, + PRInt32 aHint); + NS_IMETHOD StyleRuleAdded(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet, + nsIStyleRule* aStyleRule); + NS_IMETHOD StyleRuleRemoved(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet, + nsIStyleRule* aStyleRule); + NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument); NS_IMETHOD Create(nsIWidget * aParent); @@ -73,7 +127,11 @@ public: NS_IMETHOD GetNativeData(void*& aData); NS_IMETHOD Paint(); NS_IMETHOD SetNativeData(void* aData); + protected: + + nsHashtable mObserverTable; // stores observers for content change notification + PRUint32 mNumMenus; nsVoidArray mMenuVoidArray; nsIWidget * mParent; @@ -83,6 +141,8 @@ protected: nsIWebShell * mWebShell; nsIDOMNode * mDOMNode; + void RegisterAsDocumentObserver ( nsIWebShell* inWebShell ) ; + // Mac Specific Handle mMacMBarHandle; Handle mOriginalMacMBarHandle; diff --git a/mozilla/widget/src/mac/nsMenuItem.cpp b/mozilla/widget/src/mac/nsMenuItem.cpp index 7a6074ba2aa..87735c7feda 100644 --- a/mozilla/widget/src/mac/nsMenuItem.cpp +++ b/mozilla/widget/src/mac/nsMenuItem.cpp @@ -29,31 +29,24 @@ #include "nsMenuItem.h" #include "nsIMenu.h" #include "nsIMenuBar.h" -#include "nsIPopUpMenu.h" #include "nsIWidget.h" #include "nsIMenuListener.h" #include "nsStringUtil.h" -//------------------------------------------------------------------------- -NS_IMPL_ISUPPORTS2(nsMenuItem, nsIMenuItem, nsIMenuListener) +NS_IMPL_ISUPPORTS3(nsMenuItem, nsIMenuItem, nsIMenuListener, nsIChangeObserver) + -//------------------------------------------------------------------------- // // nsMenuItem constructor // -//------------------------------------------------------------------------- -nsMenuItem::nsMenuItem() : nsIMenuItem() +nsMenuItem::nsMenuItem() { NS_INIT_REFCNT(); - //mMenu = nsnull; mMenuParent = nsnull; - mPopUpParent = nsnull; mTarget = nsnull; - mXULCommandListener = nsnull; mIsSeparator = PR_FALSE; mWebShell = nsnull; - mDOMElement = nsnull; mDOMNode = nsnull; mKeyEquivalent.AssignWithConversion(" "); mEnabled = PR_TRUE; @@ -61,96 +54,70 @@ nsMenuItem::nsMenuItem() : nsIMenuItem() mMenuType = eRegular; } -//------------------------------------------------------------------------- // // nsMenuItem destructor // -//------------------------------------------------------------------------- nsMenuItem::~nsMenuItem() { //printf("nsMenuItem::~nsMenuItem() called \n"); NS_IF_RELEASE(mTarget); - NS_IF_RELEASE(mXULCommandListener); + + // 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 content ( do_QueryInterface(mDOMNode) ); + mManager->Unregister ( content ); + } } -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::Create(nsISupports *aParent, - const nsString &aLabel, - PRBool aIsSeparator) - +NS_METHOD nsMenuItem::Create ( nsIMenu* aParent, const nsString & aLabel, PRBool aIsSeparator, + EMenuItemType aItemType, PRBool aEnabled, + nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode ) { - mIsSeparator = aIsSeparator; - SetLabel(NS_CONST_CAST(nsString&, aLabel)); - return NS_OK; -} - -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::Create(nsIPopUpMenu *aParent, - const nsString &aLabel, - PRUint32 aCommand) -{ - mPopUpParent = aParent; - if ( mPopUpParent ) { - - nsIWidget * widget = nsnull; - - mPopUpParent->AddItem(this); + mDOMNode = aNode; + mDOMElement = do_QueryInterface ( aNode ); + mMenuParent = aParent; + mWebShell = aShell; + + mEnabled = aEnabled; + mMenuType = aItemType; + + // if we're a radio menu, register for AttributeChanged messages + mManager = aManager; + if ( aItemType == eRadio ) { + nsCOMPtr content ( do_QueryInterface(mDOMNode) ); + nsCOMPtr obs ( do_QueryInterface(NS_STATIC_CAST(nsIChangeObserver*,this)) ); + mManager->Register ( content, obs ); } + mIsSeparator = aIsSeparator; + mLabel = aLabel; return NS_OK; } -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::Create(nsIMenu * aParent) -{ - mIsSeparator = PR_TRUE; - return NS_OK; -} - -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::Create(nsIPopUpMenu * aParent) -{ - mIsSeparator = PR_TRUE; - return NS_OK; -} - -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::GetLabel(nsString &aText) +NS_METHOD +nsMenuItem::GetLabel(nsString &aText) { aText = mLabel; return NS_OK; } -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::SetLabel(nsString &aText) -{ - mLabel = aText; - return NS_OK; -} -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::SetEnabled(PRBool aIsEnabled) -{ - mEnabled = aIsEnabled; - return NS_OK; -} - -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::GetEnabled(PRBool *aIsEnabled) +NS_METHOD +nsMenuItem::GetEnabled(PRBool *aIsEnabled) { *aIsEnabled = mEnabled; return NS_OK; } -//------------------------------------------------------------------------- + NS_METHOD nsMenuItem::SetChecked(PRBool aIsEnabled) { mIsChecked = aIsEnabled; - if(mIsChecked) - mDOMElement->SetAttribute(NS_ConvertASCIItoUCS2("checked"), NS_ConvertASCIItoUCS2("true")); - else - mDOMElement->SetAttribute(NS_ConvertASCIItoUCS2("checked"), NS_ConvertASCIItoUCS2("false")); + if ( mMenuType == eRadio && aIsEnabled ) + UncheckRadioSiblings ( mDOMElement ); + return NS_OK; } @@ -161,12 +128,6 @@ NS_METHOD nsMenuItem::GetChecked(PRBool *aIsEnabled) return NS_OK; } -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::SetMenuItemType(EMenuItemType aType) -{ - mMenuType = aType; - return NS_OK; -} //------------------------------------------------------------------------- NS_METHOD nsMenuItem::GetMenuItemType(EMenuItemType *aType) @@ -175,12 +136,6 @@ NS_METHOD nsMenuItem::GetMenuItemType(EMenuItemType *aType) return NS_OK; } -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::GetCommand(PRUint32 & aCommand) -{ - aCommand = mCommand; - return NS_OK; -} //------------------------------------------------------------------------- NS_METHOD nsMenuItem::GetTarget(nsIWidget *& aTarget) @@ -199,8 +154,6 @@ NS_METHOD nsMenuItem::GetNativeData(void *& aData) //------------------------------------------------------------------------- NS_METHOD nsMenuItem::AddMenuListener(nsIMenuListener * aMenuListener) { - NS_IF_RELEASE(mXULCommandListener); - NS_IF_ADDREF(aMenuListener); mXULCommandListener = aMenuListener; return NS_OK; } @@ -218,6 +171,7 @@ NS_METHOD nsMenuItem::IsSeparator(PRBool & aIsSep) return NS_OK; } + //------------------------------------------------------------------------- // nsIMenuListener interface //------------------------------------------------------------------------- @@ -231,43 +185,11 @@ nsEventStatus nsMenuItem::MenuItemSelected(const nsMenuEvent & aMenuEvent) case eRadio: { // we only want to muck with things if we were selected and we're not - // already checked. + // already checked. if ( mIsChecked ) break; SetChecked(PR_TRUE); - - // walk the sibling list looking for nodes with the same name and - // uncheck them all. - - nsAutoString myGroupName; - mDOMElement->GetAttribute(NS_ConvertASCIItoUCS2("name"), myGroupName); - - nsCOMPtr parent; - mDOMNode->GetParentNode(getter_AddRefs(parent)); - if ( !parent ) - break; - nsCOMPtr currSibling; - parent->GetFirstChild(getter_AddRefs(currSibling)); - while ( currSibling ) { - // skip this node - if ( currSibling.get() != mDOMNode ) { - nsCOMPtr currElement = do_QueryInterface(currSibling); - if ( !currElement ) - break; - - // if the current sibling is in the same group, clear it - nsAutoString currGroupName; - currElement->GetAttribute(NS_ConvertASCIItoUCS2("name"), currGroupName); - if ( currGroupName == myGroupName ) - currElement->SetAttribute(NS_ConvertASCIItoUCS2("checked"), NS_ConvertASCIItoUCS2("false")); - } - - // advance to the next node - nsIDOMNode* next; - currSibling->GetNextSibling(&next); - currSibling = dont_AddRef(next); - - } // for each sibling + UncheckRadioSiblings(mDOMElement); break; } @@ -314,16 +236,6 @@ nsEventStatus nsMenuItem::MenuDestruct(const nsMenuEvent & aMenuEvent) return nsEventStatus_eIgnore; } -//------------------------------------------------------------------------- -/** -* Sets the JavaScript Command to be invoked when a "gui" event occurs on a source widget -* @param aStrCmd the JS command to be cached for later execution -* @return NS_OK -*/ -NS_METHOD nsMenuItem::SetCommand(const nsString & aStrCmd) -{ - return NS_OK; -} //------------------------------------------------------------------------- /** @@ -360,41 +272,7 @@ NS_METHOD nsMenuItem::DoCommand() return nsEventStatus_eConsumeNoDefault; } - -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::SetDOMNode(nsIDOMNode * aDOMNode) -{ - mDOMNode = aDOMNode; - NS_ADDREF(mDOMNode); - return NS_OK; -} -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::GetDOMNode(nsIDOMNode ** aDOMNode) -{ - *aDOMNode = mDOMNode; - return NS_OK; -} - -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::SetDOMElement(nsIDOMElement * aDOMElement) -{ - mDOMElement = aDOMElement; - return NS_OK; -} - -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::GetDOMElement(nsIDOMElement ** aDOMElement) -{ - return NS_OK; -} - -//------------------------------------------------------------------------- -NS_METHOD nsMenuItem::SetWebShell(nsIWebShell * aWebShell) -{ - mWebShell = aWebShell; - return NS_OK; -} //------------------------------------------------------------------------- NS_METHOD nsMenuItem::GetModifiers(PRUint8 * aModifiers) @@ -428,3 +306,77 @@ NS_METHOD nsMenuItem::GetShortcutChar(nsString &aText) aText = mKeyEquivalent; return res; } + +// +// UncheckRadioSiblings +// +// walk the sibling list looking for nodes with the same name and +// uncheck them all. +// +void +nsMenuItem :: UncheckRadioSiblings ( nsIDOMElement* inCheckedElement ) +{ + nsCOMPtr checkedNode ( do_QueryInterface(inCheckedElement) ); + + nsAutoString myGroupName; + inCheckedElement->GetAttribute(NS_ConvertASCIItoUCS2("name"), myGroupName); + + nsCOMPtr parent; + checkedNode->GetParentNode(getter_AddRefs(parent)); + if ( !parent ) + return; + nsCOMPtr currSibling; + parent->GetFirstChild(getter_AddRefs(currSibling)); + while ( currSibling ) { + // skip this node + if ( currSibling.get() != checkedNode ) { + nsCOMPtr currElement = do_QueryInterface(currSibling); + if ( !currElement ) + break; + + // if the current sibling is in the same group, clear it + nsAutoString currGroupName; + currElement->GetAttribute(NS_ConvertASCIItoUCS2("name"), currGroupName); + if ( currGroupName == myGroupName ) + currElement->SetAttribute(NS_ConvertASCIItoUCS2("checked"), NS_ConvertASCIItoUCS2("false")); + } + + // advance to the next node + nsIDOMNode* next; + currSibling->GetNextSibling(&next); + currSibling = dont_AddRef(next); + + } // for each sibling + +} // UncheckRadioSiblings + +#pragma mark - + +// +// nsIChangeObserver +// + + +NS_IMETHODIMP +nsMenuItem :: AttributeChanged ( nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom *aAttribute, + PRInt32 aHint) +{ + nsCOMPtr checkedAtom = NS_NewAtom("checked"); + nsAutoString checked; + if ( aAttribute == checkedAtom.get() ) { + mDOMElement->GetAttribute(NS_ConvertASCIItoUCS2("checked"), checked); + if ( checked.EqualsWithConversion("true") ) + UncheckRadioSiblings ( mDOMElement ); + } + return NS_OK; + +} // AttributeChanged + + +NS_IMETHODIMP +nsMenuItem :: ContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer) +{ + return NS_OK; + +} // ContentRemoved + diff --git a/mozilla/widget/src/mac/nsMenuItem.h b/mozilla/widget/src/mac/nsMenuItem.h index 432612eb01a..4f606e3cba2 100644 --- a/mozilla/widget/src/mac/nsMenuItem.h +++ b/mozilla/widget/src/mac/nsMenuItem.h @@ -27,53 +27,44 @@ #include "nsIMenuItem.h" #include "nsString.h" #include "nsIMenuListener.h" +#include "nsIChangeManager.h" + class nsIMenu; -class nsIPopUpMenu; class nsIWidget; /** * Native Motif MenuItem wrapper */ -class nsMenuItem : public nsIMenuItem, public nsIMenuListener +class nsMenuItem : public nsIMenuItem, public nsIMenuListener, public nsIChangeObserver { - public: nsMenuItem(); virtual ~nsMenuItem(); // nsISupports NS_DECL_ISUPPORTS + NS_DECL_NSICHANGEOBSERVER // nsIMenuItem Methods - NS_IMETHOD Create(nsISupports *aParent, - const nsString &aLabel, - PRBool aIsSeparator); + NS_IMETHOD Create ( nsIMenu* aParent, const nsString & aLabel, PRBool aIsSeparator, + EMenuItemType aItemType, PRBool aEnabled, + nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode ) ; NS_IMETHOD GetLabel(nsString &aText); - NS_IMETHOD SetLabel(nsString &aText); NS_IMETHOD SetShortcutChar(const nsString &aText); NS_IMETHOD GetShortcutChar(nsString &aText); - NS_IMETHOD SetEnabled(PRBool aIsEnabled); NS_IMETHOD GetEnabled(PRBool *aIsEnabled); NS_IMETHOD SetChecked(PRBool aIsEnabled); NS_IMETHOD GetChecked(PRBool *aIsEnabled); - NS_IMETHOD SetMenuItemType(EMenuItemType aIsCheckbox); NS_IMETHOD GetMenuItemType(EMenuItemType *aIsCheckbox); - NS_IMETHOD GetCommand(PRUint32 & aCommand); NS_IMETHOD GetTarget(nsIWidget *& aTarget); NS_IMETHOD GetNativeData(void*& aData); NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener); NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener); NS_IMETHOD IsSeparator(PRBool & aIsSep); - NS_IMETHOD SetCommand(const nsString & aStrCmd); NS_IMETHOD DoCommand(); - NS_IMETHOD SetDOMNode(nsIDOMNode * aDOMNode); - NS_IMETHOD GetDOMNode(nsIDOMNode ** aDOMNode); - NS_IMETHOD SetDOMElement(nsIDOMElement * aDOMElement); - NS_IMETHOD GetDOMElement(nsIDOMElement ** aDOMElement); - NS_IMETHOD SetWebShell(nsIWebShell * aWebShell); NS_IMETHOD SetModifiers(PRUint8 aModifiers); NS_IMETHOD GetModifiers(PRUint8 * aModifiers); @@ -81,36 +72,28 @@ public: nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent); nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent); nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent); - nsEventStatus MenuConstruct( - const nsMenuEvent & aMenuEvent, - nsIWidget * aParentWindow, - void * menuNode, - void * aWebShell); + nsEventStatus MenuConstruct(const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow, + void * menuNode, void * aWebShell); nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent); - + protected: - NS_IMETHOD Create(nsIPopUpMenu *aParent, - const nsString &aLabel, - PRUint32 aCommand) ; - NS_IMETHOD Create(nsIMenu * aParent); - NS_IMETHOD Create(nsIPopUpMenu * aParent); - - nsString mLabel; - nsString mKeyEquivalent; - PRUint32 mCommand; + void UncheckRadioSiblings ( nsIDOMElement* inCheckedElement ) ; - nsIMenu * mMenuParent; - nsIPopUpMenu * mPopUpParent; + nsAutoString mLabel; + nsAutoString mKeyEquivalent; + + nsIMenu * mMenuParent; // weak, parent owns us nsIWidget * mTarget; - nsIMenuListener * mXULCommandListener; + nsCOMPtr mXULCommandListener; PRBool mIsSeparator; nsIMenuListener * mListener; - nsIWebShell * mWebShell; - nsIDOMElement * mDOMElement; - nsIDOMNode * mDOMNode; + nsIWebShell* mWebShell; // weak, document outlives us + nsCOMPtr mDOMElement; // for convenience; strong to manage QI + nsIDOMNode* mDOMNode; // weak, content outlives us + nsIChangeManager* mManager; // weak, manager outlives us PRUint8 mModifiers; PRBool mEnabled; diff --git a/mozilla/widget/src/mac/nsWidgetFactory.cpp b/mozilla/widget/src/mac/nsWidgetFactory.cpp index 24cdb6d8ae7..5677857261a 100644 --- a/mozilla/widget/src/mac/nsWidgetFactory.cpp +++ b/mozilla/widget/src/mac/nsWidgetFactory.cpp @@ -40,7 +40,6 @@ #include "nsMenuBar.h" #include "nsMenu.h" #include "nsMenuItem.h" -#include "nsContextMenu.h" #include "nsClipboard.h" #include "nsTransferable.h" @@ -87,7 +86,6 @@ static NS_DEFINE_CID(kCLabel, NS_LABEL_CID); static NS_DEFINE_CID(kCMenuBar, NS_MENUBAR_CID); static NS_DEFINE_CID(kCMenu, NS_MENU_CID); static NS_DEFINE_CID(kCMenuItem, NS_MENUITEM_CID); -static NS_DEFINE_CID(kCContextMenu, NS_CONTEXTMENU_CID); static NS_DEFINE_CID(kCPopUpMenu, NS_POPUPMENU_CID); // Drag and Drop/Clipboard @@ -236,9 +234,6 @@ nsresult nsWidgetFactory::CreateInstance(nsISupports *aOuter, else if (mClassID.Equals(kCMenuItem)) { inst = (nsISupports*)(nsIMenuItem*) new nsMenuItem(); } - else if (mClassID.Equals(kCContextMenu)) { - inst = (nsISupports*)(nsIContextMenu*) new nsContextMenu(); - } else if (mClassID.Equals(kCPopUpMenu)) { // inst = (nsISupports*)new nsPopUpMenu(); NS_NOTYETIMPLEMENTED("nsPopUpMenu");