+void wxMenuBar::Init(size_t n, wxMenu *menus[], const wxString titles[], long style)
+{
+ m_invokingWindow = NULL;
+
+#if wxUSE_LIBHILDON
+ // Hildon window uses a single menu instead of a menu bar, so wxMenuBar is
+ // the same as menu in this case
+ m_widget =
+ m_menubar = gtk_menu_new();
+#else // !wxUSE_LIBHILDON
+ if (!PreCreation( NULL, wxDefaultPosition, wxDefaultSize ) ||
+ !CreateBase( NULL, -1, wxDefaultPosition, wxDefaultSize, style, wxDefaultValidator, wxT("menubar") ))
+ {
+ wxFAIL_MSG( wxT("wxMenuBar creation failed") );
+ return;
+ }
+
+ m_menubar = gtk_menu_bar_new();
+
+ if (style & wxMB_DOCKABLE)
+ {
+ m_widget = gtk_handle_box_new();
+ gtk_container_add(GTK_CONTAINER(m_widget), m_menubar);
+ gtk_widget_show(m_menubar);
+ }
+ else
+ {
+ m_widget = m_menubar;
+ }
+
+ PostCreation();
+
+ ApplyWidgetStyle();
+#endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON
+
+ for (size_t i = 0; i < n; ++i )
+ Append(menus[i], titles[i]);
+}
+
+wxMenuBar::wxMenuBar(size_t n, wxMenu *menus[], const wxString titles[], long style)
+{
+ Init(n, menus, titles, style);
+}
+
+wxMenuBar::wxMenuBar(long style)
+{
+ Init(0, NULL, NULL, style);
+}
+
+wxMenuBar::wxMenuBar()
+{
+ Init(0, NULL, NULL, 0);
+}
+
+wxMenuBar::~wxMenuBar()
+{
+}
+
+static void
+wxMenubarUnsetInvokingWindow(wxMenu* menu, wxWindow* win, GtkWindow* tlw = NULL)
+{
+ menu->SetInvokingWindow( (wxWindow*) NULL );
+
+ // support for native hot keys
+ if (menu->m_accel)
+ {
+ if (tlw == NULL)
+ tlw = GTK_WINDOW(wxGetTopLevelParent(win)->m_widget);
+ if (g_slist_find(menu->m_accel->acceleratables, tlw))
+ gtk_window_remove_accel_group(tlw, menu->m_accel);
+ }
+
+ wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
+ while (node)
+ {
+ wxMenuItem *menuitem = node->GetData();
+ if (menuitem->IsSubMenu())
+ wxMenubarUnsetInvokingWindow(menuitem->GetSubMenu(), win, tlw);
+ node = node->GetNext();
+ }
+}
+
+static void
+wxMenubarSetInvokingWindow(wxMenu* menu, wxWindow* win, GtkWindow* tlw = NULL)
+{
+ menu->SetInvokingWindow( win );
+
+ // support for native hot keys
+ if (menu->m_accel)
+ {
+ if (tlw == NULL)
+ tlw = GTK_WINDOW(wxGetTopLevelParent(win)->m_widget);
+ if (!g_slist_find(menu->m_accel->acceleratables, tlw))
+ gtk_window_add_accel_group(tlw, menu->m_accel);
+ }
+
+ wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
+ while (node)
+ {
+ wxMenuItem *menuitem = node->GetData();
+ if (menuitem->IsSubMenu())
+ wxMenubarSetInvokingWindow(menuitem->GetSubMenu(), win, tlw);
+ node = node->GetNext();
+ }
+}
+
+void wxMenuBar::SetInvokingWindow( wxWindow *win )
+{
+ m_invokingWindow = win;
+
+ wxMenuList::compatibility_iterator node = m_menus.GetFirst();
+ while (node)
+ {
+ wxMenu *menu = node->GetData();
+ wxMenubarSetInvokingWindow( menu, win );
+ node = node->GetNext();
+ }
+}
+
+void wxMenuBar::SetLayoutDirection(wxLayoutDirection dir)
+{
+ if ( dir == wxLayout_Default )
+ {
+ const wxWindow *const frame = GetFrame();
+ if ( frame )
+ {
+ // inherit layout from frame.
+ dir = frame->GetLayoutDirection();
+ }
+ else // use global layout
+ {
+ dir = wxTheApp->GetLayoutDirection();
+ }
+ }
+
+ if ( dir == wxLayout_Default )
+ return;
+
+ GTKSetLayout(m_menubar, dir);
+
+ // also set the layout of all menus we already have (new ones will inherit
+ // the current layout)
+ for ( wxMenuList::compatibility_iterator node = m_menus.GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ wxMenu *const menu = node->GetData();
+ menu->SetLayoutDirection(dir);
+ }
+}
+
+wxLayoutDirection wxMenuBar::GetLayoutDirection() const
+{
+ return GTKGetLayout(m_menubar);
+}
+
+void wxMenuBar::Attach(wxFrame *frame)
+{
+ wxMenuBarBase::Attach(frame);
+
+ SetLayoutDirection(wxLayout_Default);
+}
+
+void wxMenuBar::UnsetInvokingWindow( wxWindow *win )
+{
+ m_invokingWindow = (wxWindow*) NULL;
+
+ wxMenuList::compatibility_iterator node = m_menus.GetFirst();
+ while (node)
+ {
+ wxMenu *menu = node->GetData();
+ wxMenubarUnsetInvokingWindow( menu, win );
+ node = node->GetNext();
+ }
+}
+
+bool wxMenuBar::Append( wxMenu *menu, const wxString &title )
+{
+ if ( !wxMenuBarBase::Append( menu, title ) )
+ return false;
+
+ return GtkAppend(menu, title);
+}
+
+bool wxMenuBar::GtkAppend(wxMenu *menu, const wxString& title, int pos)
+{
+ menu->SetLayoutDirection(GetLayoutDirection());
+
+#if wxUSE_LIBHILDON
+ // if the menu has only one item, append it directly to the top level menu
+ // instead of inserting a useless submenu
+ if ( menu->GetMenuItemCount() == 1 )
+ {
+ wxMenuItem * const item = menu->FindItemByPosition(0);
+
+ // remove both mnemonics and accelerator: neither is useful under Maemo
+ const wxString str(wxStripMenuCodes(item->GetItemLabel()));
+
+ if ( item->IsSubMenu() )
+ return GtkAppend(item->GetSubMenu(), str, pos);
+
+ menu->m_owner = gtk_menu_item_new_with_mnemonic( wxGTK_CONV( str ) );
+
+ g_signal_connect(menu->m_owner, "activate",
+ G_CALLBACK(gtk_menu_clicked_callback), menu);
+ item->SetMenuItem(menu->m_owner);
+ }
+ else
+#endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON
+ {
+ const wxString str(wxConvertMnemonicsToGTK(title));
+
+ // This doesn't have much effect right now.
+ menu->SetTitle( str );
+
+ // The "m_owner" is the "menu item"
+ menu->m_owner = gtk_menu_item_new_with_mnemonic( wxGTK_CONV( str ) );
+
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu->m_owner), menu->m_menu );
+ }
+
+ gtk_widget_show( menu->m_owner );
+
+ if (pos == -1)
+ gtk_menu_shell_append( GTK_MENU_SHELL(m_menubar), menu->m_owner );
+ else
+ gtk_menu_shell_insert( GTK_MENU_SHELL(m_menubar), menu->m_owner, pos );
+
+ // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
+ // addings 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;
+
+ // TODO
+
+ if ( !GtkAppend(menu, title, (int)pos) )
+ return false;
+
+ return true;
+}
+
+wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
+{
+ // remove the old item and insert a new one
+ wxMenu *menuOld = Remove(pos);
+ if ( menuOld && !Insert(pos, menu, title) )
+ {
+ return (wxMenu*) NULL;
+ }
+
+ // either Insert() succeeded or Remove() failed and menuOld is NULL
+ return menuOld;
+}
+
+wxMenu *wxMenuBar::Remove(size_t pos)
+{
+ wxMenu *menu = wxMenuBarBase::Remove(pos);
+ if ( !menu )
+ return (wxMenu*) NULL;
+
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu->m_owner), NULL);
+ gtk_container_remove(GTK_CONTAINER(m_menubar), menu->m_owner);
+
+ gtk_widget_destroy( menu->m_owner );
+ menu->m_owner = NULL;
+
+ if (m_invokingWindow)
+ wxMenubarUnsetInvokingWindow( menu, m_invokingWindow );
+
+ return menu;
+}
+