actively update native menu items based on command node content instead of menu item node content. makes menu blinking work when using keyboard commands. also, remove some old native help menu code. b=50590 r=mento sr=pinkerton

This commit is contained in:
joshmoz%gmail.com 2006-07-10 17:50:30 +00:00
Родитель 4a36cac75e
Коммит 43de00d5af
9 изменённых файлов: 199 добавлений и 178 удалений

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

@ -51,10 +51,10 @@ class nsIContent;
class nsIMenuCommandDispatcher;
// {ab6cea83-00ff-11d5-bb6f-f432a43ead7c}
// {D0E18BEA-A0B9-4D33-899E-283A4D753F2C}
#define NS_IMENU_IID \
{ 0xab6cea83, 0x00ff, 0x11d5, \
{ 0xbb, 0x6f, 0xf4, 0x32, 0xa4, 0x3e, 0xad, 0x7c } }
{ 0xD0E18BEA, 0xA0B9, 0x4D33, \
{ 0x89, 0x9E, 0x28, 0x3A, 0x4D, 0x75, 0x3F, 0x2C } }
/**
@ -114,12 +114,6 @@ class nsIMenu : public nsISupports {
*/
NS_IMETHOD GetEnabled(PRBool* aIsEnabled) = 0;
/**
* Query if this is the help menu. Mostly for MacOS voodoo.
*
*/
NS_IMETHOD IsHelpMenu(PRBool* aIsHelpMenu) = 0;
/**
* Adds a Menu Item
*
@ -192,6 +186,12 @@ class nsIMenu : public nsISupports {
*/
NS_IMETHOD GetMenuContent(nsIContent ** aMenuContent) = 0;
/**
* Enable/disable native widget for a particular nsIMenuItem
*
*/
NS_IMETHOD ChangeNativeEnabledStatusForMenuItem(nsIMenuItem* aMenuItem,
PRBool aEnabled) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIMenu, NS_IMENU_IID)

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

@ -111,10 +111,10 @@ public:
NS_IMETHOD GetMenuContent(nsIContent ** aMenuNode);
NS_IMETHOD SetEnabled(PRBool aIsEnabled);
NS_IMETHOD GetEnabled(PRBool* aIsEnabled);
NS_IMETHOD IsHelpMenu(PRBool* aIsEnabled);
NS_IMETHOD AddMenuItem(nsIMenuItem * aMenuItem);
NS_IMETHOD AddMenu(nsIMenu * aMenu);
NS_IMETHOD ChangeNativeEnabledStatusForMenuItem(nsIMenuItem* aMenuItem, PRBool aEnabled);
protected:
// Determines how many menus are visible among the siblings that are before me.

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

