]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/app.cpp
just added a comment
[wxWidgets.git] / src / mac / carbon / app.cpp
index 45a5dea76b7d42439bb0547e96fdab7e1d80dccb..af9f64ef31d8a15a30233dfd98245711b28f9e2d 100644 (file)
@@ -350,6 +350,146 @@ void wxApp::MacReopenApp()
     }
 }
 
+//----------------------------------------------------------------------
+// Macintosh CommandID support - converting between native and wx IDs
+//----------------------------------------------------------------------
+
+// if no native match they just return the passed-in id
+
+struct IdPair
+{
+    UInt32 macId ;
+    int wxId ;
+} ;
+
+IdPair gCommandIds [] = 
+{
+    { kHICommandCut ,           wxID_CUT } ,
+    { kHICommandCopy ,          wxID_COPY } ,
+    { kHICommandPaste ,         wxID_PASTE } ,
+    { kHICommandSelectAll ,     wxID_SELECTALL } ,
+    { kHICommandClear ,         wxID_CLEAR } ,
+    { kHICommandUndo ,          wxID_UNDO } ,
+    { kHICommandRedo ,          wxID_REDO } ,
+} ;
+
+int wxMacCommandToId( UInt32 macCommandId ) 
+{
+    int wxid = 0 ;
+    
+    if ( macCommandId == kHICommandPreferences || macCommandId == kHICommandQuit || macCommandId == kHICommandAbout  )
+    {
+        switch ( macCommandId )
+        {
+            case kHICommandPreferences :
+                wxid = wxApp::s_macPreferencesMenuItemId ;
+                break ;
+            case kHICommandQuit :
+                wxid = wxApp::s_macExitMenuItemId ;
+                break ;
+            case kHICommandAbout :
+                wxid = wxApp::s_macAboutMenuItemId ;
+                break ;
+        }
+    }
+    else
+    {
+        for ( size_t i = 0 ; i < WXSIZEOF(gCommandIds) ; ++i )
+        {
+            if ( gCommandIds[i].macId == macCommandId )
+            {
+                wxid = gCommandIds[i].wxId ;
+                break ;
+            }
+        }
+    }
+    if ( wxid == 0 )
+        wxid = (int) macCommandId ;
+    
+    return wxid ;
+}
+
+UInt32 wxIdToMacCommand( int wxId ) 
+{
+    UInt32 macId = 0 ;
+    
+    if ( wxId == wxApp::s_macPreferencesMenuItemId )
+        macId = kHICommandPreferences ;
+    else if (wxId == wxApp::s_macExitMenuItemId)
+        macId = kHICommandQuit ;
+    else if (wxId == wxApp::s_macAboutMenuItemId)
+        macId = kHICommandAbout ;
+    else
+    {
+        for ( size_t i = 0 ; i < WXSIZEOF(gCommandIds) ; ++i )
+        {
+            if ( gCommandIds[i].wxId == wxId )
+            {
+                macId = gCommandIds[i].macId ;
+                break ;
+            }
+        }
+    }
+    if ( macId == 0 )
+        macId = (int) wxId ;
+    
+    return macId ;
+}
+
+wxMenu* wxFindMenuFromMacCommand( const HICommand &command , wxMenuItem* &item ) 
+{
+    wxMenu* itemMenu = NULL ;
+    int id = 0 ;
+    
+    // for 'standard' commands which don't have a wx-menu
+    if ( command.commandID == kHICommandPreferences || command.commandID == kHICommandQuit || command.commandID == kHICommandAbout  )
+    {
+        id = wxMacCommandToId( command.commandID ) ;
+        
+        wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ;
+        if ( mbar )
+        {
+            item = mbar->FindItem( id , &itemMenu ) ;
+        }
+    }
+    else if ( command.commandID != 0 && command.menu.menuRef != 0 && command.menu.menuItemIndex != 0 )
+    {
+        id = wxMacCommandToId( command.commandID ) ;
+        // make sure it is one of our own menus, or of the 'synthetic' apple and help menus , otherwise don't touch
+        MenuItemIndex firstUserHelpMenuItem ;
+        static MenuHandle mh = NULL ;
+        if ( mh == NULL )
+        {
+            if ( UMAGetHelpMenu( &mh , &firstUserHelpMenuItem) != noErr )
+            {
+                mh = NULL ;
+            }
+        }
+        
+        // is it part of the application or the help menu, then look for the id directly
+        if ( ( GetMenuHandle( kwxMacAppleMenuId ) != NULL && command.menu.menuRef == GetMenuHandle( kwxMacAppleMenuId ) ) ||
+             ( mh != NULL && command.menu.menuRef == mh ) )
+        {
+            wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ;
+            if ( mbar )
+            {
+                item = mbar->FindItem( id , &itemMenu ) ;
+            }
+        }
+        else
+        {
+            UInt32 refCon ;
+            GetMenuItemRefCon( command.menu.menuRef , command.menu.menuItemIndex , &refCon ) ;
+            itemMenu = wxFindMenuFromMacMenu( command.menu.menuRef ) ;
+            if ( itemMenu != NULL )
+            {
+                item = (wxMenuItem*) refCon ;
+            }
+        }
+    }
+    return itemMenu ;
+}
+
 //----------------------------------------------------------------------
 // Carbon Event Handler
 //----------------------------------------------------------------------
