wxWidgets/src/cocoa/mbarman.mm
Dimitri Schoolwerth 80fdcdb90e No changes, synchronised source names that appear commented at the top of files with the actual path to the files.
Fixed commented names (path, filename, and extension) of files in include/ and src/. Prepended the names in src/ with "src/" everywhere, while starting those in include/wx/ with "wx/".

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@67254 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2011-03-20 00:14:35 +00:00

400 lines
14 KiB
Plaintext

/////////////////////////////////////////////////////////////////////////////
// Name: src/cocoa/mbarman.mm
// Purpose: wxMenuBarManager implementation
// Author: David Elliott
// Modified by:
// Created: 2003/09/04
// RCS-ID: $Id$
// Copyright: (c) 2003 David Elliott
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_MENUS
#ifndef WX_PRECOMP
#include "wx/log.h"
#include "wx/app.h"
#include "wx/menu.h"
#include "wx/toplevel.h"
#endif // WX_PRECOMP
#include "wx/cocoa/mbarman.h"
#include "wx/cocoa/autorelease.h"
#include "wx/cocoa/objc/objc_uniquifying.h"
#import <Foundation/NSString.h>
#import <Foundation/NSNotification.h>
#import <AppKit/NSMenu.h>
#import <AppKit/NSApplication.h>
#import <AppKit/NSWindow.h>
#ifndef wxUSE_FSCRIPT
#define wxUSE_FSCRIPT 0
#endif
#if wxUSE_FSCRIPT
#import <FScript/FScriptMenuItem.h>
#endif
// Declare setAppleMenu: in an NSApplication category since Tiger and later
// releases support it but don't declare it as it's considered deprecated.
@interface NSApplication(wxDeprecatedMethodsWeWantToUse)
- (void)setAppleMenu:(NSMenu *)menu;
@end
// ============================================================================
// wxMenuBarManagerObserver
// ============================================================================
@interface wxMenuBarManagerObserver : NSObject
{
wxMenuBarManager *m_mbarman;
}
- (id)init;
- (id)initWithWxMenuBarManager: (wxMenuBarManager *)mbarman;
- (void)windowDidBecomeKey: (NSNotification *)notification;
#if 0
- (void)windowDidResignKey: (NSNotification *)notification;
- (void)windowDidBecomeMain: (NSNotification *)notification;
- (void)windowDidResignMain: (NSNotification *)notification;
- (void)windowWillClose: (NSNotification *)notification;
#endif // 0
@end // interface wxMenuBarManagerObserver : NSObject
WX_DECLARE_GET_OBJC_CLASS(wxMenuBarManagerObserver,NSObject)
@implementation wxMenuBarManagerObserver : NSObject
- (id)init
{
wxFAIL_MSG(wxT("[wxMenuBarManagerObserver -init] should never be called!"));
m_mbarman = NULL;
return self;
}
- (id)initWithWxMenuBarManager: (wxMenuBarManager *)mbarman
{
wxASSERT(mbarman);
m_mbarman = mbarman;
return [super init];
}
- (void)windowDidBecomeKey: (NSNotification *)notification
{
wxASSERT(m_mbarman);
m_mbarman->WindowDidBecomeKey(notification);
}
#if 0
- (void)windowDidResignKey: (NSNotification *)notification
{
wxASSERT(m_mbarman);
m_mbarman->WindowDidResignKey(notification);
}
- (void)windowDidBecomeMain: (NSNotification *)notification
{
wxASSERT(m_mbarman);
m_mbarman->WindowDidBecomeMain(notification);
}
- (void)windowDidResignMain: (NSNotification *)notification
{
wxASSERT(m_mbarman);
m_mbarman->WindowDidResignMain(notification);
}
- (void)windowWillClose: (NSNotification *)notification
{
wxASSERT(m_mbarman);
m_mbarman->WindowWillClose(notification);
}
#endif // 0
@end // implementation wxMenuBarManagerObserver : NSObject
WX_IMPLEMENT_GET_OBJC_CLASS(wxMenuBarManagerObserver,NSObject)
// ============================================================================
// wxMenuBarManager
// ============================================================================
wxMenuBarManager *wxMenuBarManager::sm_mbarmanInstance = NULL;
static void AddFScriptItem(NSMenu *menu)
#if wxUSE_FSCRIPT
{
NSMenuItem *item = [[FScriptMenuItem alloc] init];
[menu addItem: item];
[item release];
}
#else
{}
#endif
wxMenuBarManager::wxMenuBarManager()
{
m_observer = [[WX_GET_OBJC_CLASS(wxMenuBarManagerObserver) alloc]
initWithWxMenuBarManager:this];
[[NSNotificationCenter defaultCenter] addObserver:m_observer
selector:@selector(windowDidBecomeKey:)
name:NSWindowDidBecomeKeyNotification object:nil];
// HACK: Reuse the same selector and eventual C++ method and make it
// check for whether the notification is to become key or main.
[[NSNotificationCenter defaultCenter] addObserver:m_observer
selector:@selector(windowDidBecomeKey:)
name:NSWindowDidBecomeMainNotification object:nil];
#if 0
[[NSNotificationCenter defaultCenter] addObserver:m_observer
selector:@selector(windowDidResignKey:)
name:NSWindowDidResignKeyNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:m_observer
selector:@selector(windowDidBecomeMain:)
name:NSWindowDidBecomeMainNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:m_observer
selector:@selector(windowDidResignMain:)
name:NSWindowDidResignMainNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:m_observer
selector:@selector(windowWillClose:)
name:NSWindowWillCloseNotification object:nil];
#endif // 0
m_menuApp = nil;
m_menuServices = nil;
m_menuWindows = nil;
m_menuMain = nil;
m_mainMenuBarInstalled = true;
m_mainMenuBar = NULL;
m_currentNSWindow = nil;
NSApplication *theNSApplication = wxTheApp->GetNSApplication();
// Create the services menu.
m_menuServices = [[NSMenu alloc] initWithTitle: @"Services"];
[theNSApplication setServicesMenu:m_menuServices];
NSMenuItem *menuitem;
// Create the application (Apple) menu.
m_menuApp = [[NSMenu alloc] initWithTitle: @"Apple Menu"];
/**/[m_menuApp addItemWithTitle:@"Preferences..." action:nil keyEquivalent:@""];
/**/[m_menuApp addItem: [NSMenuItem separatorItem]];
/**/AddFScriptItem(m_menuApp);
/**/menuitem = [[NSMenuItem alloc] initWithTitle: @"Services" action:nil keyEquivalent:@""];
[menuitem setSubmenu:m_menuServices];
[m_menuApp addItem: menuitem];
[menuitem release];
/**/[m_menuApp addItem: [NSMenuItem separatorItem]];
/**/menuitem = [[NSMenuItem alloc] initWithTitle:@"Hide" action:@selector(hide:) keyEquivalent:@""];
[menuitem setTarget: theNSApplication];
[m_menuApp addItem: menuitem];
[menuitem release];
/**/menuitem = [[NSMenuItem alloc] initWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@""];
[menuitem setTarget: theNSApplication];
[m_menuApp addItem: menuitem];
[menuitem release];
/**/menuitem = [[NSMenuItem alloc] initWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
[menuitem setTarget: theNSApplication];
[m_menuApp addItem: menuitem];
[menuitem release];
/**/[m_menuApp addItem: [NSMenuItem separatorItem]];
/**/menuitem = [[NSMenuItem alloc] initWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"];
[menuitem setTarget: theNSApplication];
[m_menuApp addItem: menuitem];
[menuitem release];
[theNSApplication setAppleMenu:m_menuApp];
// Create the Windows menu
m_menuWindows = [[NSMenu alloc] initWithTitle: @"Window"];
/**/[m_menuWindows addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@""];
/**/[m_menuWindows addItem: [NSMenuItem separatorItem]];
/**/[m_menuWindows addItemWithTitle:@"Bring All to Front" action:@selector(arrangeInFront:) keyEquivalent:@""];
[theNSApplication setWindowsMenu:m_menuWindows];
// Create the main menubar
m_menuMain = [[NSMenu alloc] initWithTitle: @"wxApp Menu"];
/**/NSMenuItem *dummyItem = [[NSMenuItem alloc] initWithTitle:@"App menu"
/* Note: title gets clobbered by app name anyway */
action:nil keyEquivalent:@""];
[dummyItem setSubmenu:m_menuApp];
[m_menuMain addItem:dummyItem];
[dummyItem release];
/**/dummyItem = [[NSMenuItem alloc] initWithTitle:@"Window"
action:nil keyEquivalent:@""];
[dummyItem setSubmenu:m_menuWindows];
[m_menuMain addItem:dummyItem];
[dummyItem release];
[theNSApplication setMainMenu: m_menuMain];
}
wxMenuBarManager::~wxMenuBarManager()
{
[m_observer release];
}
void wxMenuBarManager::CreateInstance()
{
sm_mbarmanInstance = new wxMenuBarManager;
}
void wxMenuBarManager::DestroyInstance()
{
delete sm_mbarmanInstance;
sm_mbarmanInstance = NULL;
}
void wxMenuBarManager::SetMenuBar(wxMenuBar* menubar)
{
m_mainMenuBarInstalled = false;
if(menubar)
{
[[[wxTheApp->GetNSApplication() mainMenu] itemAtIndex:0] setSubmenu:nil];
[[menubar->GetNSMenu() itemAtIndex:0] setSubmenu:m_menuApp];
[wxTheApp->GetNSApplication() setMainMenu:menubar->GetNSMenu()];
}
else
InstallMainMenu();
}
void wxMenuBarManager::SetMainMenuBar(wxMenuBar* menubar)
{
m_mainMenuBar = menubar;
if(m_mainMenuBarInstalled)
InstallMainMenu();
}
void wxMenuBarManager::InstallMainMenu()
{
if(m_mainMenuBar)
SetMenuBar(m_mainMenuBar);
else
{
m_mainMenuBarInstalled = true;
[[[wxTheApp->GetNSApplication() mainMenu] itemAtIndex:0] setSubmenu:nil];
[[m_menuMain itemAtIndex:0] setSubmenu:m_menuApp];
[wxTheApp->GetNSApplication() setMainMenu:m_menuMain];
}
}
void wxMenuBarManager::WindowDidBecomeKey(NSNotification *notification)
{
/* NOTE: m_currentNSWindow might be destroyed but we only ever use it
to look it up in the hash table. Do not send messages to it. */
/* Update m_currentNSWindow only if we really should. For instance,
if a non-wx window is becoming key but a wx window remains main
then don't change out the menubar. However, if a non-wx window
(whether the same window or not) is main, then switch to the
generic menubar so the wx window that last installed a menubar
doesn't get menu events it doesn't expect.
If a wx window is becoming main then check to see if the key
window is a wx window and if so do nothing because that
is what would have been done before.
If a non-wx window is becoming main and
*/
NSString *notificationName = [notification name];
if(NULL == notificationName)
return;
else if([NSWindowDidBecomeKeyNotification isEqualTo:notificationName])
{ // This is the only one that was handled in 2.8 as shipped
// Generally the key window can change without the main window changing.
// The user can do this simply by clicking on something in a palette window
// that needs to become key.
NSWindow *newKeyWindow = [notification object];
wxCocoaNSWindow *theWxKeyWindow = wxCocoaNSWindow::GetFromCocoa(newKeyWindow);
if(theWxKeyWindow != NULL)
{ // If the new key window is a wx window, handle it as before
// even if it has not actually changed.
m_currentNSWindow = newKeyWindow;
}
else
{ // If the new key window is not wx then check the main window.
NSWindow *mainWindow = [[NSApplication sharedApplication] mainWindow];
if(m_currentNSWindow == mainWindow)
// Don't reset if the menubar doesn't need to change.
return;
else
// This is strange because theoretically we should have picked this up
// already in the main window notification but it's possible that
// we simply haven't gotten it yet and will about as soon as we return.
// We already know that the key window isn't wx so fall back to this
// one and let the code go ahead and set the wx menubar if it is
// a wx window and set the generic one if it isn't.
m_currentNSWindow = mainWindow;
}
}
else if([NSWindowDidBecomeMainNotification isEqualTo:notificationName])
{ // Handling this is new
// Generally the main window cannot change without the key window changing
// because if the user clicks on a window that can become main then the
// window will also become key.
// However, it's possible that when it becomes main it automatically makes
// some palette the key window.
NSWindow *newMainWindow = [notification object];
// If we already know about the window, bail.
if(newMainWindow == m_currentNSWindow)
return;
else
{
NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow];
if(keyWindow == m_currentNSWindow)
// if we already know about the key window, bail
return;
else
{ // As above, sort of strange. Neither one is current. Prefer key over main.
wxCocoaNSWindow *theWxMainWindow = wxCocoaNSWindow::GetFromCocoa(keyWindow);
if(theWxMainWindow != NULL)
m_currentNSWindow = keyWindow;
else
m_currentNSWindow = newMainWindow;
}
}
}
m_currentNSWindow = [notification object];
wxCocoaNSWindow *win = wxCocoaNSWindow::GetFromCocoa(m_currentNSWindow);
if(win)
InstallMenuBarForWindow(win);
else
SetMenuBar(NULL);
}
#if 0
void wxMenuBarManager::WindowDidResignKey(NSNotification *notification)
{
}
void wxMenuBarManager::WindowDidBecomeMain(NSNotification *notification)
{
}
void wxMenuBarManager::WindowDidResignMain(NSNotification *notification)
{
}
void wxMenuBarManager::WindowWillClose(NSNotification *notification)
{
}
#endif // 0
void wxMenuBarManager::InstallMenuBarForWindow(wxCocoaNSWindow *win)
{
wxASSERT(win);
wxMenuBar *menubar = win->GetAppMenuBar(win);
wxLogTrace(wxTRACE_COCOA,wxT("Found menubar=%p for window=%p."),menubar,win);
SetMenuBar(menubar);
}
void wxMenuBarManager::UpdateMenuBar()
{
if(m_currentNSWindow)
{
wxCocoaNSWindow *win = wxCocoaNSWindow::GetFromCocoa(m_currentNSWindow);
if(win)
InstallMenuBarForWindow(win);
}
}
#endif // wxUSE_MENUS