@ -544,17 +544,6 @@ NS_IMETHODIMP nsMenuX::GetEnabled(PRBool* aIsEnabled)
}
// This is only here because it implements a pure virtual function
// that exists to support Carbon widgets. It can be removed when
// Carbon widgets are dead for real.
NS_IMETHODIMP nsMenuX::IsHelpMenu(PRBool* aIsHelpMenu)
{
NS_ENSURE_ARG_POINTER(aIsHelpMenu);
*aIsHelpMenu = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP nsMenuX::GetMenuContent(nsIContent ** aMenuContent)
{
NS_ENSURE_ARG_POINTER(aMenuContent);
@ -660,8 +649,7 @@ void nsMenuX::LoadMenuItem(nsIMenu* inParentMenu, nsIContent* inMenuItemContent)
}
void
nsMenuX::LoadSubMenu(nsIMenu * pParentMenu, nsIContent* inMenuItemContent)
void nsMenuX::LoadSubMenu(nsIMenu * pParentMenu, nsIContent* inMenuItemContent)
{
// if menu should be hidden, bail
if (inMenuItemContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::hidden,
@ -696,8 +684,7 @@ nsMenuX::LoadSubMenu(nsIMenu * pParentMenu, nsIContent* inMenuItemContent)
}
void
nsMenuX::LoadSeparator(nsIContent* inMenuItemContent)
void nsMenuX::LoadSeparator(nsIContent* inMenuItemContent)
{
// if item should be hidden, bail
if (inMenuItemContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::hidden,
@ -708,15 +695,13 @@ nsMenuX::LoadSeparator(nsIContent* inMenuItemContent)
}
//
// OnCreate
//
// Fire our oncreate handler. Returns TRUE if we should keep processing the event,
// FALSE if the handler wants to stop the creation of the menu
//
PRBool
nsMenuX::OnCreate()
PRBool nsMenuX::OnCreate()
{
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(PR_TRUE, NS_XUL_POPUP_SHOWING, nsnull,
@ -796,8 +781,8 @@ nsMenuX::OnCreate()
return PR_TRUE;
}
PRBool
nsMenuX::OnCreated()
PRBool nsMenuX::OnCreated()
{
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(PR_TRUE, NS_XUL_POPUP_SHOWN, nsnull, nsMouseEvent::eReal);
@ -820,14 +805,14 @@ nsMenuX::OnCreated()
return PR_TRUE;
}
//
// OnDestroy
//
// Fire our ondestroy handler. Returns TRUE if we should keep processing the event,
// FALSE if the handler wants to stop the destruction of the menu
//
PRBool
nsMenuX::OnDestroy()
PRBool nsMenuX::OnDestroy()
{
if (mDestroyHandlerCalled)
return PR_TRUE;
@ -857,8 +842,8 @@ nsMenuX::OnDestroy()
return PR_TRUE;
}
PRBool
nsMenuX::OnDestroyed()
PRBool nsMenuX::OnDestroyed()
{
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(PR_TRUE, NS_XUL_POPUP_HIDDEN, nsnull,
@ -884,6 +869,8 @@ nsMenuX::OnDestroyed()
return PR_TRUE;
}
//
// GetMenuPopupContent
//
@ -891,8 +878,7 @@ nsMenuX::OnDestroyed()
// of a very few children so we won't be iterating over a bazillion menu items to find
// it (so the strcmp won't kill us).
//
void
nsMenuX::GetMenuPopupContent(nsIContent** aResult)
void nsMenuX::GetMenuPopupContent(nsIContent** aResult)
{
if (!aResult)
return;
@ -927,8 +913,7 @@ nsMenuX::GetMenuPopupContent(nsIContent** aResult)
// It doesn't matter if I am visible. Note that this will always count the
// Application menu, since we always put it in there.
//
nsresult
nsMenuX::CountVisibleBefore(PRUint32* outVisibleBefore)
nsresult nsMenuX::CountVisibleBefore(PRUint32* outVisibleBefore)
{
NS_ASSERTION(outVisibleBefore, "bad index param");
@ -974,13 +959,20 @@ nsMenuX::CountVisibleBefore(PRUint32* outVisibleBefore)
} // CountVisibleBefore
NS_IMETHODIMP nsMenuX::ChangeNativeEnabledStatusForMenuItem(nsIMenuItem* aMenuItem,
PRBool aEnabled)
{
return NS_OK;
}
//
// nsIChangeObserver
//
NS_IMETHODIMP
nsMenuX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIContent *aContent, nsIAtom *aAttribute)
NS_IMETHODIMP nsMenuX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID,
nsIContent *aContent, nsIAtom *aAttribute)
{
// ignore the |open| attribute, which is by far the most common
if (gConstructingMenu || (aAttribute == nsWidgetAtoms::open))
@ -1076,8 +1068,8 @@ nsMenuX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIConte
} // AttributeChanged
NS_IMETHODIMP
nsMenuX::ContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer)
NS_IMETHODIMP nsMenuX::ContentRemoved(nsIDocument *aDocument, nsIContent *aChild,
PRInt32 aIndexInContainer)
{
if (gConstructingMenu)
return NS_OK;
@ -1091,8 +1083,8 @@ nsMenuX::ContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aInd
} // ContentRemoved
NS_IMETHODIMP
nsMenuX::ContentInserted(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer)
NS_IMETHODIMP nsMenuX::ContentInserted(nsIDocument *aDocument, nsIContent *aChild,
PRInt32 aIndexInContainer)
{
if (gConstructingMenu)
return NS_OK;
@ -1107,6 +1099,7 @@ nsMenuX::ContentInserted(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIn
// Carbon event support
//
static pascal OSStatus MyMenuEventHandler(EventHandlerCallRef myHandler, EventRef event, void* userData)
{
UInt32 kind = ::GetEventKind(event);
@ -1160,6 +1153,7 @@ static pascal OSStatus MyMenuEventHandler(EventHandlerCallRef myHandler, EventRe
return eventNotHandledErr;
}
static OSStatus InstallMyMenuEventHandler(MenuRef menuRef, void* userData, EventHandlerRef* outHandler)
{
static EventTypeSpec eventList[] = {

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

@ -55,8 +55,10 @@ interface nsIDocument;
[scriptable, uuid(d8cf3bd0-1dd1-11b2-a837-fec5f865b071)]
interface nsIChangeObserver : nsISupports
{
void AttributeChanged ( in nsIDocument aDocument,
in long aNameSpaceID, in nsIAtom aAttribute ) ;
void AttributeChanged(in nsIDocument aDocument,
in long aNameSpaceID,
in nsIContent aContent,
in nsIAtom aAttribute);
void ContentRemoved ( in nsIDocument aDocument, in nsIContent aChild,
in long aIndexInContainer ) ;

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

@ -521,22 +521,18 @@ NS_METHOD nsMenuBarX::AddMenu(nsIMenu * aMenu)
MenuRef menuRef = nsnull;
aMenu->GetNativeData((void**)&menuRef);
PRBool helpMenu;
aMenu->IsHelpMenu(&helpMenu);
if(!helpMenu) {
nsCOMPtr<nsIContent> menu;
aMenu->GetMenuContent(getter_AddRefs(menu));
if(!menu->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::hidden,
nsWidgetAtoms::_true, eCaseMatters) &&
menu->GetChildCount() > 0) {
// make sure we only increment |mNumMenus| if the menu is visible, since
// we use it as an index of where to insert the next menu.
mNumMenus++;
::InsertMenuItem(mRootMenu, "\pPlaceholder", mNumMenus);
OSStatus status = ::SetMenuItemHierarchicalMenu(mRootMenu, mNumMenus, menuRef);
NS_ASSERTION(status == noErr, "nsMenuBarX::AddMenu: SetMenuItemHierarchicalMenu failed.");
}
nsCOMPtr<nsIContent> menu;
aMenu->GetMenuContent(getter_AddRefs(menu));
if(!menu->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::hidden,
nsWidgetAtoms::_true, eCaseMatters) &&
menu->GetChildCount() > 0) {
// make sure we only increment |mNumMenus| if the menu is visible, since
// we use it as an index of where to insert the next menu.
mNumMenus++;
::InsertMenuItem(mRootMenu, "\pPlaceholder", mNumMenus);
OSStatus status = ::SetMenuItemHierarchicalMenu(mRootMenu, mNumMenus, menuRef);
NS_ASSERTION(status == noErr, "nsMenuBarX::AddMenu: SetMenuItemHierarchicalMenu failed.");
}
return NS_OK;
@ -699,9 +695,9 @@ nsMenuBarX::AttributeChanged( nsIDocument * aDocument, nsIContent * aContent,
{
// lookup and dispatch to registered thang.
nsCOMPtr<nsIChangeObserver> obs;
Lookup ( aContent, getter_AddRefs(obs) );
if ( obs )
obs->AttributeChanged ( aDocument, aNameSpaceID, aAttribute );
Lookup(aContent, getter_AddRefs(obs));
if (obs)
obs->AttributeChanged(aDocument, aNameSpaceID, aContent, aAttribute);
}
void

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

@ -74,6 +74,7 @@ NS_IMPL_ISUPPORTS4(nsMenuItemX, nsIMenuItem, nsIMenuListener, nsIChangeObserver,
nsMenuItemX::nsMenuItemX()
{
mMenuParent = nsnull;
mManager = nsnull;
mIsSeparator = PR_FALSE;
mKeyEquivalent.AssignLiteral(" ");
mEnabled = PR_TRUE;
@ -90,7 +91,12 @@ nsMenuItemX::nsMenuItemX()
//
nsMenuItemX::~nsMenuItemX()
{
mManager->Unregister(mContent);
if (mManager) {
if (mContent)
mManager->Unregister(mContent);
if (mCommandContent)
mManager->Unregister(mCommandContent);
}
#if DEBUG
--gMenuItemCounterX;
@ -117,6 +123,23 @@ NS_METHOD nsMenuItemX::Create(nsIMenu* aParent, const nsString & aLabel, PRBool
mIsSeparator = aIsSeparator;
mLabel = aLabel;
// We need to pick up a command content node, it is highly unlikely that one
// won't exist. If we find one, register for changes on it.
nsCOMPtr<nsIDOMDocument> domDocument = do_QueryInterface(aNode->GetDocument());
if (domDocument) {
nsAutoString ourCommand;
aNode->GetAttr(kNameSpaceID_None, nsWidgetAtoms::command, ourCommand);
if (!ourCommand.IsEmpty()) {
nsCOMPtr<nsIDOMElement> commandElt;
domDocument->GetElementById(ourCommand, getter_AddRefs(commandElt));
if (commandElt) {
mCommandContent = do_QueryInterface(commandElt);
mManager->Register(mCommandContent, obs);
}
}
}
return NS_OK;
}
@ -382,41 +405,62 @@ nsMenuItemX :: UncheckRadioSiblings(nsIContent* inCheckedContent)
NS_IMETHODIMP
nsMenuItemX :: AttributeChanged ( nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom *aAttribute )
nsMenuItemX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIContent *aContent, nsIAtom *aAttribute)
{
if (aAttribute == nsWidgetAtoms::checked) {
// if we're a radio menu, uncheck our sibling radio items. No need to
// do any of this if we're just a normal check menu.
if ( mMenuType == eRadio ) {
if (mContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::checked,
nsWidgetAtoms::_true, eCaseMatters))
UncheckRadioSiblings(mContent);
}
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
}
else if (aAttribute == nsWidgetAtoms::disabled || aAttribute == nsWidgetAtoms::hidden ||
if (aContent == mContent) {
if (aAttribute == nsWidgetAtoms::checked) {
// if we're a radio menu, uncheck our sibling radio items. No need to
// do any of this if we're just a normal check menu.
if (mMenuType == eRadio) {
if (mContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::checked,
nsWidgetAtoms::_true, eCaseMatters))
UncheckRadioSiblings(mContent);
}
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
}
else if (aAttribute == nsWidgetAtoms::disabled || aAttribute == nsWidgetAtoms::hidden ||
aAttribute == nsWidgetAtoms::collapsed || aAttribute == nsWidgetAtoms::label ) {
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
}
}
else if (aContent == mCommandContent &&
aAttribute == nsWidgetAtoms::disabled &&
mMenuParent && mCommandContent) {
nsAutoString menuItemDisabled;
nsAutoString commandDisabled;
mContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::disabled, menuItemDisabled);
mCommandContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::disabled, commandDisabled);
if (!commandDisabled.Equals(menuItemDisabled)) {
// The menu's disabled state needs to be updated to match the command.
if (commandDisabled.IsEmpty())
mContent->UnsetAttr(kNameSpaceID_None, nsWidgetAtoms::disabled, PR_TRUE);
else
mContent->SetAttr(kNameSpaceID_None, nsWidgetAtoms::disabled, commandDisabled, PR_TRUE);
}
// we need to get our native menu item to update itself
mMenuParent->ChangeNativeEnabledStatusForMenuItem(this, !commandDisabled.EqualsLiteral("true"));
}
return NS_OK;
} // AttributeChanged
}
NS_IMETHODIMP
nsMenuItemX :: ContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer)
{
if (aChild == mCommandContent) {
mManager->Unregister(mCommandContent);
mCommandContent = nsnull;
}
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
return NS_OK;
} // ContentRemoved
}
NS_IMETHODIMP
nsMenuItemX :: ContentInserted(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer)

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

@ -109,7 +109,8 @@ protected:
nsCOMPtr<nsIMenuListener> mXULCommandListener;
nsWeakPtr mDocShellWeakRef; // weak ref to docshell
nsCOMPtr<nsIContent> mContent;
nsCOMPtr<nsIContent> mContent;
nsCOMPtr<nsIContent> mCommandContent;
PRUint8 mModifiers;
PRPackedBool mIsSeparator;

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

@ -105,9 +105,8 @@ NS_IMPL_ISUPPORTS4(nsMenuX, nsIMenu, nsIMenuListener, nsIChangeObserver, nsISupp
// nsMenuX constructor
//
nsMenuX::nsMenuX()
: mNumMenuItems(0), mParent(nsnull), mManager(nsnull),
mMacMenuID(0), mMacMenuHandle(nsnull), mHelpMenuOSItemsCount(0),
mIsHelpMenu(PR_FALSE), mIsEnabled(PR_TRUE), mDestroyHandlerCalled(PR_FALSE),
: mNumMenuItems(0), mParent(nsnull), mManager(nsnull), mMacMenuID(0),
mMacMenuHandle(nsnull), mIsEnabled(PR_TRUE), mDestroyHandlerCalled(PR_FALSE),
mNeedsRebuild(PR_TRUE), mConstructed(PR_FALSE), mVisible(PR_TRUE), mHandler(nsnull)
{
#if DEBUG
@ -174,6 +173,13 @@ nsMenuX::Create(nsISupports * aParent, const nsAString &aLabel, const nsAString
if (menubar && mMenuContent->GetChildCount() == 0)
mVisible = PR_FALSE;
// We call MenuConstruct here because keyboard commands are dependent upon
// native menu items being created. If we only call MenuConstruct when a menu
// is actually selected, then we can't access keyboard commands until the
// menu gets selected, which is bad.
nsMenuEvent fake(PR_TRUE, 0, nsnull);
MenuConstruct(fake, nsnull, nsnull, nsnull);
return NS_OK;
}
@ -476,12 +482,6 @@ nsEventStatus nsMenuX::MenuSelected(const nsMenuEvent & aMenuEvent)
MenuHandle selectedMenuHandle = (MenuHandle) aMenuEvent.mCommand;
if (mMacMenuHandle == selectedMenuHandle) {
if (mIsHelpMenu && mConstructed){
RemoveAll();
mConstructed = false;
SetRebuild(PR_TRUE);
}
// Open the node.
mMenuContent->SetAttr(kNameSpaceID_None, nsWidgetAtoms::open, NS_LITERAL_STRING("true"), PR_TRUE);
@ -489,10 +489,10 @@ nsEventStatus nsMenuX::MenuSelected(const nsMenuEvent & aMenuEvent)
// Fire our oncreate handler. If we're told to stop, don't build the menu at all
PRBool keepProcessing = OnCreate();
if (!mIsHelpMenu && !mNeedsRebuild || !keepProcessing)
if (!mNeedsRebuild || !keepProcessing)
return nsEventStatus_eConsumeNoDefault;
if(!mConstructed || mNeedsRebuild) {
if (!mConstructed || mNeedsRebuild) {
if (mNeedsRebuild)
RemoveAll();
@ -501,13 +501,9 @@ nsEventStatus nsMenuX::MenuSelected(const nsMenuEvent & aMenuEvent)
NS_ERROR("No doc shell");
return nsEventStatus_eConsumeNoDefault;
}
if (mIsHelpMenu) {
HelpMenuConstruct(aMenuEvent, nsnull /* mParentWindow */, nsnull, docShell);
mConstructed = true;
} else {
MenuConstruct(aMenuEvent, nsnull /* mParentWindow */, nsnull, docShell);
mConstructed = true;
}
MenuConstruct(aMenuEvent, nsnull /* mParentWindow */, nsnull, docShell);
mConstructed = true;
}
OnCreated(); // Now that it's built, fire the popupShown event.
@ -589,46 +585,6 @@ nsEventStatus nsMenuX::MenuConstruct(
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuX::HelpMenuConstruct(
const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * /* menuNode */,
void * aDocShell)
{
//printf("nsMenuX::MenuConstruct called for %s = %d \n", NS_LossyConvertUTF16toASCII(mLabel).get(), mMacMenuHandle);
int numHelpItems = ::CountMenuItems(mMacMenuHandle);
for (int i=0; i < numHelpItems; ++i) {
mMenuItemsArray.AppendElement(&gDummyMenuItemX);
}
// Retrieve our menupopup.
nsCOMPtr<nsIContent> menuPopup;
GetMenuPopupContent(getter_AddRefs(menuPopup));
if (!menuPopup)
return nsEventStatus_eIgnore;
// Iterate over the kids
PRUint32 count = menuPopup->GetChildCount();
for ( PRUint32 i = 0; i < count; ++i ) {
nsIContent *child = menuPopup->GetChildAt(i);
if ( child ) {
// depending on the type, create a menu item, separator, or submenu
nsIAtom *tag = child->Tag();
if ( tag == nsWidgetAtoms::menuitem )
LoadMenuItem(this, child);
else if ( tag == nsWidgetAtoms::menuseparator )
LoadSeparator(child);
else if ( tag == nsWidgetAtoms::menu )
LoadSubMenu(this, child);
}
} // for each menu item
//printf(" Done building, mMenuItemVoidArray.Count() = %d \n", mMenuItemVoidArray.Count());
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuX::MenuDestruct(const nsMenuEvent & aMenuEvent)
@ -661,11 +617,9 @@ nsEventStatus nsMenuX::CheckRebuild(PRBool & aNeedsRebuild)
//-------------------------------------------------------------------------
nsEventStatus nsMenuX::SetRebuild(PRBool aNeedsRebuild)
{
if(!gConstructingMenu) {
if (!gConstructingMenu)
mNeedsRebuild = aNeedsRebuild;
//if(mNeedsRebuild)
// RemoveAll();
}
return nsEventStatus_eIgnore;
}
@ -686,7 +640,7 @@ NS_METHOD nsMenuX::SetEnabled(PRBool aIsEnabled)
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Get enabled state
*
@ -698,20 +652,7 @@ NS_METHOD nsMenuX::GetEnabled(PRBool* aIsEnabled)
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Query if this is the help menu
*
*/
NS_METHOD nsMenuX::IsHelpMenu(PRBool* aIsHelpMenu)
{
NS_ENSURE_ARG_POINTER(aIsHelpMenu);
*aIsHelpMenu = mIsHelpMenu;
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Get GetMenuContent
*
@ -814,10 +755,40 @@ void nsMenuX::LoadMenuItem( nsIMenu* inParentMenu, nsIContent* inMenuItemContent
if (inMenuItemContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::hidden,
nsWidgetAtoms::_true, eCaseMatters))
return;
nsCOMPtr<nsIDOMDocument> domDocument = do_QueryInterface(inMenuItemContent->GetDocument());
if (!domDocument)
return;
// We want the enabled state from the command element, not the menu item element.
// The command element is more up-to-date and it matters for keyboard shortcuts
// that can be invoked without opening the menu for the item. Sync menu item's
// enabled state with its command element now.
nsAutoString ourCommand;
inMenuItemContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::command, ourCommand);
if (!ourCommand.IsEmpty()) {
// get the command DOM element
nsCOMPtr<nsIDOMElement> commandElt;
domDocument->GetElementById(ourCommand, getter_AddRefs(commandElt));
if (commandElt) {
nsCOMPtr<nsIContent> commandContent = do_QueryInterface(commandElt);
nsAutoString menuItemDisabled;
nsAutoString commandDisabled;
inMenuItemContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::disabled, menuItemDisabled);
commandContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::disabled, commandDisabled);
if (!commandDisabled.Equals(menuItemDisabled)) {
// The menu's disabled state needs to be updated to match the command
if (commandDisabled.IsEmpty())
inMenuItemContent->UnsetAttr(kNameSpaceID_None, nsWidgetAtoms::disabled, PR_TRUE);
else
inMenuItemContent->SetAttr(kNameSpaceID_None, nsWidgetAtoms::disabled, commandDisabled, PR_TRUE);
}
}
}
// Create nsMenuItem
nsCOMPtr<nsIMenuItem> pnsMenuItem = do_CreateInstance ( kMenuItemCID ) ;
if ( pnsMenuItem ) {
if (pnsMenuItem) {
nsAutoString menuitemName;
inMenuItemContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::label, menuitemName);
@ -854,12 +825,7 @@ void nsMenuX::LoadMenuItem( nsIMenu* inParentMenu, nsIContent* inMenuItemContent
nsAutoString keyValue;
inMenuItemContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::key, keyValue);
// Try to find the key node. Get the document so we can do |GetElementByID|
nsCOMPtr<nsIDOMDocument> domDocument =
do_QueryInterface(inMenuItemContent->GetDocument());
if ( !domDocument )
return;
// Try to find the key node.
nsCOMPtr<nsIDOMElement> keyElement;
if (!keyValue.IsEmpty())
domDocument->GetElementById(keyValue, getter_AddRefs(keyElement));
@ -1232,6 +1198,29 @@ nsMenuX :: CountVisibleBefore ( PRUint32* outVisibleBefore )
} // CountVisibleBefore
NS_IMETHODIMP
nsMenuX::ChangeNativeEnabledStatusForMenuItem(nsIMenuItem* aMenuItem, PRBool aEnabled)
{
// look for the menu item given
PRUint32 menuItemCount;
mMenuItemsArray.Count(&menuItemCount);
for (PRUint32 i = 0; i < menuItemCount; i++) {
nsISupports* currItem;
mMenuItemsArray.GetElementAt(i, &currItem);
if (currItem == aMenuItem) {
if (aEnabled)
::EnableMenuItem(mMacMenuHandle, i + 1);
else
::DisableMenuItem(mMacMenuHandle, i + 1);
break;
}
}
return NS_OK;
}
#pragma mark -
//
@ -1240,7 +1229,7 @@ nsMenuX :: CountVisibleBefore ( PRUint32* outVisibleBefore )
NS_IMETHODIMP
nsMenuX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom *aAttribute)
nsMenuX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIContent *aContent, nsIAtom *aAttribute)
{
if (gConstructingMenu)
return NS_OK;

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

@ -133,10 +133,10 @@ public:
NS_IMETHOD GetMenuContent(nsIContent ** aMenuNode);
NS_IMETHOD SetEnabled(PRBool aIsEnabled);
NS_IMETHOD GetEnabled(PRBool* aIsEnabled);
NS_IMETHOD IsHelpMenu(PRBool* aIsEnabled);
NS_IMETHOD AddMenuItem(nsIMenuItem * aMenuItem);
NS_IMETHOD AddMenu(nsIMenu * aMenu);
NS_IMETHOD ChangeNativeEnabledStatusForMenuItem(nsIMenuItem* aMenuItem, PRBool aEnabled);
protected:
// Determines how many menus are visible among the siblings that are before me.
@ -161,9 +161,6 @@ protected:
void LoadSubMenu ( nsIMenu * pParentMenu, nsIContent* menuitemContent );
void LoadSeparator ( nsIContent* menuitemContent );
nsEventStatus HelpMenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow,
void* unused, void* aDocShell);
MenuHandle NSStringNewMenu(short menuID, nsString& menuTitle);
protected:
@ -180,8 +177,6 @@ protected:
// MacSpecific
PRInt16 mMacMenuID;
MenuHandle mMacMenuHandle;
PRInt16 mHelpMenuOSItemsCount;
PRPackedBool mIsHelpMenu;
PRPackedBool mIsEnabled;
PRPackedBool mDestroyHandlerCalled;
PRPackedBool mNeedsRebuild;