+wxMenuBar::wxMenuBar( long style )
+{
+ /* the parent window is known after wxFrame::SetMenu() */
+ m_needParent = FALSE;
+ m_style = style;
+ m_invokingWindow = (wxWindow*) NULL;
+
+ if (!PreCreation( (wxWindow*) NULL, wxDefaultPosition, wxDefaultSize ) ||
+ !CreateBase( (wxWindow*) NULL, -1, wxDefaultPosition, wxDefaultSize, style, wxDefaultValidator, wxT("menubar") ))
+ {
+ wxFAIL_MSG( wxT("wxMenuBar creation failed") );
+ return;
+ }
+
+ m_menus.DeleteContents( TRUE );
+
+ /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
+#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
+ m_accel = gtk_accel_group_new();
+ m_factory = gtk_item_factory_new( GTK_TYPE_MENU_BAR, "<main>", m_accel );
+ m_menubar = gtk_item_factory_get_widget( m_factory, "<main>" );
+#else
+ m_menubar = gtk_menu_bar_new();
+#endif
+
+ if (style & wxMB_DOCKABLE)
+ {
+ m_widget = gtk_handle_box_new();
+ gtk_container_add( GTK_CONTAINER(m_widget), GTK_WIDGET(m_menubar) );
+ gtk_widget_show( GTK_WIDGET(m_menubar) );
+ }
+ else
+ {
+ m_widget = GTK_WIDGET(m_menubar);
+ }
+
+ PostCreation();
+}
+
+wxMenuBar::wxMenuBar()
+{
+ /* the parent window is known after wxFrame::SetMenu() */
+ m_needParent = FALSE;
+ m_style = 0;
+ m_invokingWindow = (wxWindow*) NULL;
+
+ if (!PreCreation( (wxWindow*) NULL, wxDefaultPosition, wxDefaultSize ) ||
+ !CreateBase( (wxWindow*) NULL, -1, wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, wxT("menubar") ))
+ {
+ wxFAIL_MSG( wxT("wxMenuBar creation failed") );
+ return;
+ }
+
+ m_menus.DeleteContents( TRUE );
+
+ /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
+#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
+ m_accel = gtk_accel_group_new();
+ m_factory = gtk_item_factory_new( GTK_TYPE_MENU_BAR, "<main>", m_accel );
+ m_menubar = gtk_item_factory_get_widget( m_factory, "<main>" );
+#else
+ m_menubar = gtk_menu_bar_new();
+#endif
+
+ m_widget = GTK_WIDGET(m_menubar);
+
+ PostCreation();
+}
+
+wxMenuBar::~wxMenuBar()
+{
+// gtk_object_unref( GTK_OBJECT(m_factory) ); why not ?
+}
+
+static void wxMenubarUnsetInvokingWindow( wxMenu *menu, wxWindow *win )
+{
+ menu->SetInvokingWindow( (wxWindow*) NULL );
+
+#if (GTK_MINOR_VERSION > 0)
+ wxWindow *top_frame = win;
+ while (top_frame->GetParent() && !(top_frame->IsTopLevel()))
+ top_frame = top_frame->GetParent();
+
+ /* support for native hot keys */
+ gtk_accel_group_detach( menu->m_accel, GTK_OBJECT(top_frame->m_widget) );
+#endif
+
+ wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
+ while (node)
+ {
+ wxMenuItem *menuitem = node->GetData();
+ if (menuitem->IsSubMenu())
+ wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu(), win );
+ node = node->GetNext();
+ }
+}
+
+static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win )
+{
+ menu->SetInvokingWindow( win );
+
+#if (GTK_MINOR_VERSION > 0)
+ wxWindow *top_frame = win;
+ while (top_frame->GetParent() && !(top_frame->IsTopLevel()))
+ top_frame = top_frame->GetParent();
+
+ /* support for native hot keys */
+ gtk_accel_group_attach( menu->m_accel, GTK_OBJECT(top_frame->m_widget) );
+#endif
+
+ wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
+ while (node)
+ {
+ wxMenuItem *menuitem = node->GetData();
+ if (menuitem->IsSubMenu())
+ wxMenubarSetInvokingWindow( menuitem->GetSubMenu(), win );
+ node = node->GetNext();
+ }
+}
+
+void wxMenuBar::SetInvokingWindow( wxWindow *win )
+{
+ m_invokingWindow = win;
+#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
+ wxWindow *top_frame = win;
+ while (top_frame->GetParent() && !(top_frame->IsTopLevel()))
+ top_frame = top_frame->GetParent();
+
+ /* support for native key accelerators indicated by underscroes */
+ gtk_accel_group_attach( m_accel, GTK_OBJECT(top_frame->m_widget) );
+#endif
+
+ wxMenuList::Node *node = m_menus.GetFirst();
+ while (node)
+ {
+ wxMenu *menu = node->GetData();
+ wxMenubarSetInvokingWindow( menu, win );
+ node = node->GetNext();
+ }
+}
+
+void wxMenuBar::UnsetInvokingWindow( wxWindow *win )
+{
+ m_invokingWindow = (wxWindow*) NULL;
+#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
+ wxWindow *top_frame = win;
+ while (top_frame->GetParent() && !(top_frame->IsTopLevel()))
+ top_frame = top_frame->GetParent();
+
+ /* support for native key accelerators indicated by underscroes */
+ gtk_accel_group_detach( m_accel, GTK_OBJECT(top_frame->m_widget) );
+#endif
+
+ wxMenuList::Node *node = m_menus.GetFirst();
+ while (node)
+ {
+ wxMenu *menu = node->GetData();
+ wxMenubarUnsetInvokingWindow( menu, win );
+ node = node->GetNext();
+ }
+}
+
+bool wxMenuBar::Append( wxMenu *menu, const wxString &title )
+{
+ m_menus.Append( menu );
+
+ const wxChar *pc;
+
+ /* GTK 1.2 wants to have "_" instead of "&" for accelerators */
+ wxString str;
+ for ( pc = title; *pc != wxT('\0'); pc++ )
+ {
+ if (*pc == wxT('&'))
+ {
+#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
+ str << wxT('_');
+ }
+ else if (*pc == wxT('/'))
+ {
+ str << wxT('\\');
+#endif
+ }
+ else
+ {
+#if __WXGTK12__
+ if ( *pc == wxT('_') )
+ {
+ // underscores must be doubled to prevent them from being
+ // interpreted as accelerator character prefix by GTK
+ str << *pc;
+ }
+#endif // GTK+ 1.2
+
+ str << *pc;
+ }
+ }
+
+ /* this doesn't have much effect right now */
+ menu->SetTitle( str );
+
+ /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
+#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
+
+ /* local buffer in multibyte form */
+ wxString buf;
+ buf << wxT('/') << str.c_str();
+
+ char *cbuf = new char[buf.Length()+1];
+ strcpy(cbuf, buf.mbc_str());
+
+ GtkItemFactoryEntry entry;
+ entry.path = (gchar *)cbuf; // const_cast
+ entry.accelerator = (gchar*) NULL;
+ entry.callback = (GtkItemFactoryCallback) NULL;
+ entry.callback_action = 0;
+ entry.item_type = "<Branch>";
+
+ 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 */
+ wxString tmp = wxT("<main>/");
+ for ( pc = str; *pc != wxT('\0'); pc++ )
+ {
+ // contrary to the common sense, we must throw out _all_ underscores,
+ // (i.e. "Hello__World" => "HelloWorld" and not "Hello_World" as we
+ // might naively think). IMHO it's a bug in GTK+ (VZ)
+ while (*pc == wxT('_'))
+ pc++;
+ tmp << *pc;
+ }
+ menu->m_owner = gtk_item_factory_get_item( m_factory, tmp.mb_str() );
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu->m_owner), menu->m_menu );
+ delete [] cbuf;
+#else
+
+ menu->m_owner = gtk_menu_item_new_with_label( str.mb_str() );
+ gtk_widget_show( menu->m_owner );
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu->m_owner), menu->m_menu );
+
+ gtk_menu_bar_append( GTK_MENU_BAR(m_menubar), menu->m_owner );
+
+#endif
+
+ // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
+ // adding menu later on.
+ if (m_invokingWindow)
+ wxMenubarSetInvokingWindow( menu, m_invokingWindow );
+
+ return TRUE;
+}
+
+bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
+{
+ if ( !wxMenuBarBase::Insert(pos, menu, title) )
+ return FALSE;
+
+ wxFAIL_MSG(wxT("TODO"));
+
+ return FALSE;
+}
+
+wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
+{
+ if ( !wxMenuBarBase::Replace(pos, menu, title) )
+ return FALSE;
+
+ wxFAIL_MSG(wxT("TODO"));
+
+ return NULL;
+}
+
+wxMenu *wxMenuBar::Remove(size_t pos)
+{
+ if ( !wxMenuBarBase::Remove(pos) )
+ return FALSE;
+
+ wxFAIL_MSG(wxT("TODO"));
+
+ return NULL;
+}
+
+static int FindMenuItemRecursive( const wxMenu *menu, const wxString &menuString, const wxString &itemString )
+{
+ if (menu->GetTitle() == menuString)
+ {
+ int res = menu->FindItem( itemString );
+ if (res != wxNOT_FOUND)
+ return res;
+ }
+
+ wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
+ while (node)
+ {
+ wxMenuItem *item = node->GetData();
+ if (item->IsSubMenu())
+ return FindMenuItemRecursive(item->GetSubMenu(), menuString, itemString);
+
+ node = node->GetNext();
+ }
+
+ return wxNOT_FOUND;
+}