fixes for bug 31104 (radio menus not updating when poked in content model). involved making only the menubar be a document observer (which increased performance on mac) and passing attributeChanged messages to menuItems that cared. r=saari.

git-svn-id: svn://10.0.0.236/trunk@70881 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
pinkerton%netscape.com
2000-05-26 00:15:33 +00:00
parent c2c3b849eb
commit c8df49db6a
12 changed files with 745 additions and 904 deletions

Binary file not shown.

View File

@@ -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

View File

@@ -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;
/**
*
*/

View File

@@ -43,7 +43,7 @@ RoutineDescriptorPtr gmdefUPP;
nsVoidArray gPreviousMenuHandleStack;
nsVoidArray gPreviousMenuStack; // Strong references kept!
nsIMenuBar * gCachedMacMenubar;
nsCOMPtr<nsIMenuBar> 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<nsIMenu> menu;
menubar->GetMenuAt(i, *getter_AddRefs(menu));
if(menu) {
nsCOMPtr<nsIMenuListener> 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<nsIMenuListener> 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<nsIMenuListener> 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());
}

View File

@@ -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<nsIDocShell> docShell(do_QueryInterface(mWebShell));
nsCOMPtr<nsIContentViewer> cv;
docShell->GetContentViewer(getter_AddRefs(cv));
if (cv) {
nsCOMPtr<nsIDocumentViewer> docv(do_QueryInterface(cv));
if (!docv)
return;
nsCOMPtr<nsIDocument> 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<nsIContent> 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<nsIContent> content ( do_QueryInterface(aNode) );
nsCOMPtr<nsIChangeObserver> 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<nsIMenuBar> 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<nsIDOMNode> 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<nsIDocShell> docShell(do_QueryInterface(mWebShell));
nsCOMPtr<nsIContentViewer> cv;
docShell->GetContentViewer(getter_AddRefs(cv));
if (cv) {
nsCOMPtr<nsIDocumentViewer> docv(do_QueryInterface(cv));
if (!docv)
return NS_OK;
nsCOMPtr<nsIDocument> doc;
docv->GetDocument(*getter_AddRefs(doc));
if (!doc)
return NS_OK;
nsCOMPtr<nsIDocumentObserver> 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<nsIMenuItem> 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<nsIDocument> document;
nsCOMPtr<nsIContent> 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<nsIDOMXULDocument> 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<nsISupports> 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<nsIMenu> pnsMenu;
nsresult rv = nsComponentManager::CreateInstance(kMenuCID, nsnull, NS_GET_IID(nsIMenu), getter_AddRefs(pnsMenu));
nsCOMPtr<nsIMenu> pnsMenu ( do_CreateInstance(kMenuCID) );
if ( pnsMenu ) {
// Call Create
nsCOMPtr<nsISupports> 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<nsISupports> 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<nsIAtom> openAtom = NS_NewAtom("open");
if(aAttribute != openAtom.get()) {
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
if(!element) {
NS_ERROR("Unable to QI dom element.");
return NS_OK;
}
nsCOMPtr<nsIContent> 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<nsIAtom> disabledAtom = NS_NewAtom("disabled");
nsCOMPtr<nsIAtom> valueAtom = NS_NewAtom("value");
nsCOMPtr<nsIAtom> hiddenAtom = NS_NewAtom("hidden");
if(aAttribute == disabledAtom.get()) {
nsCOMPtr<nsIDOMElement> 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<nsIDOMElement> 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<nsIDOMElement> 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<nsIDOMElement> element(do_QueryInterface(mDOMNode));
if(!element) {
NS_ERROR("Unable to QI dom element.");
return NS_OK;
}
nsCOMPtr<nsIContent> 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<nsIAtom> openAtom = NS_NewAtom("open");
if ( aAttribute == openAtom.get() )
return NS_OK;
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
if(!element) {
NS_ERROR("Unable to QI dom element.");
return NS_OK;
}
nsCOMPtr<nsIAtom> disabledAtom = NS_NewAtom("disabled");
nsCOMPtr<nsIAtom> valueAtom = NS_NewAtom("value");
nsCOMPtr<nsIAtom> 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 -

View File

@@ -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 <Menus.h>
#include <UnicodeConverter.h>
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<nsIDOMElement> 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:

View File

@@ -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<nsIDocShell> docShell ( do_QueryInterface(inWebShell) );
nsCOMPtr<nsIContentViewer> cv;
docShell->GetContentViewer(getter_AddRefs(cv));
if (cv) {
// get the document
nsCOMPtr<nsIDocumentViewer> docv(do_QueryInterface(cv));
if (!docv)
return;
nsCOMPtr<nsIDocument> doc;
docv->GetDocument(*getter_AddRefs(doc));
if (!doc)
return;
// register ourselves
nsCOMPtr<nsIDocumentObserver> 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<nsIMenuListener> 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<nsIMenu> pnsMenu ( do_CreateInstance(kMenuCID) );
if ( pnsMenu ) {
nsCOMPtr<nsISupports> supports ( do_QueryInterface(pnsMenuBar) );
nsCOMPtr<nsIChangeManager> 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<nsIMenuListener> 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<nsIChangeObserver> 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<nsIContent> me ( do_QueryInterface(mDOMNode) );
if ( aContainer == me.get() ) {
Unregister(aChild);
RemoveMenu ( aIndexInContainer );
}
else {
nsCOMPtr<nsIChangeObserver> 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;
}

View File

@@ -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 <UnicodeConverter.h>
@@ -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;

View File

@@ -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<nsIContent> 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<nsIContent> content ( do_QueryInterface(mDOMNode) );
nsCOMPtr<nsIChangeObserver> 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<nsIDOMNode> parent;
mDOMNode->GetParentNode(getter_AddRefs(parent));
if ( !parent )
break;
nsCOMPtr<nsIDOMNode> currSibling;
parent->GetFirstChild(getter_AddRefs(currSibling));
while ( currSibling ) {
// skip this node
if ( currSibling.get() != mDOMNode ) {
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_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<nsIDOMNode> checkedNode ( do_QueryInterface(inCheckedElement) );
nsAutoString myGroupName;
inCheckedElement->GetAttribute(NS_ConvertASCIItoUCS2("name"), myGroupName);
nsCOMPtr<nsIDOMNode> parent;
checkedNode->GetParentNode(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_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<nsIAtom> 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

View File

@@ -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<nsIMenuListener> mXULCommandListener;
PRBool mIsSeparator;
nsIMenuListener * mListener;
nsIWebShell * mWebShell;
nsIDOMElement * mDOMElement;
nsIDOMNode * mDOMNode;
nsIWebShell* mWebShell; // weak, document outlives us
nsCOMPtr<nsIDOMElement> mDOMElement; // for convenience; strong to manage QI
nsIDOMNode* mDOMNode; // weak, content outlives us
nsIChangeManager* mManager; // weak, manager outlives us
PRUint8 mModifiers;
PRBool mEnabled;

View File

@@ -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");