mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-03 02:25:34 +00:00
fix up the way we handle menu separators. this is cleaner and allows them to be hidden and unhidden after creation. b=375011 r=cbarrett sr=roc a=roc
This commit is contained in:
parent
71a60fb79a
commit
a14c02df08
@ -41,7 +41,6 @@
|
||||
#include "nsISupports.h"
|
||||
#include "nsStringFwd.h"
|
||||
|
||||
class nsIDocShell;
|
||||
class nsIMenuBar;
|
||||
class nsIMenu;
|
||||
class nsIMenuItem;
|
||||
@ -68,8 +67,8 @@ class nsIMenu : public nsISupports {
|
||||
* Creates the Menu
|
||||
*
|
||||
*/
|
||||
NS_IMETHOD Create ( nsISupports * aParent, const nsAString &aLabel, const nsAString &aAccessKey,
|
||||
nsIChangeManager* aManager, nsIDocShell* aShell, nsIContent* aNode ) = 0;
|
||||
NS_IMETHOD Create(nsISupports * aParent, const nsAString &aLabel, const nsAString &aAccessKey,
|
||||
nsIChangeManager* aManager, nsIContent* aNode) = 0;
|
||||
|
||||
/**
|
||||
* Get the Menu's Parent. This addrefs.
|
||||
@ -120,13 +119,6 @@ class nsIMenu : public nsISupports {
|
||||
*/
|
||||
NS_IMETHOD AddItem(nsISupports* aItem) = 0;
|
||||
|
||||
/**
|
||||
* Adds a separator. Do not use outside of widget menu implementations.
|
||||
* Add and modify menu separators via DOM content.
|
||||
*
|
||||
*/
|
||||
NS_IMETHOD AddSeparator() = 0;
|
||||
|
||||
/**
|
||||
* Returns the number of visible menu items
|
||||
* This includes separators. It does not include hidden items.
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include "nsISupports.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDOMElement.h"
|
||||
|
||||
// {F9A30AA5-D526-4C19-8418-C21BF6B31837}
|
||||
@ -72,16 +71,15 @@ class nsIMenuItem : public nsISupports {
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMENUITEM_IID)
|
||||
|
||||
enum EMenuItemType { eRegular = 0, eCheckbox, eRadio } ;
|
||||
enum EMenuItemType { eRegular = 0, eCheckbox, eRadio, eSeparator} ;
|
||||
|
||||
/**
|
||||
* Creates the MenuItem
|
||||
*
|
||||
*/
|
||||
NS_IMETHOD Create(nsIMenu* aParent, const nsString & aLabel, PRBool isSeparator,
|
||||
EMenuItemType aItemType, nsIChangeManager* aManager,
|
||||
nsIDocShell* aShell, nsIContent* aNode) = 0;
|
||||
|
||||
NS_IMETHOD Create(nsIMenu* aParent, const nsString & aLabel, EMenuItemType aItemType,
|
||||
nsIChangeManager* aManager, nsIContent* aNode) = 0;
|
||||
|
||||
/**
|
||||
* Get the MenuItem label
|
||||
*
|
||||
|
@ -445,14 +445,13 @@ nsMenuBarX::MenuConstruct(const nsMenuEvent & aMenuEvent, nsIWidget* aParentWind
|
||||
menu->GetAttr(kNameSpaceID_None, nsWidgetAtoms::accesskey, menuAccessKey);
|
||||
|
||||
// Don't create the whole menu yet, just add in the top level names
|
||||
|
||||
|
||||
// Create nsMenu, the menubar will own it
|
||||
nsCOMPtr<nsIMenu> pnsMenu(do_CreateInstance(kMenuCID));
|
||||
if (pnsMenu) {
|
||||
pnsMenu->Create(static_cast<nsIMenuBar*>(this), menuName, menuAccessKey,
|
||||
static_cast<nsIChangeManager *>(this),
|
||||
nsnull, menu);
|
||||
|
||||
static_cast<nsIChangeManager *>(this), menu);
|
||||
|
||||
// Make nsMenu a child of nsMenuBar. nsMenuBar takes ownership.
|
||||
AddMenu(pnsMenu);
|
||||
|
||||
|
@ -154,8 +154,7 @@ nsMenuItemIconX::GetIconURI(nsIURI** aIconURI)
|
||||
if (menuItem) {
|
||||
nsIMenuItem::EMenuItemType menuItemType;
|
||||
menuItem->GetMenuItemType(&menuItemType);
|
||||
if (menuItemType == nsIMenuItem::eCheckbox ||
|
||||
menuItemType == nsIMenuItem::eRadio)
|
||||
if (menuItemType != nsIMenuItem::eRegular)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -71,9 +71,8 @@ public:
|
||||
NS_DECL_NSICHANGEOBSERVER
|
||||
|
||||
// nsIMenuItem Methods
|
||||
NS_IMETHOD Create(nsIMenu* aParent, const nsString & aLabel, PRBool aIsSeparator,
|
||||
EMenuItemType aItemType, nsIChangeManager* aManager,
|
||||
nsIDocShell* aShell, nsIContent* aNode);
|
||||
NS_IMETHOD Create(nsIMenu* aParent, const nsString & aLabel, EMenuItemType aItemType,
|
||||
nsIChangeManager* aManager, nsIContent* aNode);
|
||||
NS_IMETHOD GetLabel(nsString &aText);
|
||||
NS_IMETHOD SetShortcutChar(const nsString &aText);
|
||||
NS_IMETHOD GetShortcutChar(nsString &aText);
|
||||
@ -122,10 +121,9 @@ protected:
|
||||
nsRefPtr<nsMenuItemIconX> mIcon;
|
||||
|
||||
PRUint8 mModifiers;
|
||||
PRPackedBool mIsSeparator;
|
||||
PRPackedBool mEnabled;
|
||||
PRPackedBool mIsChecked;
|
||||
EMenuItemType mMenuType;
|
||||
EMenuItemType mType; // regular, checkbox, radio, or separator
|
||||
};
|
||||
|
||||
#endif // nsMenuItemX_h_
|
||||
|
@ -67,11 +67,10 @@ nsMenuItemX::nsMenuItemX()
|
||||
mNativeMenuItem = nil;
|
||||
mMenuParent = nsnull;
|
||||
mManager = nsnull;
|
||||
mIsSeparator = PR_FALSE;
|
||||
mKeyEquivalent.AssignLiteral(" ");
|
||||
mEnabled = PR_TRUE;
|
||||
mIsChecked = PR_FALSE;
|
||||
mMenuType = eRegular;
|
||||
mType = eRegular;
|
||||
}
|
||||
|
||||
|
||||
@ -85,15 +84,14 @@ nsMenuItemX::~nsMenuItemX()
|
||||
}
|
||||
|
||||
|
||||
NS_METHOD nsMenuItemX::Create(nsIMenu* aParent, const nsString & aLabel, PRBool aIsSeparator,
|
||||
EMenuItemType aItemType, nsIChangeManager* aManager,
|
||||
nsIDocShell* aShell, nsIContent* aNode)
|
||||
NS_METHOD nsMenuItemX::Create(nsIMenu* aParent, const nsString & aLabel, EMenuItemType aItemType,
|
||||
nsIChangeManager* aManager, nsIContent* aNode)
|
||||
{
|
||||
mContent = aNode; // addref
|
||||
mMenuParent = aParent; // weak
|
||||
|
||||
mMenuType = aItemType;
|
||||
|
||||
|
||||
mType = aItemType;
|
||||
|
||||
// register for AttributeChanged messages
|
||||
mManager = aManager;
|
||||
nsCOMPtr<nsIChangeObserver> obs = do_QueryInterface(static_cast<nsIChangeObserver*>(this));
|
||||
@ -126,11 +124,10 @@ NS_METHOD nsMenuItemX::Create(nsIMenu* aParent, const nsString & aLabel, PRBool
|
||||
else
|
||||
mEnabled = !mContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::disabled, nsWidgetAtoms::_true, eCaseMatters);
|
||||
|
||||
mIsSeparator = aIsSeparator;
|
||||
mLabel = aLabel;
|
||||
|
||||
// set up the native menu item
|
||||
if (aIsSeparator) {
|
||||
if (mType == nsIMenuItem::eSeparator) {
|
||||
mNativeMenuItem = [[NSMenuItem separatorItem] retain];
|
||||
}
|
||||
else {
|
||||
@ -218,7 +215,7 @@ NS_METHOD nsMenuItemX::GetChecked(PRBool *aIsEnabled)
|
||||
|
||||
NS_METHOD nsMenuItemX::GetMenuItemType(EMenuItemType *aType)
|
||||
{
|
||||
*aType = mMenuType;
|
||||
*aType = mType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -247,7 +244,7 @@ NS_METHOD nsMenuItemX::RemoveMenuListener(nsIMenuListener * aMenuListener)
|
||||
|
||||
NS_METHOD nsMenuItemX::IsSeparator(PRBool & aIsSep)
|
||||
{
|
||||
aIsSep = mIsSeparator;
|
||||
aIsSep = (mType == nsIMenuItem::eSeparator);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -312,11 +309,11 @@ nsEventStatus nsMenuItemX::SetRebuild(PRBool aNeedsRebuild)
|
||||
|
||||
// Executes the "cached" javaScript command.
|
||||
// Returns NS_OK if the command was executed properly, otherwise an error code.
|
||||
NS_METHOD nsMenuItemX::DoCommand()
|
||||
NS_IMETHODIMP nsMenuItemX::DoCommand()
|
||||
{
|
||||
// flip "checked" state if we're a checkbox menu, or an un-checked radio menu
|
||||
if (mMenuType == nsIMenuItem::eCheckbox ||
|
||||
(mMenuType == nsIMenuItem::eRadio && !mIsChecked)) {
|
||||
if (mType == nsIMenuItem::eCheckbox ||
|
||||
(mType == nsIMenuItem::eRadio && !mIsChecked)) {
|
||||
if (!mContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::autocheck,
|
||||
nsWidgetAtoms::_false, eCaseMatters))
|
||||
SetChecked(!mIsChecked);
|
||||
@ -327,7 +324,7 @@ NS_METHOD nsMenuItemX::DoCommand()
|
||||
nsXULCommandEvent event(PR_TRUE, NS_XUL_COMMAND, nsnull);
|
||||
|
||||
mContent->DispatchDOMEvent(&event, nsnull, nsnull, &status);
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -460,7 +457,7 @@ nsMenuItemX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIC
|
||||
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 (mType == nsIMenuItem::eRadio) {
|
||||
if (mContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::checked,
|
||||
nsWidgetAtoms::_true, eCaseMatters))
|
||||
UncheckRadioSiblings(mContent);
|
||||
|
@ -96,15 +96,14 @@ public:
|
||||
nsEventStatus SetRebuild(PRBool aMenuEvent);
|
||||
|
||||
// nsIMenu Methods
|
||||
NS_IMETHOD Create (nsISupports * aParent, const nsAString &aLabel, const nsAString &aAccessKey,
|
||||
nsIChangeManager* aManager, nsIDocShell* aShell, nsIContent* aNode);
|
||||
NS_IMETHOD Create(nsISupports * aParent, const nsAString &aLabel, const nsAString &aAccessKey,
|
||||
nsIChangeManager* aManager, nsIContent* aNode);
|
||||
NS_IMETHOD GetParent(nsISupports *&aParent);
|
||||
NS_IMETHOD GetLabel(nsString &aText);
|
||||
NS_IMETHOD SetLabel(const nsAString &aText);
|
||||
NS_IMETHOD GetAccessKey(nsString &aText);
|
||||
NS_IMETHOD SetAccessKey(const nsAString &aText);
|
||||
NS_IMETHOD AddItem(nsISupports* aText);
|
||||
NS_IMETHOD AddSeparator();
|
||||
NS_IMETHOD GetItemCount(PRUint32 &aCount);
|
||||
NS_IMETHOD GetItemAt(const PRUint32 aPos, nsISupports *& aMenuItem);
|
||||
NS_IMETHOD GetVisibleItemCount(PRUint32 &aCount);
|
||||
@ -145,7 +144,6 @@ protected:
|
||||
|
||||
void LoadMenuItem(nsIContent* inMenuItemContent);
|
||||
void LoadSubMenu(nsIContent* inMenuContent);
|
||||
void LoadSeparator(nsIContent* inSeparatorContent);
|
||||
|
||||
NSMenu* CreateMenuWithGeckoString(nsString& menuTitle);
|
||||
|
||||
|
@ -86,22 +86,6 @@ static PRBool gConstructingMenu = PR_FALSE;
|
||||
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
|
||||
static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID);
|
||||
|
||||
// Refcounted class for dummy menu items like separators
|
||||
class nsDummyMenuItemX : public nsISupports {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsDummyMenuItemX()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt) nsDummyMenuItemX::AddRef() { return ++mRefCnt; }
|
||||
NS_IMETHODIMP nsDummyMenuItemX::Release() { return --mRefCnt; }
|
||||
NS_IMPL_QUERY_INTERFACE0(nsDummyMenuItemX)
|
||||
static nsDummyMenuItemX gDummyMenuItemX;
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS4(nsMenuX, nsIMenu, nsIMenuListener, nsIChangeObserver, nsISupportsWeakReference)
|
||||
|
||||
|
||||
@ -133,7 +117,7 @@ nsMenuX::~nsMenuX()
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuX::Create(nsISupports * aParent, const nsAString &aLabel, const nsAString &aAccessKey,
|
||||
nsIChangeManager* aManager, nsIDocShell* aShell, nsIContent* aNode)
|
||||
nsIChangeManager* aManager, nsIContent* aNode)
|
||||
{
|
||||
mMenuContent = aNode;
|
||||
|
||||
@ -308,17 +292,6 @@ nsresult nsMenuX::AddMenu(nsIMenu * aMenu)
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMenuX::AddSeparator()
|
||||
{
|
||||
// We're not really appending an nsMenuItem but a placeholder needs to be
|
||||
// here to make sure that event dispatching isn't off by one.
|
||||
mMenuItemsArray.AppendObject(&gDummyMenuItemX); // owning ref
|
||||
++mVisibleItemsCount;
|
||||
[mMacMenu addItem:[NSMenuItem separatorItem]];
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// Includes all items, including hidden/collapsed ones
|
||||
NS_IMETHODIMP nsMenuX::GetItemCount(PRUint32 &aCount)
|
||||
{
|
||||
@ -346,10 +319,7 @@ static PRBool MenuNodeIsVisible(nsISupports *item)
|
||||
// Find the content for this item in the menu, be it a MenuItem or a Menu
|
||||
nsCOMPtr<nsIContent> itemContent;
|
||||
nsCOMPtr<nsIMenuItem> menuItem = do_QueryInterface(item);
|
||||
if (item == &gDummyMenuItemX) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
else if (menuItem) {
|
||||
if (menuItem) {
|
||||
menuItem->GetMenuItemContent(getter_AddRefs(itemContent));
|
||||
}
|
||||
else {
|
||||
@ -596,10 +566,8 @@ nsEventStatus nsMenuX::MenuConstruct(
|
||||
if (child) {
|
||||
// depending on the type, create a menu item, separator, or submenu
|
||||
nsIAtom *tag = child->Tag();
|
||||
if (tag == nsWidgetAtoms::menuitem)
|
||||
if (tag == nsWidgetAtoms::menuitem || tag == nsWidgetAtoms::menuseparator)
|
||||
LoadMenuItem(child);
|
||||
else if (tag == nsWidgetAtoms::menuseparator)
|
||||
LoadSeparator(child);
|
||||
else if (tag == nsWidgetAtoms::menu)
|
||||
LoadSubMenu(child);
|
||||
}
|
||||
@ -707,18 +675,22 @@ void nsMenuX::LoadMenuItem(nsIContent* inMenuItemContent)
|
||||
|
||||
// printf("menuitem %s \n", NS_LossyConvertUTF16toASCII(menuitemName).get());
|
||||
|
||||
static nsIContent::AttrValuesArray strings[] =
|
||||
{&nsWidgetAtoms::checkbox, &nsWidgetAtoms::radio, nsnull};
|
||||
nsIMenuItem::EMenuItemType itemType = nsIMenuItem::eRegular;
|
||||
switch (inMenuItemContent->FindAttrValueIn(kNameSpaceID_None, nsWidgetAtoms::type,
|
||||
strings, eCaseMatters)) {
|
||||
case 0: itemType = nsIMenuItem::eCheckbox; break;
|
||||
case 1: itemType = nsIMenuItem::eRadio; break;
|
||||
if (inMenuItemContent->Tag() == nsWidgetAtoms::menuseparator) {
|
||||
itemType = nsIMenuItem::eSeparator;
|
||||
}
|
||||
else {
|
||||
static nsIContent::AttrValuesArray strings[] =
|
||||
{&nsWidgetAtoms::checkbox, &nsWidgetAtoms::radio, nsnull};
|
||||
switch (inMenuItemContent->FindAttrValueIn(kNameSpaceID_None, nsWidgetAtoms::type,
|
||||
strings, eCaseMatters)) {
|
||||
case 0: itemType = nsIMenuItem::eCheckbox; break;
|
||||
case 1: itemType = nsIMenuItem::eRadio; break;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the item.
|
||||
pnsMenuItem->Create(this, menuitemName, PR_FALSE, itemType, mManager,
|
||||
nsnull, inMenuItemContent);
|
||||
pnsMenuItem->Create(this, menuitemName, itemType, mManager, inMenuItemContent);
|
||||
|
||||
AddMenuItem(pnsMenuItem);
|
||||
|
||||
@ -739,7 +711,7 @@ void nsMenuX::LoadSubMenu(nsIContent* inMenuContent)
|
||||
if (!pnsMenu)
|
||||
return;
|
||||
|
||||
pnsMenu->Create(reinterpret_cast<nsISupports*>(this), menuName, EmptyString(), mManager, nsnull, inMenuContent);
|
||||
pnsMenu->Create(reinterpret_cast<nsISupports*>(this), menuName, EmptyString(), mManager, inMenuContent);
|
||||
|
||||
AddMenu(pnsMenu);
|
||||
|
||||
@ -749,17 +721,6 @@ void nsMenuX::LoadSubMenu(nsIContent* inMenuContent)
|
||||
}
|
||||
|
||||
|
||||
void nsMenuX::LoadSeparator(nsIContent* inSeparatorContent)
|
||||
{
|
||||
// See bug 375011.
|
||||
// Currently we don't create nsIMenuItem objects for separators so we can't
|
||||
// track changes in their hidden/collapsed attributes. If it is hidden now it
|
||||
// is hidden forever.
|
||||
if (!NodeIsHiddenOrCollapsed(inSeparatorContent))
|
||||
AddSeparator();
|
||||
}
|
||||
|
||||
|
||||
// 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()
|
||||
|
Loading…
Reference in New Issue
Block a user