1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "menu.h"
12 #pragma implementation "menuitem.h"
19 //-----------------------------------------------------------------------------
21 //-----------------------------------------------------------------------------
23 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
,wxWindow
)
25 wxMenuBar::wxMenuBar()
27 m_needParent
= FALSE
; // hmmm
29 PreCreation( (wxWindow
*) NULL
, -1, wxDefaultPosition
, wxDefaultSize
, 0, "menu" );
31 m_menus
.DeleteContents( TRUE
);
33 m_menubar
= gtk_menu_bar_new();
35 m_widget
= GTK_WIDGET(m_menubar
);
42 void wxMenuBar::Append( wxMenu
*menu
, const wxString
&title
)
44 m_menus
.Append( menu
);
45 menu
->m_title
= title
; // ??????
49 pos
= menu
->m_title
.First( '&' );
50 if (pos
!= -1) menu
->m_title
.Remove( pos
, 1 );
54 root_menu
= gtk_menu_item_new_with_label( WXSTRINGCAST(menu
->m_title
) );
55 gtk_widget_show( root_menu
);
56 gtk_menu_item_set_submenu( GTK_MENU_ITEM(root_menu
), menu
->m_menu
);
58 gtk_menu_bar_append( GTK_MENU_BAR(m_menubar
), root_menu
);
61 static int FindMenuItemRecursive( const wxMenu
*menu
, const wxString
&menuString
, const wxString
&itemString
)
63 if (menu
->m_title
== menuString
)
65 int res
= menu
->FindItem( itemString
);
66 if (res
!= -1) return res
;
68 wxNode
*node
= menu
->m_items
.First();
71 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
72 if (item
->IsSubMenu())
73 return FindMenuItemRecursive(item
->GetSubMenu(), menuString
, itemString
);
79 int wxMenuBar::FindMenuItem( const wxString
&menuString
, const wxString
&itemString
) const
81 wxNode
*node
= m_menus
.First();
84 wxMenu
*menu
= (wxMenu
*)node
->Data();
85 int res
= FindMenuItemRecursive( menu
, menuString
, itemString
);
86 if (res
!= -1) return res
;
92 // Find a wxMenuItem using its id. Recurses down into sub-menus
93 static wxMenuItem
* FindMenuItemByIdRecursive(const wxMenu
* menu
, int id
)
95 wxMenuItem
* result
= menu
->FindItem(id
);
97 wxNode
*node
= menu
->m_items
.First();
98 while ( node
&& result
== NULL
) {
99 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
100 if ( item
->IsSubMenu() )
101 result
= FindMenuItemByIdRecursive( item
->GetSubMenu(), id
);
108 wxMenuItem
* wxMenuBar::FindMenuItemById( int id
) const
110 wxMenuItem
* result
= 0;
111 wxNode
*node
= m_menus
.First();
112 while (node
&& result
== 0)
114 wxMenu
*menu
= (wxMenu
*)node
->Data();
115 result
= FindMenuItemByIdRecursive( menu
, id
);
121 void wxMenuBar::Check( int id
, bool check
)
123 wxMenuItem
* item
= FindMenuItemById( id
);
124 if (item
) item
->Check(check
);
127 bool wxMenuBar::Checked( int id
) const
129 wxMenuItem
* item
= FindMenuItemById( id
);
130 if (item
) return item
->IsChecked();
134 void wxMenuBar::Enable( int id
, bool enable
)
136 wxMenuItem
* item
= FindMenuItemById( id
);
137 if (item
) item
->Enable(enable
);
140 bool wxMenuBar::Enabled( int id
) const
142 wxMenuItem
* item
= FindMenuItemById( id
);
143 if (item
) return item
->IsEnabled();
147 //-----------------------------------------------------------------------------
149 //-----------------------------------------------------------------------------
151 static void gtk_menu_clicked_callback( GtkWidget
*widget
, wxMenu
*menu
)
153 int id
= menu
->FindMenuIdByMenuItem(widget
);
155 wxASSERT( id
!= -1 ); // should find it!
157 if (!menu
->IsEnabled(id
)) return;
159 wxCommandEvent
event( wxEVT_COMMAND_MENU_SELECTED
, id
);
160 event
.SetEventObject( menu
);
163 if (menu
->m_callback
)
165 (void) (*(menu
->m_callback
)) (*menu
, event
);
169 if (menu
->GetEventHandler()->ProcessEvent(event
)) return;
171 wxWindow
*win
= menu
->GetInvokingWindow();
172 if (win
) win
->GetEventHandler()->ProcessEvent( event
);
175 //-----------------------------------------------------------------------------
177 //-----------------------------------------------------------------------------
179 static void gtk_menu_hilight_callback( GtkWidget
*widget
, wxMenu
*menu
)
181 int id
= menu
->FindMenuIdByMenuItem(widget
);
183 wxASSERT( id
!= -1 ); // should find it!
185 if (!menu
->IsEnabled(id
)) return;
187 wxCommandEvent
event( wxEVT_MENU_HIGHLIGHT
, id
);
188 event
.SetEventObject( menu
);
191 /* wxMSW doesn't call callback here either
192 if (menu->m_callback)
194 (void) (*(menu->m_callback)) (*menu, event);
199 if (menu
->GetEventHandler()->ProcessEvent(event
)) return;
201 wxWindow
*win
= menu
->GetInvokingWindow();
202 if (win
) win
->GetEventHandler()->ProcessEvent( event
);
205 //-----------------------------------------------------------------------------
207 //-----------------------------------------------------------------------------
209 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
,wxObject
)
211 wxMenuItem::wxMenuItem()
214 m_isCheckMenu
= FALSE
;
217 m_subMenu
= (wxMenu
*) NULL
;
218 m_menuItem
= (GtkWidget
*) NULL
;
221 // it's valid for this function to be called even if m_menuItem == NULL
222 void wxMenuItem::SetName(const wxString
& str
)
225 for ( const char *pc
= str
; *pc
!= '\0'; pc
++ )
235 GtkLabel
*label
= GTK_LABEL( GTK_BIN(m_menuItem
)->child
);
237 gtk_label_set( label
, m_text
.c_str());
241 void wxMenuItem::Check( bool check
)
243 wxCHECK_RET( m_menuItem
, "invalid menu item" );
245 wxCHECK_RET( IsCheckable(), "Can't check uncheckable item!" )
248 gtk_check_menu_item_set_state( (GtkCheckMenuItem
*)m_menuItem
, (gint
)check
);
251 void wxMenuItem::Enable( bool enable
)
253 wxCHECK_RET( m_menuItem
, "invalid menu item" );
255 gtk_widget_set_sensitive( m_menuItem
, enable
);
256 m_isEnabled
= enable
;
259 bool wxMenuItem::IsChecked() const
261 wxCHECK_MSG( m_menuItem
, FALSE
, "invalid menu item" );
263 wxCHECK( IsCheckable(), FALSE
); // can't get state of uncheckable item!
265 bool bIsChecked
= ((GtkCheckMenuItem
*)m_menuItem
)->active
!= 0;
267 wxASSERT( bIsChecked
== m_isChecked
); // consistency check
272 //-----------------------------------------------------------------------------
274 //-----------------------------------------------------------------------------
276 IMPLEMENT_DYNAMIC_CLASS(wxMenu
,wxEvtHandler
)
278 wxMenu::wxMenu( const wxString
& title
, const wxFunction func
)
281 m_items
.DeleteContents( TRUE
);
282 m_invokingWindow
= (wxWindow
*) NULL
;
283 m_menu
= gtk_menu_new(); // Do not show!
286 m_eventHandler
= this;
287 m_clientData
= (void*) NULL
;
289 if (m_title
.IsNull()) m_title
= "";
297 void wxMenu::SetTitle( const wxString
& title
)
299 // Waiting for something better.
303 const wxString
wxMenu::GetTitle() const
308 void wxMenu::AppendSeparator()
310 wxMenuItem
*mitem
= new wxMenuItem();
311 mitem
->SetId(ID_SEPARATOR
);
313 GtkWidget
*menuItem
= gtk_menu_item_new();
314 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
315 gtk_widget_show( menuItem
);
316 mitem
->SetMenuItem(menuItem
);
317 m_items
.Append( mitem
);
320 void wxMenu::Append( int id
, const wxString
&item
, const wxString
&helpStr
, bool checkable
)
322 wxMenuItem
*mitem
= new wxMenuItem();
324 mitem
->SetText(item
);
325 mitem
->SetHelp(helpStr
);
326 mitem
->SetCheckable(checkable
);
327 const char *text
= mitem
->GetText();
328 GtkWidget
*menuItem
= checkable
? gtk_check_menu_item_new_with_label(text
)
329 : gtk_menu_item_new_with_label(text
);
331 mitem
->SetMenuItem(menuItem
);
333 gtk_signal_connect( GTK_OBJECT(menuItem
), "activate",
334 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
),
337 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
338 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
341 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
342 gtk_widget_show( menuItem
);
343 m_items
.Append( mitem
);
346 void wxMenu::Append( int id
, const wxString
&text
, wxMenu
*subMenu
, const wxString
&helpStr
)
348 wxMenuItem
*mitem
= new wxMenuItem();
350 mitem
->SetText(text
);
352 GtkWidget
*menuItem
= gtk_menu_item_new_with_label(mitem
->GetText());
353 mitem
->SetHelp(helpStr
);
354 mitem
->SetMenuItem(menuItem
);
355 mitem
->SetSubMenu(subMenu
);
357 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem
), subMenu
->m_menu
);
358 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
359 gtk_widget_show( menuItem
);
360 m_items
.Append( mitem
);
363 int wxMenu::FindItem( const wxString itemString
) const
365 wxString
s( itemString
);
369 pos
= s
.First( '&' );
370 if (pos
!= -1) s
.Remove( pos
, 1 );
373 wxNode
*node
= m_items
.First();
376 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
377 if (item
->GetText() == s
)
378 return item
->GetId();
385 void wxMenu::Enable( int id
, bool enable
)
387 wxMenuItem
*item
= FindItem(id
);
389 item
->Enable(enable
);
392 bool wxMenu::IsEnabled( int id
) const
394 wxMenuItem
*item
= FindItem(id
);
396 return item
->IsEnabled();
401 void wxMenu::Check( int id
, bool enable
)
403 wxMenuItem
*item
= FindItem(id
);
408 bool wxMenu::IsChecked( int id
) const
410 wxMenuItem
*item
= FindItem(id
);
412 return item
->IsChecked();
417 void wxMenu::SetLabel( int id
, const wxString
&label
)
419 wxMenuItem
*item
= FindItem(id
);
421 item
->SetText(label
);
424 wxString
wxMenu::GetLabel( int id
) const
426 wxMenuItem
*item
= FindItem(id
);
427 if (item
) return item
->GetText();
431 void wxMenu::SetHelpString( int id
, const wxString
& helpString
)
433 wxMenuItem
*item
= FindItem(id
);
434 if (item
) item
->SetHelp( helpString
);
437 wxString
wxMenu::GetHelpString( int id
) const
439 wxMenuItem
*item
= FindItem(id
);
440 if (item
) return item
->GetHelp();
444 int wxMenu::FindMenuIdByMenuItem( GtkWidget
*menuItem
) const
446 wxNode
*node
= m_items
.First();
449 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
450 if (item
->GetMenuItem() == menuItem
)
451 return item
->GetId();
458 wxMenuItem
*wxMenu::FindItem(int id
) const
460 wxNode
*node
= m_items
.First();
462 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
463 if ( item
->GetId() == id
)
468 // Not finding anything here can be correct
469 // when search the entire menu system for
470 // an entry -> no error message.
472 return (wxMenuItem
*) NULL
;
475 void wxMenu::SetInvokingWindow( wxWindow
*win
)
477 m_invokingWindow
= win
;
480 wxWindow
*wxMenu::GetInvokingWindow()
482 return m_invokingWindow
;