@@ -438,42 +578,69 @@ static pascal OSStatus wxMacAppCommandEventHandler( EventHandlerCallRef handler
     cEvent.GetParameter<HICommand>(kEventParamDirectObject,typeHICommand,&command) ;
 
     wxMenuItem* item = NULL ;
-    MenuCommand id = command.commandID ;
-    // for items we don't really control
-    if ( id == kHICommandPreferences )
-    {
-        id = wxApp::s_macPreferencesMenuItemId ;
-
-        wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ;
-        if ( mbar )
-        {
-            wxMenu* menu = NULL ;
-            item = mbar->FindItem( id , &menu ) ;
-        }
-    }
-    else if ( id != 0 && command.menu.menuRef != 0 && command.menu.menuItemIndex != 0 )
-    {
-        GetMenuItemRefCon( command.menu.menuRef , command.menu.menuItemIndex , (UInt32*) &item ) ;
-    }
+    wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ;
+    int id = wxMacCommandToId( command.commandID ) ;
 
     if ( item )
     {
-       switch( cEvent.GetKind() )
-       {
-           case kEventProcessCommand :
-           {
+        wxASSERT( itemMenu != NULL ) ;
+        
+        switch( cEvent.GetKind() )
+        {
+            case kEventProcessCommand :
+            {
                 if (item->IsCheckable())
-                {
                     item->Check( !item->IsChecked() ) ;
-                }
 
-                item->GetMenu()->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ;
-                result = noErr ;
+                if ( itemMenu->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) )
+                    result = noErr ;
             }
             break ;
         case kEventCommandUpdateStatus:
-            // eventually trigger an updateui round
-            result = noErr ;
+            {
+                wxUpdateUIEvent event(id);
+                event.SetEventObject( itemMenu );
+                                
+                bool processed = false;
+                
+                // Try the menu's event handler
+                {
+                    wxEvtHandler *handler = itemMenu->GetEventHandler();
+                    if ( handler )
+                        processed = handler->ProcessEvent(event);
+                }
+                
+                // Try the window the menu was popped up from (and up through the
+                // hierarchy)
+                if ( !processed )
+                {
+                    const wxMenuBase *menu = itemMenu;
+                    while ( menu )
+                    {
+                        wxWindow *win = menu->GetInvokingWindow();
+                        if ( win )
+                        {
+                            processed = win->GetEventHandler()->ProcessEvent(event);
+                            break;
+                        }
+                        
+                        menu = menu->GetParent();
+                    }
+                }
+                
+                if ( processed )
+                {
+                    // if anything changed, update the changed attribute
+                    if (event.GetSetText())
+                        itemMenu->SetLabel(id, event.GetText());
+                    if (event.GetSetChecked())
+                        itemMenu->Check(id, event.GetChecked());
+                    if (event.GetSetEnabled())
+                        itemMenu->Enable(id, event.GetEnabled());
+
+                    result = noErr ;
+                }
+            }
             break ;
         default :
             break ;