1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Netscape Public License
6
* Version 1.1 (the "License"); you may not use this file except in
7
* compliance with the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/NPL/
10
* Software distributed under the License is distributed on an "AS IS" basis,
11
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
* for the specific language governing rights and limitations under the
15
* The Original Code is mozilla.org code.
17
* The Initial Developer of the Original Code is
18
* Netscape Communications Corporation.
19
* Portions created by the Initial Developer are Copyright (C) 1998
20
* the Initial Developer. All Rights Reserved.
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the NPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the NPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
39
#include "nsIServiceManager.h"
40
#include "nsIComponentManager.h"
41
#include "nsINameSpaceManager.h"
43
#include "nsIMenuItem.h"
44
#include "nsIContent.h"
46
#include "nsMenuBarX.h"
49
#include "nsISupports.h"
50
#include "nsIWidget.h"
52
#include "nsIStringBundle.h"
53
#include "nsIDocument.h"
54
#include "nsIDocShell.h"
55
#include "nsIDocumentViewer.h"
56
#include "nsIDocumentObserver.h"
58
#include "nsIDOMDocument.h"
59
#include "nsWidgetAtoms.h"
62
#include <TextUtils.h>
64
#include <Resources.h>
65
#include <Appearance.h>
67
#include "nsMacResources.h"
69
#include "nsGUIEvent.h"
72
#include "nsWidgetsCID.h"
73
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
75
NS_IMPL_ISUPPORTS6(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIDocumentObserver,
76
nsIChangeManager, nsIMenuCommandDispatcher, nsISupportsWeakReference)
78
MenuRef nsMenuBarX::sAppleMenu = nsnull;
79
EventHandlerUPP nsMenuBarX::sCommandEventHandler = nsnull;
83
// nsMenuBarX constructor
85
nsMenuBarX::nsMenuBarX()
86
: mCurrentCommandID(1),
89
mIsMenuBarAdded(PR_FALSE),
92
OSStatus status = ::CreateNewMenu(0, 0, &mRootMenu);
93
NS_ASSERTION(status == noErr, "nsMenuBarX::nsMenuBarX: creation of root menu failed.");
95
// create our global carbon event command handler shared by all windows
96
if ( !sCommandEventHandler )
97
sCommandEventHandler = ::NewEventHandlerUPP(CommandEventHandler);
101
// nsMenuBarX destructor
103
nsMenuBarX::~nsMenuBarX()
105
mMenusArray.Clear(); // release all menus
107
// make sure we unregister ourselves as a document observer
109
nsCOMPtr<nsIDocumentObserver> observer ( do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)) );
110
mDocument->RemoveObserver(observer);
114
::ReleaseMenu(mRootMenu);
118
nsMenuBarX::MenuItemSelected(const nsMenuEvent & aMenuEvent)
120
// Dispatch menu event
121
nsEventStatus eventStatus = nsEventStatus_eIgnore;
124
mMenusArray.Count(&numItems);
126
for (PRUint32 i = numItems; i > 0; --i)
128
nsCOMPtr<nsISupports> menuSupports = getter_AddRefs(mMenusArray.ElementAt(i - 1));
129
nsCOMPtr<nsIMenuListener> menuListener = do_QueryInterface(menuSupports);
132
eventStatus = menuListener->MenuItemSelected(aMenuEvent);
133
if (nsEventStatus_eIgnore != eventStatus)
142
nsMenuBarX::MenuSelected(const nsMenuEvent & aMenuEvent)
145
nsEventStatus eventStatus = nsEventStatus_eIgnore;
147
nsCOMPtr<nsIMenuListener> menuListener;
148
//((nsISupports*)mMenuVoidArray[i-1])->QueryInterface(NS_GET_IID(nsIMenuListener), (void**)&menuListener);
149
//printf("gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count());
151
nsCOMPtr<nsIMenu> theMenu;
152
gPreviousMenuStack.GetMenuAt(gPreviousMenuStack.Count() - 1, getter_AddRefs(theMenu));
153
menuListener = do_QueryInterface(theMenu);
156
//TODO: MenuSelected is the right thing to call...
157
//eventStatus = menuListener->MenuSelected(aMenuEvent);
158
eventStatus = menuListener->MenuItemSelected(aMenuEvent);
159
if (nsEventStatus_eIgnore != eventStatus)
162
// If it's the help menu, gPreviousMenuStack won't be accurate so we need to get the listener a different way
163
// We'll do it the old fashioned way of looping through and finding it
165
mMenusArray.Count(&numItems);
166
for (PRUint32 i = numItems; i > 0; --i)
168
nsCOMPtr<nsISupports> menuSupports = getter_AddRefs(mMenusArray.ElementAt(i - 1));
169
nsCOMPtr<nsIMenuListener> thisListener = do_QueryInterface(menuSupports);
172
//TODO: MenuSelected is the right thing to call...
173
//eventStatus = menuListener->MenuSelected(aMenuEvent);
174
eventStatus = thisListener->MenuItemSelected(aMenuEvent);
175
if(nsEventStatus_eIgnore != eventStatus)
185
nsMenuBarX::MenuDeselected(const nsMenuEvent & aMenuEvent)
187
return nsEventStatus_eIgnore;
191
nsMenuBarX::CheckRebuild(PRBool & aNeedsRebuild)
193
aNeedsRebuild = PR_TRUE;
194
return nsEventStatus_eIgnore;
198
nsMenuBarX::SetRebuild(PRBool aNeedsRebuild)
200
return nsEventStatus_eIgnore;
204
nsMenuBarX :: GetDocument ( nsIWebShell* inWebShell, nsIDocument** outDocument )
206
*outDocument = nsnull;
208
nsCOMPtr<nsIDocShell> docShell ( do_QueryInterface(inWebShell) );
209
nsCOMPtr<nsIContentViewer> cv;
211
docShell->GetContentViewer(getter_AddRefs(cv));
214
nsCOMPtr<nsIDocumentViewer> docv(do_QueryInterface(cv));
217
docv->GetDocument(outDocument); // addrefs
224
// RegisterAsDocumentObserver
229
nsMenuBarX :: RegisterAsDocumentObserver ( nsIWebShell* inWebShell )
231
nsCOMPtr<nsIDocument> doc;
232
GetDocument(inWebShell, getter_AddRefs(doc));
236
// register ourselves
237
nsCOMPtr<nsIDocumentObserver> observer ( do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)) );
238
doc->AddObserver(observer);
239
// also get pointer to doc, just in case webshell goes away
240
// we can still remove ourself as doc observer directly from doc
242
} // RegisterAsDocumentObesrver
248
// Do what's necessary to conform to the Aqua guidelines for menus. Initially, this
249
// means removing 'Quit' from the file menu and 'Preferences' from the edit menu, along
250
// with their various separators (if present).
253
nsMenuBarX :: AquifyMenuBar ( )
255
nsCOMPtr<nsIDOMDocument> domDoc ( do_QueryInterface(mMenuBarContent->GetDocument()) );
257
// remove quit item and its separator
258
HideItem ( domDoc, NS_LITERAL_STRING("menu_FileQuitSeparator"), nsnull );
259
HideItem ( domDoc, NS_LITERAL_STRING("menu_FileQuitItem"), getter_AddRefs(mQuitItemContent) );
261
// remove prefs item and its separator, but save off the pref content node
262
// so we can invoke its command later.
263
HideItem ( domDoc, NS_LITERAL_STRING("menu_PrefsSeparator"), nsnull );
264
HideItem ( domDoc, NS_LITERAL_STRING("menu_preferences"), getter_AddRefs(mPrefItemContent) );
271
// InstallCommandEventHandler
273
// Grab our window and install an event handler to handle command events which are
274
// used to drive the action when the user chooses an item from a menu. We have to install
275
// it on the window because the menubar isn't in the event chain for a menu command event.
278
nsMenuBarX :: InstallCommandEventHandler ( )
280
OSStatus err = noErr;
282
WindowRef myWindow = NS_REINTERPRET_CAST(WindowRef, mParent->GetNativeData(NS_NATIVE_DISPLAY));
283
NS_ASSERTION ( myWindow, "Can't get WindowRef to install command handler!" );
284
if ( myWindow && sCommandEventHandler ) {
285
const EventTypeSpec commandEventList[] = { {kEventClassCommand, kEventCommandProcess},
286
{kEventClassCommand, kEventCommandUpdateStatus} };
287
err = ::InstallWindowEventHandler ( myWindow, sCommandEventHandler, 2, commandEventList, this, NULL );
288
NS_ASSERTION ( err == noErr, "Uh oh, command handler not installed" );
293
} // InstallCommandEventHandler
297
// CommandEventHandler
299
// Processes Command carbon events from enabling/selecting of items in the menu.
302
nsMenuBarX :: CommandEventHandler ( EventHandlerCallRef inHandlerChain, EventRef inEvent, void* userData )
304
OSStatus handled = eventNotHandledErr;
307
OSErr err1 = ::GetEventParameter ( inEvent, kEventParamDirectObject, typeHICommand,
308
NULL, sizeof(HICommand), NULL, &command );
312
nsMenuBarX* self = NS_REINTERPRET_CAST(nsMenuBarX*, userData);
313
switch ( ::GetEventKind(inEvent) ) {
314
// user selected a menu item. See if it's one we handle.
315
case kEventCommandProcess:
317
switch ( command.commandID ) {
318
case kHICommandPreferences:
320
nsEventStatus status = self->ExecuteCommand(self->mPrefItemContent);
321
if ( status == nsEventStatus_eConsumeNoDefault ) // event handled, no other processing
328
nsEventStatus status = self->ExecuteCommand(self->mQuitItemContent);
329
if ( status == nsEventStatus_eConsumeNoDefault ) // event handled, no other processing
334
case kHICommandAbout:
336
// the 'about' command is special because we don't have a nsIMenu or nsIMenuItem
337
// for the apple menu. Grovel for the content node with an id of "aboutName"
338
// and call it directly.
339
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(self->mDocument);
341
nsCOMPtr<nsIDOMElement> domElement;
342
domDoc->GetElementById(NS_LITERAL_STRING("aboutName"), getter_AddRefs(domElement));
343
nsCOMPtr<nsIContent> aboutContent ( do_QueryInterface(domElement) );
344
self->ExecuteCommand(aboutContent);
352
// given the commandID, look it up in our hashtable and dispatch to
353
// that content node. Recall that we store weak pointers to the content
354
// nodes in the hash table.
355
nsPRUint32Key key ( command.commandID );
356
nsIMenuItem* content = NS_REINTERPRET_CAST(nsIMenuItem*, self->mObserverTable.Get(&key));
358
content->DoCommand();
363
} // switch on commandID
367
// enable/disable menu id's
368
case kEventCommandUpdateStatus:
370
// only enable the preferences item in the app menu if we found a pref
371
// item DOM node in this menubar.
372
if ( command.commandID == kHICommandPreferences ) {
373
if ( self->mPrefItemContent )
374
::EnableMenuCommand ( nsnull, kHICommandPreferences );
376
::DisableMenuCommand ( nsnull, kHICommandPreferences );
381
} // switch on event type
385
} // CommandEventHandler
391
// Execute the menu item by sending a command message to the
392
// DOM node specified in |inDispatchTo|.
395
nsMenuBarX :: ExecuteCommand ( nsIContent* inDispatchTo )
397
nsEventStatus status = nsEventStatus_eIgnore;
398
if ( inDispatchTo ) {
399
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
401
return nsEventStatus_eConsumeNoDefault;
402
nsCOMPtr<nsIPresContext> presContext;
403
MenuHelpersX::WebShellToPresContext(webShell, getter_AddRefs(presContext));
405
nsMouseEvent event(NS_XUL_COMMAND);
407
inDispatchTo->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
417
// Hide the item in the menu by setting the 'hidden' attribute. Returns it in |outHiddenNode| so
418
// the caller can hang onto it if they so choose. It is acceptable to pass nsull
419
// for |outHiddenNode| if the caller doesn't care about the hidden node.
422
nsMenuBarX :: HideItem ( nsIDOMDocument* inDoc, const nsAString & inID, nsIContent** outHiddenNode )
424
nsCOMPtr<nsIDOMElement> menuItem;
425
inDoc->GetElementById(inID, getter_AddRefs(menuItem));
426
nsCOMPtr<nsIContent> menuContent ( do_QueryInterface(menuItem) );
428
menuContent->SetAttr ( kNameSpaceID_None, nsWidgetAtoms::hidden, NS_LITERAL_STRING("true"), PR_FALSE );
429
if ( outHiddenNode ) {
430
*outHiddenNode = menuContent.get();
431
NS_IF_ADDREF(*outHiddenNode);
439
nsMenuBarX::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow,
440
void * menubarNode, void * aWebShell )
442
mWebShellWeakRef = do_GetWeakReference(NS_STATIC_CAST(nsIWebShell*, aWebShell));
443
nsIDOMNode* aDOMNode = NS_STATIC_CAST(nsIDOMNode*, menubarNode);
444
mMenuBarContent = do_QueryInterface(aDOMNode); // strong ref
445
NS_ASSERTION ( mMenuBarContent, "No content specified for this menubar" );
446
if ( !mMenuBarContent )
447
return nsEventStatus_eIgnore;
449
Create(aParentWindow);
451
// if we're on X (using aqua UI guidelines for menus), remove quit and prefs
454
OSStatus err = ::Gestalt ( gestaltMenuMgrAttr, &result );
455
if ( !err && (result & gestaltMenuMgrAquaLayoutMask) )
457
err = InstallCommandEventHandler();
459
return nsEventStatus_eIgnore;
461
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
462
if (webShell) RegisterAsDocumentObserver(webShell);
464
// set this as a nsMenuListener on aParentWindow
465
aParentWindow->AddMenuListener((nsIMenuListener *)this);
467
PRUint32 count = mMenuBarContent->GetChildCount();
468
for ( PRUint32 i = 0; i < count; ++i ) {
469
nsIContent *menu = mMenuBarContent->GetChildAt(i);
471
if (menu->Tag() == nsWidgetAtoms::menu &&
472
menu->IsContentOfType(nsIContent::eXUL)) {
473
nsAutoString menuName;
474
nsAutoString menuAccessKey(NS_LITERAL_STRING(" "));
475
menu->GetAttr(kNameSpaceID_None, nsWidgetAtoms::label, menuName);
476
menu->GetAttr(kNameSpaceID_None, nsWidgetAtoms::accesskey, menuAccessKey);
478
// Don't create the whole menu yet, just add in the top level names
480
// Create nsMenu, the menubar will own it
481
nsCOMPtr<nsIMenu> pnsMenu ( do_CreateInstance(kMenuCID) );
483
pnsMenu->Create(NS_STATIC_CAST(nsIMenuBar*, this), menuName, menuAccessKey,
484
NS_STATIC_CAST(nsIChangeManager *, this),
485
NS_REINTERPRET_CAST(nsIWebShell*, aWebShell), menu);
487
// Make nsMenu a child of nsMenuBar. nsMenuBar takes ownership
490
nsAutoString menuIDstring;
491
menu->GetAttr(kNameSpaceID_None, nsWidgetAtoms::id, menuIDstring);
492
if ( menuIDstring == NS_LITERAL_STRING("menu_Help") ) {
494
MenuHandle handle = nsnull;
496
::HMGetHelpMenuHandle(&handle);
498
event.mCommand = (unsigned int) handle;
499
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(pnsMenu));
500
listener->MenuSelected(event);
507
// Give the aParentWindow this nsMenuBarX to hold onto.
508
// The parent takes ownership
509
aParentWindow->SetMenuBar(this);
511
return nsEventStatus_eIgnore;
516
nsMenuBarX::MenuDestruct(const nsMenuEvent & aMenuEvent)
518
return nsEventStatus_eIgnore;
522
//-------------------------------------------------------------------------
524
// Create the proper widget
526
//-------------------------------------------------------------------------
527
NS_METHOD nsMenuBarX::Create(nsIWidget *aParent)
533
//-------------------------------------------------------------------------
534
NS_METHOD nsMenuBarX::GetParent(nsIWidget *&aParent)
536
NS_IF_ADDREF(aParent = mParent);
541
//-------------------------------------------------------------------------
542
NS_METHOD nsMenuBarX::SetParent(nsIWidget *aParent)
544
mParent = aParent; // weak ref
548
//-------------------------------------------------------------------------
549
NS_METHOD nsMenuBarX::AddMenu(nsIMenu * aMenu)
551
// keep track of all added menus.
552
mMenusArray.AppendElement(aMenu); // owner
554
if (mNumMenus == 0) {
555
// if apple menu hasn't been created, create it.
557
nsresult rv = CreateAppleMenu(aMenu);
558
NS_ASSERTION ( NS_SUCCEEDED(rv), "Can't create Apple menu" );
561
// add shared Apple menu to our menubar
563
// InsertMenuItem() is 1-based, so the apple/application menu needs to
564
// be at index 1. |mNumMenus| will be incremented below, so the following menu (File)
565
// won't overwrite the apple menu by reusing the ID.
567
::InsertMenuItem(mRootMenu, "\pA", mNumMenus);
568
::SetMenuItemHierarchicalMenu(mRootMenu, 1, sAppleMenu);
572
MenuRef menuRef = nsnull;
573
aMenu->GetNativeData((void**)&menuRef);
576
aMenu->IsHelpMenu(&helpMenu);
578
nsCOMPtr<nsIContent> menu;
579
aMenu->GetMenuContent(getter_AddRefs(menu));
580
nsAutoString menuHidden;
581
menu->GetAttr(kNameSpaceID_None, nsWidgetAtoms::hidden, menuHidden);
582
if( menuHidden != NS_LITERAL_STRING("true")) {
583
// make sure we only increment |mNumMenus| if the menu is visible, since
584
// we use it as an index of where to insert the next menu.
587
::InsertMenuItem(mRootMenu, "\pPlaceholder", mNumMenus);
588
OSStatus status = ::SetMenuItemHierarchicalMenu(mRootMenu, mNumMenus, menuRef);
589
NS_ASSERTION(status == noErr, "nsMenuBarX::AddMenu: SetMenuItemHierarchicalMenu failed.");
600
// build the Apple menu shared by all menu bars.
603
nsMenuBarX :: CreateAppleMenu ( nsIMenu* inMenu )
605
Str32 menuStr = { 1, kMenuAppleLogoFilledGlyph };
606
OSStatus s = ::CreateNewMenu(kAppleMenuID, 0, &sAppleMenu);
608
if ( s == noErr && sAppleMenu ) {
609
::SetMenuTitle(sAppleMenu, menuStr);
611
// this code reads the "label" attribute from the <menuitem/> with
612
// id="aboutName" and puts its label in the Apple Menu
614
nsCOMPtr<nsIContent> menu;
615
inMenu->GetMenuContent(getter_AddRefs(menu));
617
nsCOMPtr<nsIDocument> doc = menu->GetDocument();
619
nsCOMPtr<nsIDOMDocument> domdoc ( do_QueryInterface(doc) );
621
nsCOMPtr<nsIDOMElement> aboutMenuItem;
622
domdoc->GetElementById(NS_LITERAL_STRING("aboutName"), getter_AddRefs(aboutMenuItem));
624
aboutMenuItem->GetAttribute(NS_LITERAL_STRING("label"), label);
629
CFStringRef labelRef = ::CFStringCreateWithCharacters(kCFAllocatorDefault, (UniChar*)label.get(), label.Length());
631
::InsertMenuItemTextWithCFString(sAppleMenu, labelRef, 1, 0, 0);
632
::CFRelease(labelRef);
635
::SetMenuItemCommandID(sAppleMenu, 1, kHICommandAbout);
637
::AppendMenu(sAppleMenu, "\p-");
640
return (s == noErr && sAppleMenu) ? NS_OK : NS_ERROR_FAILURE;
644
//-------------------------------------------------------------------------
645
NS_METHOD nsMenuBarX::GetMenuCount(PRUint32 &aCount)
651
//-------------------------------------------------------------------------
652
NS_METHOD nsMenuBarX::GetMenuAt(const PRUint32 aCount, nsIMenu *& aMenu)
655
nsCOMPtr<nsISupports> supports = getter_AddRefs(mMenusArray.ElementAt(aCount));
656
if (!supports) return NS_OK;
658
return CallQueryInterface(supports, &aMenu); // addref
661
//-------------------------------------------------------------------------
662
NS_METHOD nsMenuBarX::InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu)
667
//-------------------------------------------------------------------------
668
NS_METHOD nsMenuBarX::RemoveMenu(const PRUint32 aCount)
670
mMenusArray.RemoveElementAt(aCount);
671
::DeleteMenuItem(mRootMenu, aCount + 1); // MenuManager is 1-based
676
//-------------------------------------------------------------------------
677
NS_METHOD nsMenuBarX::RemoveAll()
679
NS_ASSERTION(0, "Not implemented!");
680
// mMenusArray.Clear(); // maybe?
684
//-------------------------------------------------------------------------
685
NS_METHOD nsMenuBarX::GetNativeData(void *& aData)
687
aData = (void *) mRootMenu;
691
//-------------------------------------------------------------------------
692
NS_METHOD nsMenuBarX::SetNativeData(void* aData)
695
Handle menubarHandle = (Handle)aData;
696
if (mMacMBarHandle && mMacMBarHandle != menubarHandle)
697
::DisposeHandle(mMacMBarHandle);
698
mMacMBarHandle = menubarHandle;
703
//-------------------------------------------------------------------------
704
NS_METHOD nsMenuBarX::Paint()
706
// hack to correctly swap menu bars.
707
// hopefully this is fast enough.
708
::SetRootMenu(mRootMenu);
716
// nsIDocumentObserver
717
// this is needed for menubar changes
720
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(nsMenuBarX)
721
NS_IMPL_NSIDOCUMENTOBSERVER_REFLOW_STUB(nsMenuBarX)
722
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsMenuBarX)
723
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsMenuBarX)
726
nsMenuBarX::BeginUpdate( nsIDocument * aDocument, nsUpdateType aUpdateType )
731
nsMenuBarX::EndUpdate( nsIDocument * aDocument, nsUpdateType aUpdateType )
736
nsMenuBarX::CharacterDataChanged( nsIDocument * aDocument, nsIContent * aContent, PRBool aAppend)
741
nsMenuBarX::ContentAppended( nsIDocument * aDocument, nsIContent * aContainer,
742
PRInt32 aNewIndexInContainer)
744
if ( aContainer == mMenuBarContent ) {
745
//Register(aContainer, );
746
//InsertMenu ( aNewIndexInContainer );
749
nsCOMPtr<nsIChangeObserver> obs;
750
Lookup ( aContainer, getter_AddRefs(obs) );
752
obs->ContentInserted ( aDocument, aContainer, aNewIndexInContainer );
754
nsCOMPtr<nsIContent> parent = aContainer->GetParent();
756
Lookup ( parent, getter_AddRefs(obs) );
758
obs->ContentInserted ( aDocument, aContainer, aNewIndexInContainer );
765
nsMenuBarX::ContentReplaced( nsIDocument * aDocument, nsIContent * aContainer, nsIContent * aOldChild,
766
nsIContent * aNewChild, PRInt32 aIndexInContainer)
771
nsMenuBarX::DocumentWillBeDestroyed( nsIDocument * aDocument )
778
nsMenuBarX::AttributeChanged( nsIDocument * aDocument, nsIContent * aContent, PRInt32 aNameSpaceID,
779
nsIAtom * aAttribute, PRInt32 aModType)
781
// lookup and dispatch to registered thang.
782
nsCOMPtr<nsIChangeObserver> obs;
783
Lookup ( aContent, getter_AddRefs(obs) );
785
obs->AttributeChanged ( aDocument, aNameSpaceID, aAttribute );
789
nsMenuBarX::ContentRemoved( nsIDocument * aDocument, nsIContent * aContainer,
790
nsIContent * aChild, PRInt32 aIndexInContainer )
792
if ( aContainer == mMenuBarContent ) {
794
RemoveMenu ( aIndexInContainer );
797
nsCOMPtr<nsIChangeObserver> obs;
798
Lookup ( aContainer, getter_AddRefs(obs) );
800
obs->ContentRemoved ( aDocument, aChild, aIndexInContainer );
802
nsCOMPtr<nsIContent> parent = aContainer->GetParent();
804
Lookup ( parent, getter_AddRefs(obs) );
806
obs->ContentRemoved ( aDocument, aChild, aIndexInContainer );
813
nsMenuBarX::ContentInserted( nsIDocument * aDocument, nsIContent * aContainer,
814
nsIContent * aChild, PRInt32 aIndexInContainer )
816
if ( aContainer == mMenuBarContent ) {
817
//Register(aChild, );
818
//InsertMenu ( aIndexInContainer );
821
nsCOMPtr<nsIChangeObserver> obs;
822
Lookup ( aContainer, getter_AddRefs(obs) );
824
obs->ContentInserted ( aDocument, aChild, aIndexInContainer );
826
nsCOMPtr<nsIContent> parent = aContainer->GetParent();
828
Lookup ( parent, getter_AddRefs(obs) );
830
obs->ContentInserted ( aDocument, aChild, aIndexInContainer );
841
// We don't use a |nsSupportsHashtable| because we know that the lifetime of all these items
842
// is bouded by the lifetime of the menubar. No need to add any more strong refs to the
843
// picture because the containment hierarchy already uses strong refs.
847
nsMenuBarX :: Register ( nsIContent *aContent, nsIChangeObserver *aMenuObject )
849
nsVoidKey key ( aContent );
850
mObserverTable.Put ( &key, aMenuObject );
857
nsMenuBarX :: Unregister ( nsIContent *aContent )
859
nsVoidKey key ( aContent );
860
mObserverTable.Remove ( &key );
867
nsMenuBarX :: Lookup ( nsIContent *aContent, nsIChangeObserver **_retval )
871
nsVoidKey key ( aContent );
872
*_retval = NS_REINTERPRET_CAST(nsIChangeObserver*, mObserverTable.Get(&key));
873
NS_IF_ADDREF ( *_retval );
883
// Implementation methods for nsIMenuCommandDispatcher
890
// Given a menu item, creates a unique 4-character command ID and
891
// maps it to the item. Returns the id for use by the client.
894
nsMenuBarX :: Register ( nsIMenuItem* inMenuItem, PRUint32* outCommandID )
896
// no real need to check for uniqueness. We always start afresh with each
897
// window at 1. Even if we did get close to the reserved Apple command id's,
898
// those don't start until at least ' ', which is integer 538976288. If
899
// we have that many menu items in one window, I think we have other problems.
901
// put it in the table, set out param for client
902
nsPRUint32Key key ( mCurrentCommandID );
903
mObserverTable.Put ( &key, inMenuItem );
904
*outCommandID = mCurrentCommandID;
906
// make id unique for next time
916
// Removes the mapping between the given 4-character command ID
917
// and its associated menu item.
920
nsMenuBarX :: Unregister ( PRUint32 inCommandID )
922
nsPRUint32Key key ( inCommandID );
923
mObserverTable.Remove ( &key );
933
// WebShellToPresContext
935
// Helper to dig out a pres context from a webshell. A common thing to do before
936
// sending an event into the dom.
939
MenuHelpersX::WebShellToPresContext (nsIWebShell* inWebShell, nsIPresContext** outContext )
941
NS_ENSURE_ARG_POINTER(outContext);
942
*outContext = nsnull;
944
return NS_ERROR_INVALID_ARG;
946
nsresult retval = NS_OK;
948
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(inWebShell));
950
nsCOMPtr<nsIContentViewer> contentViewer;
951
docShell->GetContentViewer(getter_AddRefs(contentViewer));
952
if ( contentViewer ) {
953
nsCOMPtr<nsIDocumentViewer> docViewer ( do_QueryInterface(contentViewer) );
955
docViewer->GetPresContext(outContext); // AddRefs for us
957
retval = NS_ERROR_FAILURE;
960
retval = NS_ERROR_FAILURE;
964
} // WebShellToPresContext