From 19735a1665d7e10a01e044100eb6e1054d0ff21c Mon Sep 17 00:00:00 2001 From: "joshmoz%gmail.com" Date: Fri, 2 Dec 2005 21:39:26 +0000 Subject: [PATCH] refactor menu item code in cocoa widgets. also allow menu items to be disabled. b=316076 r=mento sr=pinkerton --- widget/src/cocoa/nsMenuBarX.h | 1 + widget/src/cocoa/nsMenuBarX.mm | 13 +++ widget/src/cocoa/nsMenuItemX.h | 18 ++-- widget/src/cocoa/nsMenuItemX.mm | 178 +++++++++++++++++--------------- widget/src/cocoa/nsMenuX.h | 5 - widget/src/cocoa/nsMenuX.mm | 105 ++++--------------- widget/src/mac/nsMenuItemX.cpp | 13 +-- 7 files changed, 144 insertions(+), 189 deletions(-) diff --git a/widget/src/cocoa/nsMenuBarX.h b/widget/src/cocoa/nsMenuBarX.h index eb21fade179c..61df93d36d99 100644 --- a/widget/src/cocoa/nsMenuBarX.h +++ b/widget/src/cocoa/nsMenuBarX.h @@ -63,6 +63,7 @@ namespace MenuHelpersX nsresult DocShellToPresContext(nsIDocShell* inDocShell, nsPresContext** outContext); nsEventStatus DispatchCommandTo(nsIWeakReference* aDocShellWeakRef, nsIContent* aTargetContent); + NSString* CreateTruncatedCocoaLabel(nsString itemLabel); } diff --git a/widget/src/cocoa/nsMenuBarX.mm b/widget/src/cocoa/nsMenuBarX.mm index b8eadbdc1f72..1852809b2beb 100644 --- a/widget/src/cocoa/nsMenuBarX.mm +++ b/widget/src/cocoa/nsMenuBarX.mm @@ -905,3 +905,16 @@ MenuHelpersX::DispatchCommandTo(nsIWeakReference* aDocShellWeakRef, return status; } + +NSString* MenuHelpersX::CreateTruncatedCocoaLabel(nsString itemLabel) +{ + // ::TruncateThemeText() doesn't take the number of characters to truncate to, it takes a pixel with + // to fit the string in. Ugh. I talked it over with sfraser and we couldn't come up with an + // easy way to compute what this should be given the system font, etc, so we're just going + // to hard code it to something reasonable and bigger fonts will just have to deal. + const short kMaxItemPixelWidth = 300; + CFMutableStringRef labelRef = ::CFStringCreateMutable(kCFAllocatorDefault, itemLabel.Length()); + ::CFStringAppendCharacters(labelRef, (UniChar*)itemLabel.get(), itemLabel.Length()); + ::TruncateThemeText(labelRef, kThemeMenuItemFont, kThemeStateActive, kMaxItemPixelWidth, truncMiddle, NULL); + return (NSString*)labelRef; // caller releases +} diff --git a/widget/src/cocoa/nsMenuItemX.h b/widget/src/cocoa/nsMenuItemX.h index ca05e3af3f24..a2874bebe956 100644 --- a/widget/src/cocoa/nsMenuItemX.h +++ b/widget/src/cocoa/nsMenuItemX.h @@ -20,6 +20,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Josh Aas * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -38,7 +39,6 @@ #ifndef nsMenuItemX_h__ #define nsMenuItemX_h__ - #include "nsIMenuItem.h" #include "nsString.h" #include "nsIMenuListener.h" @@ -46,6 +46,8 @@ #include "nsWeakReference.h" #include "nsIWidget.h" +#include + class nsIMenu; /** @@ -66,9 +68,9 @@ public: NS_DECL_NSICHANGEOBSERVER // nsIMenuItem Methods - NS_IMETHOD Create ( nsIMenu* aParent, const nsString & aLabel, PRBool aIsSeparator, - EMenuItemType aItemType, PRBool aEnabled, - nsIChangeManager* aManager, nsIDocShell* aShell, nsIContent* aNode ) ; + NS_IMETHOD Create (nsIMenu* aParent, const nsString & aLabel, PRBool aIsSeparator, + EMenuItemType aItemType, PRBool aEnabled, + nsIChangeManager* aManager, nsIDocShell* aShell, nsIContent* aNode); NS_IMETHOD GetLabel(nsString &aText); NS_IMETHOD SetShortcutChar(const nsString &aText); NS_IMETHOD GetShortcutChar(nsString &aText); @@ -91,7 +93,7 @@ public: nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent); nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent); nsEventStatus MenuConstruct(const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow, - void * menuNode, void * aDocShell); + void * menuNode, void * aDocShell); nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent); nsEventStatus CheckRebuild(PRBool & aMenuEvent); nsEventStatus SetRebuild(PRBool aMenuEvent); @@ -100,8 +102,10 @@ protected: void UncheckRadioSiblings ( nsIContent* inCheckedElement ) ; - nsString mLabel; - nsString mKeyEquivalent; + NSMenuItem* mNativeMenuItem; // strong ref, we own + + nsString mLabel; + nsString mKeyEquivalent; nsIMenu* mMenuParent; // weak, parent owns us nsIChangeManager* mManager; // weak diff --git a/widget/src/cocoa/nsMenuItemX.mm b/widget/src/cocoa/nsMenuItemX.mm index 65542a03f8b7..1dc8d3ab0502 100644 --- a/widget/src/cocoa/nsMenuItemX.mm +++ b/widget/src/cocoa/nsMenuItemX.mm @@ -20,6 +20,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Josh Aas * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -40,7 +41,7 @@ #include "nsIContent.h" #include "nsPresContext.h" -#include "nsMenuBarX.h" // for MenuHelpers namespace +#include "nsMenuBarX.h" // for MenuHelpers namespace #include "nsMenuItemX.h" #include "nsIMenu.h" #include "nsIMenuBar.h" @@ -55,49 +56,34 @@ #include "nsGUIEvent.h" -#if 0 -nsInstanceCounter gMenuItemCounterX("nsMenuItemX"); -#endif - - NS_IMPL_ISUPPORTS4(nsMenuItemX, nsIMenuItem, nsIMenuListener, nsIChangeObserver, nsISupportsWeakReference) -// -// nsMenuItemX constructor -// + nsMenuItemX::nsMenuItemX() { + mNativeMenuItem = nil; mMenuParent = nsnull; mIsSeparator = PR_FALSE; mKeyEquivalent.AssignLiteral(" "); mEnabled = PR_TRUE; mIsChecked = PR_FALSE; mMenuType = eRegular; - -#if 0 - ++gMenuItemCounterX; -#endif } -// -// nsMenuItemX destructor -// + nsMenuItemX::~nsMenuItemX() { + [mNativeMenuItem release]; mManager->Unregister(mContent); - -#if 0 - --gMenuItemCounterX; -#endif } -NS_METHOD nsMenuItemX::Create ( nsIMenu* aParent, const nsString & aLabel, PRBool aIsSeparator, - EMenuItemType aItemType, PRBool aEnabled, - nsIChangeManager* aManager, nsIDocShell* aShell, nsIContent* aNode ) +NS_METHOD nsMenuItemX::Create(nsIMenu* aParent, const nsString & aLabel, PRBool aIsSeparator, + EMenuItemType aItemType, PRBool aEnabled, + nsIChangeManager* aManager, nsIDocShell* aShell, nsIContent* aNode) { - mContent = aNode; // addref - mMenuParent = aParent; // weak + mContent = aNode; // addref + mMenuParent = aParent; // weak mDocShellWeakRef = do_GetWeakReference(aShell); mEnabled = aEnabled; @@ -106,10 +92,23 @@ NS_METHOD nsMenuItemX::Create ( nsIMenu* aParent, const nsString & aLabel, PRBoo // register for AttributeChanged messages mManager = aManager; nsCOMPtr obs = do_QueryInterface(NS_STATIC_CAST(nsIChangeObserver*,this)); - mManager->Register(mContent, obs); // does not addref this + mManager->Register(mContent, obs); // does not addref this mIsSeparator = aIsSeparator; mLabel = aLabel; + + // set up the native menu item + if (aIsSeparator) { + mNativeMenuItem = [[NSMenuItem separatorItem] retain]; + } + else { + NSString *newCocoaLabelString = MenuHelpersX::CreateTruncatedCocoaLabel(mLabel); + mNativeMenuItem = [[NSMenuItem alloc] initWithTitle:newCocoaLabelString action:nil keyEquivalent:@""]; + [newCocoaLabelString release]; + + [mNativeMenuItem setEnabled:(BOOL)aEnabled]; + } + return NS_OK; } @@ -129,19 +128,25 @@ nsMenuItemX::GetEnabled(PRBool *aIsEnabled) } -NS_METHOD nsMenuItemX::SetChecked(PRBool aIsEnabled) +NS_METHOD nsMenuItemX::SetChecked(PRBool aIsChecked) { - mIsChecked = aIsEnabled; + mIsChecked = aIsChecked; // update the content model. This will also handle unchecking our siblings // if we are a radiomenu mContent->SetAttr(kNameSpaceID_None, nsWidgetAtoms::checked, mIsChecked ? NS_LITERAL_STRING("true") : NS_LITERAL_STRING("false"), PR_TRUE); + + // update native menu item + if (mIsChecked) + [mNativeMenuItem setState:NSOnState]; + else + [mNativeMenuItem setState:NSOffState]; return NS_OK; } -//------------------------------------------------------------------------- + NS_METHOD nsMenuItemX::GetChecked(PRBool *aIsEnabled) { *aIsEnabled = mIsChecked; @@ -149,7 +154,6 @@ NS_METHOD nsMenuItemX::GetChecked(PRBool *aIsEnabled) } -//------------------------------------------------------------------------- NS_METHOD nsMenuItemX::GetMenuItemType(EMenuItemType *aType) { *aType = mMenuType; @@ -157,28 +161,27 @@ NS_METHOD nsMenuItemX::GetMenuItemType(EMenuItemType *aType) } -//------------------------------------------------------------------------- NS_METHOD nsMenuItemX::GetTarget(nsIWidget *& aTarget) { NS_IF_ADDREF(aTarget = mTarget); return NS_OK; } -//------------------------------------------------------------------------- + NS_METHOD nsMenuItemX::GetNativeData(void *& aData) { - //aData = (void *)mMenu; + aData = mNativeMenuItem; return NS_OK; } -//------------------------------------------------------------------------- + NS_METHOD nsMenuItemX::AddMenuListener(nsIMenuListener * aMenuListener) { mXULCommandListener = aMenuListener; // addref return NS_OK; } -//------------------------------------------------------------------------- + NS_METHOD nsMenuItemX::RemoveMenuListener(nsIMenuListener * aMenuListener) { if (mXULCommandListener.get() == aMenuListener) @@ -186,7 +189,7 @@ NS_METHOD nsMenuItemX::RemoveMenuListener(nsIMenuListener * aMenuListener) return NS_OK; } -//------------------------------------------------------------------------- + NS_METHOD nsMenuItemX::IsSeparator(PRBool & aIsSep) { aIsSep = mIsSeparator; @@ -203,12 +206,13 @@ nsEventStatus nsMenuItemX::MenuItemSelected(const nsMenuEvent & aMenuEvent) return nsEventStatus_eConsumeNoDefault; } -//------------------------------------------------------------------------- + nsEventStatus nsMenuItemX::MenuSelected(const nsMenuEvent & aMenuEvent) { return nsEventStatus_eIgnore; } + //------------------------------------------------------------------------- // nsIMenuListener interface //------------------------------------------------------------------------- @@ -217,7 +221,7 @@ nsEventStatus nsMenuItemX::MenuDeselected(const nsMenuEvent & aMenuEvent) return nsEventStatus_eIgnore; } -//------------------------------------------------------------------------- + nsEventStatus nsMenuItemX::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow, @@ -227,27 +231,26 @@ nsEventStatus nsMenuItemX::MenuConstruct( return nsEventStatus_eIgnore; } -//------------------------------------------------------------------------- + nsEventStatus nsMenuItemX::MenuDestruct(const nsMenuEvent & aMenuEvent) { return nsEventStatus_eIgnore; } -//------------------------------------------------------------------------- + nsEventStatus nsMenuItemX::CheckRebuild(PRBool & aNeedsRebuild) { aNeedsRebuild = PR_TRUE; return nsEventStatus_eIgnore; } -//------------------------------------------------------------------------- + nsEventStatus nsMenuItemX::SetRebuild(PRBool aNeedsRebuild) { - //mNeedsRebuild = aNeedsRebuild; return nsEventStatus_eIgnore; } -//------------------------------------------------------------------------- + /** * Executes the "cached" JavaScript Command * @return NS_OK if the command was executed properly, otherwise an error code @@ -282,38 +285,52 @@ NS_METHOD nsMenuItemX::DoCommand() } - //------------------------------------------------------------------------- NS_METHOD nsMenuItemX::GetModifiers(PRUint8 * aModifiers) { - nsresult res = NS_OK; - *aModifiers = mModifiers; - return res; + *aModifiers = mModifiers; + return NS_OK; } -//------------------------------------------------------------------------- + NS_METHOD nsMenuItemX::SetModifiers(PRUint8 aModifiers) -{ - nsresult res = NS_OK; - - mModifiers = aModifiers; - return res; +{ + mModifiers = aModifiers; + + // set up shortcut key modifiers on native menu item + unsigned int macModifiers = 0; + if (mModifiers & knsMenuItemShiftModifier) + macModifiers |= NSShiftKeyMask; + if (mModifiers & knsMenuItemAltModifier) + macModifiers |= NSAlternateKeyMask; + if (mModifiers & knsMenuItemControlModifier) + macModifiers |= NSControlKeyMask; + if (mModifiers & knsMenuItemCommandModifier) + macModifiers |= NSCommandKeyMask; + [mNativeMenuItem setKeyEquivalentModifierMask:macModifiers]; + + return NS_OK; } -//------------------------------------------------------------------------- + NS_METHOD nsMenuItemX::SetShortcutChar(const nsString &aText) { - nsresult res = NS_OK; - mKeyEquivalent = aText; - return res; -} + mKeyEquivalent = aText; + + // set up shortcut key on native menu item + NSString *keyEquivalent = [[NSString stringWithCharacters:(unichar*)mKeyEquivalent.get() + length:mKeyEquivalent.Length()] lowercaseString]; + if (![keyEquivalent isEqualToString:@" "]) + [mNativeMenuItem setKeyEquivalent:keyEquivalent]; + + return NS_OK; +} + -//------------------------------------------------------------------------- NS_METHOD nsMenuItemX::GetShortcutChar(nsString &aText) { - nsresult res = NS_OK; - aText = mKeyEquivalent; - return res; -} + aText = mKeyEquivalent; + return NS_OK; +} // // UncheckRadioSiblings @@ -322,35 +339,33 @@ NS_METHOD nsMenuItemX::GetShortcutChar(nsString &aText) // uncheck them all. // void -nsMenuItemX :: UncheckRadioSiblings(nsIContent* inCheckedContent) +nsMenuItemX::UncheckRadioSiblings(nsIContent* inCheckedContent) { nsAutoString myGroupName; inCheckedContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::name, myGroupName); - if ( ! myGroupName.Length() ) // no groupname, nothing to do + if (!myGroupName.Length()) // no groupname, nothing to do return; nsCOMPtr parent = inCheckedContent->GetParent(); - if ( !parent ) + if (!parent) return; // loop over siblings PRUint32 count = parent->GetChildCount(); - for ( PRUint32 i = 0; i < count; ++i ) { + for (PRUint32 i = 0; i < count; i++) { nsIContent *sibling = parent->GetChildAt(i); - if ( sibling ) { - if ( sibling != inCheckedContent ) { // skip this node + if (sibling) { + if (sibling != inCheckedContent) { // skip this node // if the current sibling is in the same group, clear it nsAutoString currGroupName; sibling->GetAttr(kNameSpaceID_None, nsWidgetAtoms::name, currGroupName); - if ( currGroupName == myGroupName ) + if (currGroupName == myGroupName) sibling->SetAttr(kNameSpaceID_None, nsWidgetAtoms::checked, NS_LITERAL_STRING("false"), PR_TRUE); } } } // for each sibling - } // UncheckRadioSiblings -#pragma mark - // // nsIChangeObserver @@ -358,49 +373,44 @@ nsMenuItemX :: UncheckRadioSiblings(nsIContent* inCheckedContent) NS_IMETHODIMP -nsMenuItemX :: AttributeChanged ( nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom *aAttribute ) +nsMenuItemX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, 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 (mMenuType == eRadio) { nsAutoString checked; mContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::checked, checked); - if (checked.EqualsLiteral("true") ) + if (checked.EqualsLiteral("true")) UncheckRadioSiblings(mContent); } - nsCOMPtr listener = do_QueryInterface(mMenuParent); listener->SetRebuild(PR_TRUE); - - } + } else if (aAttribute == nsWidgetAtoms::disabled || aAttribute == nsWidgetAtoms::hidden || - aAttribute == nsWidgetAtoms::collapsed ) { + aAttribute == nsWidgetAtoms::collapsed) { nsCOMPtr listener = do_QueryInterface(mMenuParent); listener->SetRebuild(PR_TRUE); } return NS_OK; - } // AttributeChanged NS_IMETHODIMP -nsMenuItemX :: ContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer) +nsMenuItemX::ContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer) { - nsCOMPtr listener = do_QueryInterface(mMenuParent); listener->SetRebuild(PR_TRUE); return NS_OK; } // ContentRemoved + NS_IMETHODIMP nsMenuItemX :: ContentInserted(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer) { - nsCOMPtr listener = do_QueryInterface(mMenuParent); listener->SetRebuild(PR_TRUE); return NS_OK; - } // ContentInserted diff --git a/widget/src/cocoa/nsMenuX.h b/widget/src/cocoa/nsMenuX.h index d1b08627b80e..0c3d84af3bb5 100644 --- a/widget/src/cocoa/nsMenuX.h +++ b/widget/src/cocoa/nsMenuX.h @@ -122,11 +122,6 @@ protected: // fetch the content node associated with the menupopup item void GetMenuPopupContent(nsIContent** aResult); - - // Insert a new item in this menu with index |inItemIndex| with the text |inItemLabel|, - // middle-truncated to a certain pixel width with an elipsis. - void InsertMenuItemWithTruncation(nsAutoString & inItemLabel, - PRUint32 inItemIndex); // fire handlers for oncreate/ondestroy PRBool OnDestroy(); diff --git a/widget/src/cocoa/nsMenuX.mm b/widget/src/cocoa/nsMenuX.mm index f298bb219398..eee4b5723f77 100644 --- a/widget/src/cocoa/nsMenuX.mm +++ b/widget/src/cocoa/nsMenuX.mm @@ -146,7 +146,6 @@ nsMenuX::Create(nsISupports * aParent, const nsAString &aLabel, const nsAString NS_ASSERTION(menubar || menu, "Menu parent not a menu bar or menu!"); SetLabel(aLabel); - SetAccessKey(aAccessKey); nsAutoString hiddenValue, collapsedValue; mMenuContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::hidden, hiddenValue); @@ -222,40 +221,17 @@ NS_IMETHODIMP nsMenuX::AddMenuItem(nsIMenuItem * aMenuItem) if (!aMenuItem) return NS_ERROR_NULL_POINTER; - PRUint32 currItemIndex = mMenuItemsArray.Count(); mMenuItemsArray.AppendObject(aMenuItem); // owning ref - nsAutoString label; - aMenuItem->GetLabel(label); - InsertMenuItemWithTruncation(label, currItemIndex); - NSMenuItem *newNativeMenuItem = [mMacMenu itemAtIndex:currItemIndex]; - + // add the menu item to this menu + NSMenuItem* newNativeMenuItem; + aMenuItem->GetNativeData((void*&)newNativeMenuItem); + [mMacMenu addItem:newNativeMenuItem]; + // set up target/action [newNativeMenuItem setTarget:mMenuDelegate]; [newNativeMenuItem setAction:@selector(menuItemHit:)]; - // set up shortcut keys - nsAutoString geckoKeyEquivalent(NS_LITERAL_STRING(" ")); - aMenuItem->GetShortcutChar(geckoKeyEquivalent); - NSString *keyEquivalent = [[NSString stringWithCharacters:(unichar*)geckoKeyEquivalent.get() - length:geckoKeyEquivalent.Length()] lowercaseString]; - if (![keyEquivalent isEqualToString:@" "]) - [newNativeMenuItem setKeyEquivalent:keyEquivalent]; - - // set up shortcut key modifiers - PRUint8 modifiers; - aMenuItem->GetModifiers(&modifiers); - unsigned int macModifiers = 0; - if (knsMenuItemShiftModifier & modifiers) - macModifiers |= NSShiftKeyMask; - if (knsMenuItemAltModifier & modifiers) - macModifiers |= NSAlternateKeyMask; - if (knsMenuItemControlModifier & modifiers) - macModifiers |= NSControlKeyMask; - if (knsMenuItemCommandModifier & modifiers) - macModifiers |= NSCommandKeyMask; - [newNativeMenuItem setKeyEquivalentModifierMask:macModifiers]; - // set its command. we get the unique command id from the menubar nsCOMPtr dispatcher(do_QueryInterface(mManager)); if (dispatcher) { @@ -265,20 +241,6 @@ NS_IMETHODIMP nsMenuX::AddMenuItem(nsIMenuItem * aMenuItem) [newNativeMenuItem setTag:commandID]; } - PRBool isEnabled; - aMenuItem->GetEnabled(&isEnabled); - if (isEnabled) - [newNativeMenuItem setEnabled:YES]; - else - [newNativeMenuItem setEnabled:NO]; - - PRBool isChecked; - aMenuItem->GetChecked(&isChecked); - if (isChecked) - [newNativeMenuItem setState:NSOnState]; - else - [newNativeMenuItem setState:NSOffState]; - return NS_OK; } @@ -296,19 +258,14 @@ NS_IMETHODIMP nsMenuX::AddMenu(nsIMenu * aMenu) PRUint32 currItemIndex = mMenuItemsArray.Count(); mMenuItemsArray.AppendObject(supports); // owning ref - // We have to add it as a menu item and then associate it with the item + // We have to add a menu item and then associate the menu with it nsAutoString label; aMenu->GetLabel(label); - InsertMenuItemWithTruncation(label, currItemIndex); - - PRBool isEnabled; - aMenu->GetEnabled(&isEnabled); - if (isEnabled) { - [[mMacMenu itemAtIndex:currItemIndex] setEnabled:YES]; - } - else { - [[mMacMenu itemAtIndex:currItemIndex] setEnabled:NO]; - } + NSString *newCocoaLabelString = MenuHelpersX::CreateTruncatedCocoaLabel(mLabel); + NSMenuItem* newNativeMenuItem= [[NSMenuItem alloc] initWithTitle:newCocoaLabelString action:NULL keyEquivalent:@""]; + [newCocoaLabelString release]; + [mMacMenu addItem:newNativeMenuItem]; + NSMenu* childMenu; if (aMenu->GetNativeData((void**)&childMenu) == NS_OK) { [[mMacMenu itemAtIndex:currItemIndex] setSubmenu:childMenu]; @@ -317,29 +274,6 @@ NS_IMETHODIMP nsMenuX::AddMenu(nsIMenu * aMenu) } -// -// InsertMenuItemWithTruncation -// -// Insert a new item in this menu with index |inItemIndex| with the text |inItemLabel|, -// middle-truncated to a certain pixel width with an elipsis. -// -void -nsMenuX::InsertMenuItemWithTruncation(nsAutoString & inItemLabel, PRUint32 inItemIndex) -{ - // ::TruncateThemeText() doesn't take the number of characters to truncate to, it takes a pixel with - // to fit the string in. Ugh. I talked it over with sfraser and we couldn't come up with an - // easy way to compute what this should be given the system font, etc, so we're just going - // to hard code it to something reasonable and bigger fonts will just have to deal. - const short kMaxItemPixelWidth = 300; - - CFMutableStringRef labelRef = ::CFStringCreateMutable(kCFAllocatorDefault, inItemLabel.Length()); - ::CFStringAppendCharacters(labelRef, (UniChar*)inItemLabel.get(), inItemLabel.Length()); - ::TruncateThemeText(labelRef, kThemeMenuItemFont, kThemeStateActive, kMaxItemPixelWidth, truncMiddle, NULL); - [mMacMenu insertItem:[[[NSMenuItem alloc] initWithTitle:(NSString*)labelRef action:NULL keyEquivalent:@""] autorelease] atIndex:(inItemIndex)]; - ::CFRelease(labelRef); -} // InsertMenuItemWithTruncation - - NS_IMETHODIMP nsMenuX::AddSeparator() { // We're not really appending an nsMenuItem but it needs to be here to make @@ -682,6 +616,10 @@ NSMenu* nsMenuX::CreateMenuWithGeckoString(nsString& menuTitle) NSMenu* myMenu = [[NSMenu alloc] initWithTitle:title]; [myMenu setDelegate:mMenuDelegate]; + // We don't want this menu to auto-enable menu items because then Cocoa + // overrides our decisions and things get incorrectly enabled/disabled. + [myMenu setAutoenablesItems:NO]; + // we used to install Carbon event handlers here, but since NSMenu* doesn't // create its underlying MenuRef until just before display, we delay until // that happens. Now we install the event handlers when Cocoa notifies @@ -819,9 +757,9 @@ nsMenuX::LoadSubMenu(nsIMenu * pParentMenu, nsIContent* inMenuItemContent) nsAutoString disabled; inMenuItemContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::disabled, disabled); if (disabled.EqualsLiteral("true")) - pnsMenu->SetEnabled (PR_FALSE); + pnsMenu->SetEnabled(PR_FALSE); else - pnsMenu->SetEnabled (PR_TRUE); + pnsMenu->SetEnabled(PR_TRUE); // Make nsMenu a child of parent nsMenu. The parent takes ownership nsCOMPtr supports2(do_QueryInterface(pnsMenu)); @@ -873,7 +811,7 @@ nsMenuX::OnCreate() rv = dispatchTo->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); if (NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault) return PR_FALSE; - } + } // the menu is going to show and the oncreate handler has executed. We // now need to walk our menu items, checking to see if any of them have @@ -1161,10 +1099,9 @@ nsMenuX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom // reuse the existing menu, to avoid rebuilding the root menu bar. NS_ASSERTION(mMacMenu != NULL, "nsMenuX::AttributeChanged: invalid menu handle."); RemoveAll(); - CFStringRef titleRef = ::CFStringCreateWithCharacters(kCFAllocatorDefault, (UniChar*)mLabel.get(), mLabel.Length()); - NS_ASSERTION(titleRef, "nsMenuX::AttributeChanged: CFStringCreateWithCharacters failed."); - [mMacMenu setTitle:(NSString*)titleRef]; - ::CFRelease(titleRef); + NSString *newCocoaLabelString = MenuHelpersX::CreateTruncatedCocoaLabel(mLabel); + [mMacMenu setTitle:newCocoaLabelString]; + [newCocoaLabelString release]; } } else if (aAttribute == nsWidgetAtoms::hidden || aAttribute == nsWidgetAtoms::collapsed) { diff --git a/widget/src/mac/nsMenuItemX.cpp b/widget/src/mac/nsMenuItemX.cpp index fe8fccd0b1ad..f99a34d2e7ec 100644 --- a/widget/src/mac/nsMenuItemX.cpp +++ b/widget/src/mac/nsMenuItemX.cpp @@ -276,34 +276,29 @@ NS_METHOD nsMenuItemX::DoCommand() //------------------------------------------------------------------------- NS_METHOD nsMenuItemX::GetModifiers(PRUint8 * aModifiers) { - nsresult res = NS_OK; *aModifiers = mModifiers; - return res; + return NS_OK; } //------------------------------------------------------------------------- NS_METHOD nsMenuItemX::SetModifiers(PRUint8 aModifiers) { - nsresult res = NS_OK; - mModifiers = aModifiers; - return res; + return NS_OK; } //------------------------------------------------------------------------- NS_METHOD nsMenuItemX::SetShortcutChar(const nsString &aText) { - nsresult res = NS_OK; mKeyEquivalent = aText; - return res; + return NS_OK; } //------------------------------------------------------------------------- NS_METHOD nsMenuItemX::GetShortcutChar(nsString &aText) { - nsresult res = NS_OK; aText = mKeyEquivalent; - return res; + return NS_OK; } //