X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d9e403cc40c289cf77950f3b5ac1dd057cdd142c..aedcc0dc8266fbc73d6bb513bf6c6b0f17932afa:/src/gtk/menu.cpp diff --git a/src/gtk/menu.cpp b/src/gtk/menu.cpp index 34cec7b657..dea54b9e72 100644 --- a/src/gtk/menu.cpp +++ b/src/gtk/menu.cpp @@ -161,6 +161,25 @@ static wxString wxReplaceUnderscore( const wxString& title ) return str; } +//----------------------------------------------------------------------------- +// activate message from GTK +//----------------------------------------------------------------------------- + +static void gtk_menu_open_callback( GtkWidget *widget, wxMenu *menu ) +{ + if (g_isIdle) wxapp_install_idle_handler(); + + wxMenuEvent event( wxEVT_MENU_OPEN, -1 ); + event.SetEventObject( menu ); + + wxEvtHandler* handler = menu->GetEventHandler(); + if (handler && handler->ProcessEvent(event)) + return; + + wxWindow *win = menu->GetInvokingWindow(); + if (win) win->GetEventHandler()->ProcessEvent( event ); +} + //----------------------------------------------------------------------------- // wxMenuBar //----------------------------------------------------------------------------- @@ -357,7 +376,7 @@ bool wxMenuBar::GtkAppend(wxMenu *menu, const wxString& title) buf << wxT('/') << str.c_str(); // local buffer in multibyte form - char cbuf[400]; + char cbuf[400]; strcpy(cbuf, wxGTK_CONV(buf) ); GtkItemFactoryEntry entry; @@ -368,7 +387,7 @@ bool wxMenuBar::GtkAppend(wxMenu *menu, const wxString& title) entry.item_type = (char *)""; gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); // what is 2 ? - // in order to get the pointer to the item we need the item text _without_ underscores + // in order to get the pointer to the item we need the item text _without_ underscores wxString tmp = wxT("
/"); const wxChar *pc; for ( pc = str; *pc != wxT('\0'); pc++ ) @@ -392,6 +411,10 @@ bool wxMenuBar::GtkAppend(wxMenu *menu, const wxString& title) #endif + gtk_signal_connect( GTK_OBJECT(menu->m_owner), "activate", + GTK_SIGNAL_FUNC(gtk_menu_open_callback), + (gpointer)menu ); + // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables // addings menu later on. if (m_invokingWindow) @@ -471,10 +494,10 @@ static wxMenu *CopyMenu (wxMenu *menu) else menucopy->Append (itemid, text, CopyMenu(submenu), menu->GetHelpString(itemid)); - + node = node->GetNext(); } - + return menucopy; } @@ -684,7 +707,7 @@ static void gtk_menu_clicked_callback( GtkWidget *widget, wxMenu *menu ) if (item->IsCheckable()) { bool isReallyChecked = item->IsChecked(), - isInternallyChecked = item->wxMenuItemBase::IsChecked(); + isInternallyChecked = item->wxMenuItemBase::IsChecked(); // ensure that the internal state is always consistent with what is // shown on the screen @@ -697,11 +720,36 @@ static void gtk_menu_clicked_callback( GtkWidget *widget, wxMenu *menu ) { return; } + } + - // the user pressed on the menu item: report the event below + // Is this menu on a menubar? (possibly nested) + wxFrame* frame = NULL; + wxMenu* pm = menu; + while ( pm && !frame ) + { + if ( pm->IsAttached() ) + frame = pm->GetMenuBar()->GetFrame(); + pm = pm->GetParent(); } - menu->SendEvent(id, item->IsCheckable() ? item->IsChecked() : -1); + if (frame) + { + // If it is attached then let the frame send the event. + // Don't call frame->ProcessCommand(id) because it toggles + // checkable items and we've already done that above. + wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id); + commandEvent.SetEventObject(frame); + if (item->IsCheckable()) + commandEvent.SetInt(item->IsChecked()); + + frame->GetEventHandler()->ProcessEvent(commandEvent); + } + else + { + // otherwise let the menu have it + menu->SendEvent(id, item->IsCheckable() ? item->IsChecked() : -1); + } } //----------------------------------------------------------------------------- @@ -722,7 +770,8 @@ static void gtk_menu_hilight_callback( GtkWidget *widget, wxMenu *menu ) wxMenuEvent event( wxEVT_MENU_HIGHLIGHT, id ); event.SetEventObject( menu ); - if (menu->GetEventHandler()->ProcessEvent(event)) + wxEvtHandler* handler = menu->GetEventHandler(); + if (handler && handler->ProcessEvent(event)) return; wxWindow *win = menu->GetInvokingWindow(); @@ -747,7 +796,8 @@ static void gtk_menu_nolight_callback( GtkWidget *widget, wxMenu *menu ) wxMenuEvent event( wxEVT_MENU_HIGHLIGHT, -1 ); event.SetEventObject( menu ); - if (menu->GetEventHandler()->ProcessEvent(event)) + wxEvtHandler* handler = menu->GetEventHandler(); + if (handler && handler->ProcessEvent(event)) return; wxWindow *win = menu->GetInvokingWindow(); @@ -839,10 +889,10 @@ wxString wxMenuItemBase::GetLabelFromText(const wxString& text) // "&" is doubled to indicate "&" instead of accelerator continue; } - + label += *pc; } - + // wxPrintf( L"text %s label %s\n", text.c_str(), label.c_str() ); return label; @@ -857,7 +907,7 @@ void wxMenuItem::SetText( const wxString& str ) wxString label1 = wxStripMenuCodes(str.BeforeFirst('\t')); if (oldLabel == label1) return; - + DoSetText(str); if (m_menuItem) @@ -876,7 +926,7 @@ void wxMenuItem::SetText( const wxString& str ) if (m_text[n] != wxT('\\')) tmp += m_text[n]; } - + gtk_label_set_text_with_mnemonic( GTK_LABEL(label), wxGTK_CONV(tmp) ); #else // set new text @@ -936,9 +986,9 @@ void wxMenuItem::DoSetText( const wxString& str ) } ++pc; } - + // wxPrintf( L"str %s m_text %s\n", str.c_str(), m_text.c_str() ); - + m_hotKey = wxT(""); if(*pc == wxT('\t')) @@ -1074,7 +1124,8 @@ wxMenu::~wxMenu() { m_items.Clear(); - gtk_widget_destroy( m_menu ); + if ( GTK_IS_WIDGET( m_menu )) + gtk_widget_destroy( m_menu ); gtk_object_unref( GTK_OBJECT(m_factory) ); } @@ -1147,16 +1198,36 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) GtkWidget *label = gtk_accel_label_new ( wxGTK_CONV( text ) ); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_container_add (GTK_CONTAINER (menuItem), label); - guint accel_key = gtk_label_parse_uline (GTK_LABEL(label), wxGTK_CONV( text ) ); gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), menuItem); + guint accel_key; + GdkModifierType accel_mods; + + // accelerator for the item, as specified by its label + // (ex. Ctrl+O for open) + gtk_accelerator_parse(GetHotKey(*mitem).c_str(), + &accel_key, &accel_mods); if (accel_key != GDK_VoidSymbol) { gtk_widget_add_accelerator (menuItem, "activate_item", - gtk_menu_ensure_uline_accel_group (GTK_MENU (m_menu)), + gtk_menu_get_accel_group( + GTK_MENU(m_menu)), + accel_key, accel_mods, + GTK_ACCEL_VISIBLE); + } + + // accelerator for the underlined char (ex ALT+F for the File menu) + accel_key = gtk_label_parse_uline (GTK_LABEL(label), wxGTK_CONV( text ) ); + if (accel_key != GDK_VoidSymbol) + { + gtk_widget_add_accelerator (menuItem, + "activate_item", + gtk_menu_ensure_uline_accel_group ( + GTK_MENU (m_menu)), accel_key, 0, GTK_ACCEL_LOCKED); } + gtk_widget_show (label); mitem->SetLabelWidget(label); @@ -1168,8 +1239,9 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) gtk_signal_connect( GTK_OBJECT(menuItem), "activate", GTK_SIGNAL_FUNC(gtk_menu_clicked_callback), (gpointer)this ); - + gtk_menu_append( GTK_MENU(m_menu), menuItem ); + gtk_widget_show( menuItem ); appended = TRUE; // We've done this, don't do it again @@ -1254,7 +1326,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) wxString path( mitem->GetFactoryPath() ); menuItem = gtk_item_factory_get_widget( m_factory, wxGTK_CONV( path ) ); - + if (!menuItem) wxLogError( wxT("Wrong menu path: %s\n"), path.c_str() ); } @@ -1262,7 +1334,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) if ( !mitem->IsSeparator() ) { wxASSERT_MSG( menuItem, wxT("invalid menuitem") ); - + gtk_signal_connect( GTK_OBJECT(menuItem), "select", GTK_SIGNAL_FUNC(gtk_menu_hilight_callback), (gpointer)this );