]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/menu.cpp
The colour is called Aquamarine, not Aquaramine. No,
[wxWidgets.git] / src / gtk1 / menu.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: menu.cpp
3// Purpose:
4// Author: Robert Roebling
96fd301f 5// Id: $Id$
a81258be 6// Copyright: (c) 1998 Robert Roebling
96fd301f 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
c801d85f
KB
10#ifdef __GNUG__
11#pragma implementation "menu.h"
6ca41e57 12#pragma implementation "menuitem.h"
c801d85f
KB
13#endif
14
15#include "wx/menu.h"
96fd301f 16#include "wx/log.h"
30dea054 17#include "wx/intl.h"
06cfab17 18#include "wx/app.h"
c801d85f 19
83624f79
RR
20#include "gdk/gdk.h"
21#include "gtk/gtk.h"
22
c801d85f
KB
23//-----------------------------------------------------------------------------
24// wxMenuBar
25//-----------------------------------------------------------------------------
26
27IMPLEMENT_DYNAMIC_CLASS(wxMenuBar,wxWindow)
28
3502e687
RR
29wxMenuBar::wxMenuBar( long style )
30{
1e133b7d
RR
31 /* the parent window is known after wxFrame::SetMenu() */
32 m_needParent = FALSE;
3502e687 33
16bcc879 34 PreCreation( (wxWindow *) NULL, -1, wxDefaultPosition, wxDefaultSize, style, "menu" );
3502e687
RR
35
36 m_menus.DeleteContents( TRUE );
37
1e133b7d
RR
38 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
39#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
40 m_accel = gtk_accel_group_new();
41 m_factory = gtk_item_factory_new( GTK_TYPE_MENU_BAR, "<main>", m_accel );
42 m_menubar = gtk_item_factory_get_widget( m_factory, "<main>" );
43#else
3502e687 44 m_menubar = gtk_menu_bar_new();
1e133b7d 45#endif
3502e687
RR
46
47 if (style & wxMB_DOCKABLE)
48 {
49 m_widget = gtk_handle_box_new();
c626a8b7
VZ
50 gtk_container_add( GTK_CONTAINER(m_widget), GTK_WIDGET(m_menubar) );
51 gtk_widget_show( GTK_WIDGET(m_menubar) );
3502e687
RR
52 }
53 else
54 {
55 m_widget = GTK_WIDGET(m_menubar);
56 }
57
58 PostCreation();
59
60 Show( TRUE );
61}
62
96fd301f 63wxMenuBar::wxMenuBar()
c801d85f 64{
1e133b7d
RR
65 /* the parent window is known after wxFrame::SetMenu() */
66 m_needParent = FALSE;
96fd301f 67
83624f79 68 PreCreation( (wxWindow *) NULL, -1, wxDefaultPosition, wxDefaultSize, 0, "menu" );
c801d85f 69
83624f79 70 m_menus.DeleteContents( TRUE );
96fd301f 71
1e133b7d
RR
72 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
73#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
74 m_accel = gtk_accel_group_new();
75 m_factory = gtk_item_factory_new( GTK_TYPE_MENU_BAR, "<main>", m_accel );
76 m_menubar = gtk_item_factory_get_widget( m_factory, "<main>" );
77#else
83624f79 78 m_menubar = gtk_menu_bar_new();
1e133b7d 79#endif
8bbe427f 80
828f655f 81 m_widget = GTK_WIDGET(m_menubar);
96fd301f 82
83624f79 83 PostCreation();
c801d85f 84
83624f79 85 Show( TRUE );
6de97a3b 86}
c801d85f 87
1e133b7d
RR
88wxMenuBar::~wxMenuBar()
89{
90 // how to destroy a GtkItemFactory ?
91}
92
c801d85f
KB
93void wxMenuBar::Append( wxMenu *menu, const wxString &title )
94{
83624f79 95 m_menus.Append( menu );
034be888 96
1e133b7d
RR
97 /* GTK 1.2 wants to have "_" instead of "&" for accelerators */
98 wxString str;
b019151f 99 for ( const wxChar *pc = title; *pc != _T('\0'); pc++ )
83624f79 100 {
b019151f 101 if (*pc == _T('&'))
034be888
RR
102 {
103 pc++; /* skip it */
1e133b7d
RR
104#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
105 str << _T('_');
034be888
RR
106#endif
107 }
1e133b7d
RR
108 str << *pc;
109 }
110
111 /* this doesn't have much effect right now */
112 menu->SetTitle( str );
113
114 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
115#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
116
117 /* local buffer in multibyte form */
118 char buf[200];
119 strcpy( buf, "/" );
120 strcat( buf, str.mb_str() );
121
122 GtkItemFactoryEntry entry;
123 entry.path = buf;
124 entry.accelerator = (gchar*) NULL;
125 entry.callback = (GtkItemFactoryCallback) NULL;
126 entry.callback_action = 0;
127 entry.item_type = "<Branch>";
128
129 gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
130
131 /* in order to get the pointer to the item we need the item text _without_ underscores */
132 wxString tmp = _T("<main>/");
133 for ( const wxChar *pc = str; *pc != _T('\0'); pc++ )
134 {
135 if (*pc == _T('_')) pc++; /* skip it */
136 tmp << *pc;
034be888 137 }
1e133b7d
RR
138
139 menu->m_owner = gtk_item_factory_get_item( m_factory, tmp.mb_str() );
140
141 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu->m_owner), menu->m_menu );
142
143#else
96fd301f 144
1e133b7d 145 menu->m_owner = gtk_menu_item_new_with_label( str.mb_str() );
2b1c162e
RR
146 gtk_widget_show( menu->m_owner );
147 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu->m_owner), menu->m_menu );
96fd301f 148
2b1c162e 149 gtk_menu_bar_append( GTK_MENU_BAR(m_menubar), menu->m_owner );
1e133b7d
RR
150
151#endif
6de97a3b 152}
96fd301f 153
716b7364 154static int FindMenuItemRecursive( const wxMenu *menu, const wxString &menuString, const wxString &itemString )
c801d85f 155{
c626a8b7 156 if (menu->GetTitle() == menuString)
83624f79
RR
157 {
158 int res = menu->FindItem( itemString );
c626a8b7
VZ
159 if (res != wxNOT_FOUND)
160 return res;
83624f79 161 }
c626a8b7
VZ
162
163 wxNode *node = ((wxMenu *)menu)->GetItems().First(); // const_cast
83624f79
RR
164 while (node)
165 {
166 wxMenuItem *item = (wxMenuItem*)node->Data();
167 if (item->IsSubMenu())
168 return FindMenuItemRecursive(item->GetSubMenu(), menuString, itemString);
2b1c162e 169
83624f79
RR
170 node = node->Next();
171 }
172
c626a8b7
VZ
173 return wxNOT_FOUND;
174}
175
176wxMenuItem *wxMenuBar::FindItemForId(int itemId, wxMenu **menuForItem = NULL) const
177{
178 if ( menuForItem )
179 {
180 // TODO return the pointer to the menu
181
182 *menuForItem = NULL;
183 }
184
185 return FindItem(itemId);
6de97a3b 186}
c801d85f
KB
187
188int wxMenuBar::FindMenuItem( const wxString &menuString, const wxString &itemString ) const
189{
83624f79
RR
190 wxNode *node = m_menus.First();
191 while (node)
192 {
193 wxMenu *menu = (wxMenu*)node->Data();
194 int res = FindMenuItemRecursive( menu, menuString, itemString);
195 if (res != -1) return res;
196 node = node->Next();
197 }
198 return -1;
6de97a3b 199}
c801d85f 200
c626a8b7 201// Find a wxMenuItem using its id. Recurses down into sub-menus
96fd301f 202static wxMenuItem* FindMenuItemByIdRecursive(const wxMenu* menu, int id)
716b7364 203{
83624f79 204 wxMenuItem* result = menu->FindItem(id);
716b7364 205
c626a8b7
VZ
206 wxNode *node = ((wxMenu *)menu)->GetItems().First(); // const_cast
207 while ( node && result == NULL )
83624f79
RR
208 {
209 wxMenuItem *item = (wxMenuItem*)node->Data();
210 if (item->IsSubMenu())
c626a8b7 211 {
83624f79 212 result = FindMenuItemByIdRecursive( item->GetSubMenu(), id );
c626a8b7 213 }
83624f79
RR
214 node = node->Next();
215 }
96fd301f 216
83624f79 217 return result;
6de97a3b 218}
716b7364 219
c626a8b7 220wxMenuItem* wxMenuBar::FindItem( int id ) const
716b7364 221{
83624f79
RR
222 wxMenuItem* result = 0;
223 wxNode *node = m_menus.First();
224 while (node && result == 0)
225 {
226 wxMenu *menu = (wxMenu*)node->Data();
227 result = FindMenuItemByIdRecursive( menu, id );
228 node = node->Next();
229 }
c626a8b7 230
83624f79 231 return result;
716b7364
RR
232}
233
54ff4a70
RR
234void wxMenuBar::Check( int id, bool check )
235{
83624f79 236 wxMenuItem* item = FindMenuItemById( id );
c626a8b7 237
b019151f 238 wxCHECK_RET( item, _T("wxMenuBar::Check: no such item") );
c626a8b7
VZ
239
240 item->Check(check);
6de97a3b 241}
54ff4a70 242
c626a8b7 243bool wxMenuBar::IsChecked( int id ) const
716b7364 244{
83624f79 245 wxMenuItem* item = FindMenuItemById( id );
c626a8b7 246
b019151f 247 wxCHECK_MSG( item, FALSE, _T("wxMenuBar::IsChecked: no such item") );
c626a8b7
VZ
248
249 return item->IsChecked();
6de97a3b 250}
716b7364 251
54ff4a70
RR
252void wxMenuBar::Enable( int id, bool enable )
253{
83624f79 254 wxMenuItem* item = FindMenuItemById( id );
c626a8b7 255
b019151f 256 wxCHECK_RET( item, _T("wxMenuBar::Enable: no such item") );
c626a8b7
VZ
257
258 item->Enable(enable);
6de97a3b 259}
54ff4a70 260
c626a8b7 261bool wxMenuBar::IsEnabled( int id ) const
716b7364 262{
83624f79 263 wxMenuItem* item = FindMenuItemById( id );
c626a8b7 264
b019151f 265 wxCHECK_MSG( item, FALSE, _T("wxMenuBar::IsEnabled: no such item") );
c626a8b7
VZ
266
267 return item->IsEnabled();
6de97a3b 268}
716b7364 269
bbe0af5b
RR
270wxString wxMenuBar::GetLabel( int id ) const
271{
272 wxMenuItem* item = FindMenuItemById( id );
c626a8b7 273
b019151f 274 wxCHECK_MSG( item, _T(""), _T("wxMenuBar::GetLabel: no such item") );
c626a8b7
VZ
275
276 return item->GetText();
bbe0af5b
RR
277}
278
279void wxMenuBar::SetLabel( int id, const wxString &label )
280{
281 wxMenuItem* item = FindMenuItemById( id );
c626a8b7 282
b019151f 283 wxCHECK_RET( item, _T("wxMenuBar::SetLabel: no such item") );
c626a8b7
VZ
284
285 item->SetText( label );
bbe0af5b
RR
286}
287
2b1c162e 288void wxMenuBar::EnableTop( int pos, bool flag )
bbe0af5b 289{
2b1c162e 290 wxNode *node = m_menus.Nth( pos );
c626a8b7 291
b019151f 292 wxCHECK_RET( node, _T("menu not found") );
c626a8b7 293
2b1c162e 294 wxMenu* menu = (wxMenu*)node->Data();
c626a8b7
VZ
295
296 if (menu->m_owner)
297 gtk_widget_set_sensitive( menu->m_owner, flag );
bbe0af5b
RR
298}
299
2b1c162e 300wxString wxMenuBar::GetLabelTop( int pos ) const
bbe0af5b 301{
2b1c162e 302 wxNode *node = m_menus.Nth( pos );
c626a8b7 303
b019151f 304 wxCHECK_MSG( node, _T("invalid"), _T("menu not found") );
c626a8b7 305
2b1c162e 306 wxMenu* menu = (wxMenu*)node->Data();
c626a8b7 307
2b1c162e 308 return menu->GetTitle();
bbe0af5b
RR
309}
310
2b1c162e 311void wxMenuBar::SetLabelTop( int pos, const wxString& label )
bbe0af5b 312{
2b1c162e 313 wxNode *node = m_menus.Nth( pos );
c626a8b7 314
b019151f 315 wxCHECK_RET( node, _T("menu not found") );
c626a8b7 316
2b1c162e 317 wxMenu* menu = (wxMenu*)node->Data();
c626a8b7 318
2b1c162e 319 menu->SetTitle( label );
bbe0af5b
RR
320}
321
342b6a2f
RR
322void wxMenuBar::SetHelpString( int id, const wxString& helpString )
323{
324 wxMenuItem* item = FindMenuItemById( id );
c626a8b7 325
b019151f 326 wxCHECK_RET( item, _T("wxMenuBar::SetHelpString: no such item") );
c626a8b7
VZ
327
328 item->SetHelp( helpString );
342b6a2f
RR
329}
330
331wxString wxMenuBar::GetHelpString( int id ) const
332{
333 wxMenuItem* item = FindMenuItemById( id );
c626a8b7 334
b019151f 335 wxCHECK_MSG( item, _T(""), _T("wxMenuBar::GetHelpString: no such item") );
c626a8b7
VZ
336
337 return item->GetHelp();
342b6a2f
RR
338}
339
c801d85f 340//-----------------------------------------------------------------------------
cf7a7e13 341// "activate"
c801d85f
KB
342//-----------------------------------------------------------------------------
343
6de97a3b 344static void gtk_menu_clicked_callback( GtkWidget *widget, wxMenu *menu )
c801d85f 345{
83624f79 346 int id = menu->FindMenuIdByMenuItem(widget);
96fd301f 347
83624f79 348 /* should find it for normal (not popup) menu */
c626a8b7 349 wxASSERT( (id != -1) || (menu->GetInvokingWindow() != NULL) );
96fd301f 350
c626a8b7
VZ
351 if (!menu->IsEnabled(id))
352 return;
96fd301f 353
2d17d68f 354 wxMenuItem* item = menu->FindItem( id );
b019151f 355 wxCHECK_RET( item, _T("error in menu item callback") );
c626a8b7
VZ
356
357 if (item->IsCheckable())
2d17d68f 358 {
c626a8b7 359 if (item->GetCheckedFlag() == item->IsChecked())
2d17d68f 360 {
c626a8b7 361 /* the menu item has been checked by calling wxMenuItem->Check() */
2d17d68f 362 return;
c626a8b7
VZ
363 }
364 else
365 {
366 /* the user pressed on the menu item -> report */
367 item->SetCheckedFlag(item->IsChecked()); /* make consistent again */
368 }
2d17d68f
RR
369 }
370
83624f79
RR
371 wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, id );
372 event.SetEventObject( menu );
373 event.SetInt(id );
8bbe427f 374
c626a8b7 375 if (menu->GetCallback())
83624f79 376 {
c626a8b7 377 (void) (*(menu->GetCallback())) (*menu, event);
83624f79
RR
378 return;
379 }
cf7a7e13 380
c626a8b7
VZ
381 if (menu->GetEventHandler()->ProcessEvent(event))
382 return;
cf7a7e13 383
83624f79 384 wxWindow *win = menu->GetInvokingWindow();
c626a8b7
VZ
385 if (win)
386 win->GetEventHandler()->ProcessEvent( event );
cf7a7e13
RR
387}
388
389//-----------------------------------------------------------------------------
390// "select"
391//-----------------------------------------------------------------------------
392
393static void gtk_menu_hilight_callback( GtkWidget *widget, wxMenu *menu )
394{
83624f79
RR
395 int id = menu->FindMenuIdByMenuItem(widget);
396
397 wxASSERT( id != -1 ); // should find it!
cf7a7e13 398
c626a8b7
VZ
399 if (!menu->IsEnabled(id))
400 return;
cf7a7e13 401
342b6a2f 402 wxMenuEvent event( wxEVT_MENU_HIGHLIGHT, id );
83624f79 403 event.SetEventObject( menu );
cf7a7e13 404
83624f79 405/* wxMSW doesn't call callback here either
8bbe427f 406
83624f79
RR
407 if (menu->m_callback)
408 {
409 (void) (*(menu->m_callback)) (*menu, event);
410 return;
411 }
13439807 412*/
6de97a3b 413
c626a8b7
VZ
414 if (menu->GetEventHandler()->ProcessEvent(event))
415 return;
6de97a3b 416
83624f79
RR
417 wxWindow *win = menu->GetInvokingWindow();
418 if (win) win->GetEventHandler()->ProcessEvent( event );
6de97a3b 419}
c801d85f 420
cd743a6f
RR
421//-----------------------------------------------------------------------------
422// "deselect"
423//-----------------------------------------------------------------------------
424
425static void gtk_menu_nolight_callback( GtkWidget *widget, wxMenu *menu )
426{
427 int id = menu->FindMenuIdByMenuItem(widget);
428
429 wxASSERT( id != -1 ); // should find it!
430
c626a8b7
VZ
431 if (!menu->IsEnabled(id))
432 return;
cd743a6f
RR
433
434 wxMenuEvent event( wxEVT_MENU_HIGHLIGHT, -1 );
435 event.SetEventObject( menu );
436
c626a8b7
VZ
437 if (menu->GetEventHandler()->ProcessEvent(event))
438 return;
cd743a6f
RR
439
440 wxWindow *win = menu->GetInvokingWindow();
c626a8b7
VZ
441 if (win)
442 win->GetEventHandler()->ProcessEvent( event );
cd743a6f
RR
443}
444
cf7a7e13 445//-----------------------------------------------------------------------------
db1b4961 446// wxMenuItem
cf7a7e13
RR
447//-----------------------------------------------------------------------------
448
c801d85f 449IMPLEMENT_DYNAMIC_CLASS(wxMenuItem,wxObject)
96fd301f
VZ
450
451wxMenuItem::wxMenuItem()
c801d85f 452{
83624f79
RR
453 m_id = ID_SEPARATOR;
454 m_isCheckMenu = FALSE;
455 m_isChecked = FALSE;
456 m_isEnabled = TRUE;
457 m_subMenu = (wxMenu *) NULL;
458 m_menuItem = (GtkWidget *) NULL;
6de97a3b 459}
c801d85f 460
c626a8b7 461// it's valid for this function to be called even if m_menuItem == NULL
83624f79 462void wxMenuItem::SetName( const wxString& str )
716b7364 463{
b019151f
OK
464 m_text = _T("");
465 for ( const wxChar *pc = str; *pc != _T('\0'); pc++ )
83624f79 466 {
b019151f 467 if (*pc == _T('&'))
034be888
RR
468 {
469 pc++; /* skip it */
470#if (GTK_MINOR_VERSION > 0)
b019151f 471 m_text << _T('_');
034be888
RR
472#endif
473 }
83624f79
RR
474 m_text << *pc;
475 }
96fd301f 476
83624f79
RR
477 if (m_menuItem)
478 {
479 GtkLabel *label = GTK_LABEL( GTK_BIN(m_menuItem)->child );
1e133b7d 480 gtk_label_set( label, m_text.mb_str());
83624f79 481 }
716b7364
RR
482}
483
96fd301f 484void wxMenuItem::Check( bool check )
716b7364 485{
b019151f 486 wxCHECK_RET( m_menuItem, _T("invalid menu item") );
db1b4961 487
b019151f 488 wxCHECK_RET( IsCheckable(), _T("Can't check uncheckable item!") )
96fd301f 489
2d17d68f
RR
490 if (check == m_isChecked) return;
491
83624f79
RR
492 m_isChecked = check;
493 gtk_check_menu_item_set_state( (GtkCheckMenuItem*)m_menuItem, (gint)check );
716b7364
RR
494}
495
8bbe427f
VZ
496void wxMenuItem::Enable( bool enable )
497{
b019151f 498 wxCHECK_RET( m_menuItem, _T("invalid menu item") );
db1b4961 499
83624f79
RR
500 gtk_widget_set_sensitive( m_menuItem, enable );
501 m_isEnabled = enable;
a9c96bcc
RR
502}
503
96fd301f 504bool wxMenuItem::IsChecked() const
716b7364 505{
b019151f 506 wxCHECK_MSG( m_menuItem, FALSE, _T("invalid menu item") );
db1b4961 507
83624f79 508 wxCHECK( IsCheckable(), FALSE ); // can't get state of uncheckable item!
96fd301f 509
83624f79 510 bool bIsChecked = ((GtkCheckMenuItem*)m_menuItem)->active != 0;
96fd301f 511
83624f79 512 return bIsChecked;
716b7364
RR
513}
514
db1b4961 515//-----------------------------------------------------------------------------
83624f79 516// wxMenu
db1b4961
RR
517//-----------------------------------------------------------------------------
518
c801d85f
KB
519IMPLEMENT_DYNAMIC_CLASS(wxMenu,wxEvtHandler)
520
6de97a3b 521wxMenu::wxMenu( const wxString& title, const wxFunction func )
c801d85f 522{
83624f79
RR
523 m_title = title;
524 m_items.DeleteContents( TRUE );
525 m_invokingWindow = (wxWindow *) NULL;
034be888
RR
526
527#if (GTK_MINOR_VERSION > 0)
528 m_accel = gtk_accel_group_new();
529 m_factory = gtk_item_factory_new( GTK_TYPE_MENU, "<main>", m_accel );
530 m_menu = gtk_item_factory_get_widget( m_factory, "<main>" );
531#else
83624f79 532 m_menu = gtk_menu_new(); // Do not show!
034be888 533#endif
8bbe427f 534
83624f79
RR
535 m_callback = func;
536 m_eventHandler = this;
537 m_clientData = (void*) NULL;
8bbe427f 538
b019151f
OK
539 if (m_title.IsNull()) m_title = _T("");
540 if (m_title != _T(""))
83624f79
RR
541 {
542 Append(-2, m_title);
543 AppendSeparator();
544 }
c626a8b7 545
2b1c162e 546 m_owner = (GtkWidget*) NULL;
6de97a3b 547}
c801d85f 548
034be888
RR
549wxMenu::~wxMenu()
550{
551 /* how do we delete an item-factory ? */
552}
553
c2dd8380
GL
554void wxMenu::SetTitle( const wxString& title )
555{
c626a8b7 556 // TODO Waiting for something better
83624f79 557 m_title = title;
c2dd8380
GL
558}
559
560const wxString wxMenu::GetTitle() const
561{
83624f79 562 return m_title;
c2dd8380
GL
563}
564
96fd301f 565void wxMenu::AppendSeparator()
c801d85f 566{
83624f79
RR
567 wxMenuItem *mitem = new wxMenuItem();
568 mitem->SetId(ID_SEPARATOR);
96fd301f 569
83624f79
RR
570 GtkWidget *menuItem = gtk_menu_item_new();
571 gtk_menu_append( GTK_MENU(m_menu), menuItem );
572 gtk_widget_show( menuItem );
034be888 573
83624f79
RR
574 mitem->SetMenuItem(menuItem);
575 m_items.Append( mitem );
6de97a3b 576}
c801d85f 577
debe6624 578void wxMenu::Append( int id, const wxString &item, const wxString &helpStr, bool checkable )
c801d85f 579{
83624f79
RR
580 wxMenuItem *mitem = new wxMenuItem();
581 mitem->SetId(id);
582 mitem->SetText(item);
583 mitem->SetHelp(helpStr);
584 mitem->SetCheckable(checkable);
034be888
RR
585
586#if (GTK_MINOR_VERSION > 0)
1e133b7d
RR
587 /* text has "_" instead of "&" after mitem->SetText() */
588 wxString text( mitem->GetText() );
589
590 /* local buffer in multibyte form */
591 char buf[200];
592 strcpy( buf, "/" );
593 strcat( buf, text.mb_str() );
034be888
RR
594
595 GtkItemFactoryEntry entry;
1e133b7d 596 entry.path = buf;
034be888
RR
597 entry.accelerator = (gchar*) NULL;
598 entry.callback = (GtkItemFactoryCallback) gtk_menu_clicked_callback;
599 entry.callback_action = 0;
600 if (checkable)
601 entry.item_type = "<CheckItem>";
602 else
603 entry.item_type = "<Item>";
604
605 gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
606
607 /* in order to get the pointer to the item we need the item text _without_ underscores */
b019151f
OK
608 wxString s = _T("<main>/");
609 for ( const wxChar *pc = text; *pc != _T('\0'); pc++ )
034be888 610 {
b019151f 611 if (*pc == _T('_')) pc++; /* skip it */
034be888
RR
612 s << *pc;
613 }
614
1e133b7d 615 GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, s.mb_str() );
034be888
RR
616
617#else
618
1e133b7d
RR
619 GtkWidget *menuItem = checkable ? gtk_check_menu_item_new_with_label( item.mb_str() )
620 : gtk_menu_item_new_with_label( item.mb_str() );
034be888 621
83624f79
RR
622 gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
623 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
034be888
RR
624 (gpointer)this );
625
626 gtk_menu_append( GTK_MENU(m_menu), menuItem );
627 gtk_widget_show( menuItem );
628
629#endif
96fd301f 630
83624f79
RR
631 gtk_signal_connect( GTK_OBJECT(menuItem), "select",
632 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
034be888 633 (gpointer)this );
cf7a7e13 634
cd743a6f
RR
635 gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
636 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
034be888
RR
637 (gpointer)this );
638
639 mitem->SetMenuItem(menuItem);
cd743a6f 640
83624f79 641 m_items.Append( mitem );
6de97a3b 642}
c801d85f 643
96fd301f 644void wxMenu::Append( int id, const wxString &text, wxMenu *subMenu, const wxString &helpStr )
c801d85f 645{
83624f79
RR
646 wxMenuItem *mitem = new wxMenuItem();
647 mitem->SetId(id);
648 mitem->SetText(text);
828f655f 649 mitem->SetHelp(helpStr);
96fd301f 650
b019151f 651 GtkWidget *menuItem = gtk_menu_item_new_with_label(mitem->GetText().mbc_str());
83624f79
RR
652 mitem->SetMenuItem(menuItem);
653 mitem->SetSubMenu(subMenu);
96fd301f 654
cd743a6f
RR
655 gtk_signal_connect( GTK_OBJECT(menuItem), "select",
656 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
657 (gpointer*)this );
658
659 gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
660 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
661 (gpointer*)this );
662
83624f79
RR
663 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem), subMenu->m_menu );
664 gtk_menu_append( GTK_MENU(m_menu), menuItem );
665 gtk_widget_show( menuItem );
666 m_items.Append( mitem );
6de97a3b 667}
c801d85f 668
828f655f
RR
669void wxMenu::Append( wxMenuItem *item )
670{
671 m_items.Append( item );
c626a8b7 672
828f655f
RR
673 GtkWidget *menuItem = (GtkWidget*) NULL;
674
c626a8b7 675 if (item->IsSeparator())
828f655f 676 menuItem = gtk_menu_item_new();
c626a8b7 677 else if (item->IsSubMenu())
b019151f 678 menuItem = gtk_menu_item_new_with_label(item->GetText().mbc_str());
c626a8b7 679 else
b019151f
OK
680 menuItem = item->IsCheckable() ? gtk_check_menu_item_new_with_label(item->GetText().mbc_str())
681 : gtk_menu_item_new_with_label(item->GetText().mbc_str());
828f655f
RR
682
683 if (!item->IsSeparator())
684 {
685 gtk_signal_connect( GTK_OBJECT(menuItem), "select",
686 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
687 (gpointer*)this );
688
689 gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
690 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
691 (gpointer*)this );
c626a8b7
VZ
692
693 if (!item->IsSubMenu())
694 {
828f655f
RR
695 gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
696 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
697 (gpointer*)this );
c626a8b7 698 }
828f655f 699 }
c626a8b7 700
828f655f
RR
701 gtk_menu_append( GTK_MENU(m_menu), menuItem );
702 gtk_widget_show( menuItem );
703 item->SetMenuItem(menuItem);
704}
705
c801d85f
KB
706int wxMenu::FindItem( const wxString itemString ) const
707{
b019151f
OK
708 wxString s = _T("");
709 for ( const wxChar *pc = itemString; *pc != _T('\0'); pc++ )
83624f79 710 {
b019151f 711 if (*pc == _T('&'))
034be888
RR
712 {
713 pc++; /* skip it */
714#if (GTK_MINOR_VERSION > 0)
b019151f 715 s << _T('_');
034be888
RR
716#endif
717 }
718 s << *pc;
719 }
96fd301f 720
83624f79
RR
721 wxNode *node = m_items.First();
722 while (node)
723 {
724 wxMenuItem *item = (wxMenuItem*)node->Data();
725 if (item->GetText() == s)
c626a8b7 726 {
83624f79 727 return item->GetId();
c626a8b7 728 }
83624f79
RR
729 node = node->Next();
730 }
96fd301f 731
c626a8b7 732 return wxNOT_FOUND;
6de97a3b 733}
c801d85f 734
96fd301f 735void wxMenu::Enable( int id, bool enable )
716b7364 736{
83624f79 737 wxMenuItem *item = FindItem(id);
c626a8b7 738
b019151f 739 wxCHECK_RET( item, _T("wxMenu::Enable: no such item") );
c626a8b7
VZ
740
741 item->Enable(enable);
6de97a3b 742}
716b7364 743
96fd301f 744bool wxMenu::IsEnabled( int id ) const
e2414cbe 745{
83624f79 746 wxMenuItem *item = FindItem(id);
c626a8b7 747
b019151f 748 wxCHECK_MSG( item, FALSE, _T("wxMenu::IsEnabled: no such item") );
c626a8b7
VZ
749
750 return item->IsEnabled();
6de97a3b 751}
e2414cbe 752
96fd301f 753void wxMenu::Check( int id, bool enable )
c801d85f 754{
83624f79 755 wxMenuItem *item = FindItem(id);
c626a8b7 756
b019151f 757 wxCHECK_RET( item, _T("wxMenu::Check: no such item") );
c626a8b7
VZ
758
759 item->Check(enable);
6de97a3b 760}
c801d85f 761
96fd301f 762bool wxMenu::IsChecked( int id ) const
c801d85f 763{
83624f79 764 wxMenuItem *item = FindItem(id);
c626a8b7 765
b019151f 766 wxCHECK_MSG( item, FALSE, _T("wxMenu::IsChecked: no such item") );
c626a8b7
VZ
767
768 return item->IsChecked();
6de97a3b 769}
c801d85f 770
debe6624 771void wxMenu::SetLabel( int id, const wxString &label )
c801d85f 772{
83624f79 773 wxMenuItem *item = FindItem(id);
c626a8b7 774
b019151f 775 wxCHECK_RET( item, _T("wxMenu::SetLabel: no such item") );
c626a8b7
VZ
776
777 item->SetText(label);
6de97a3b 778}
96fd301f 779
c33c4050
RR
780wxString wxMenu::GetLabel( int id ) const
781{
83624f79 782 wxMenuItem *item = FindItem(id);
c626a8b7 783
b019151f 784 wxCHECK_MSG( item, _T(""), _T("wxMenu::GetLabel: no such item") );
c626a8b7
VZ
785
786 return item->GetText();
c33c4050
RR
787}
788
789void wxMenu::SetHelpString( int id, const wxString& helpString )
790{
83624f79 791 wxMenuItem *item = FindItem(id);
c626a8b7 792
b019151f 793 wxCHECK_RET( item, _T("wxMenu::SetHelpString: no such item") );
c626a8b7
VZ
794
795 item->SetHelp( helpString );
c33c4050
RR
796}
797
798wxString wxMenu::GetHelpString( int id ) const
799{
83624f79 800 wxMenuItem *item = FindItem(id);
c626a8b7 801
b019151f 802 wxCHECK_MSG( item, _T(""), _T("wxMenu::GetHelpString: no such item") );
c626a8b7
VZ
803
804 return item->GetHelp();
c33c4050
RR
805}
806
96fd301f
VZ
807int wxMenu::FindMenuIdByMenuItem( GtkWidget *menuItem ) const
808{
83624f79
RR
809 wxNode *node = m_items.First();
810 while (node)
811 {
812 wxMenuItem *item = (wxMenuItem*)node->Data();
813 if (item->GetMenuItem() == menuItem)
814 return item->GetId();
815 node = node->Next();
816 }
96fd301f 817
c626a8b7 818 return wxNOT_FOUND;
6de97a3b 819}
c801d85f 820
96fd301f 821wxMenuItem *wxMenu::FindItem(int id) const
c801d85f 822{
83624f79 823 wxNode *node = m_items.First();
c626a8b7 824 while (node)
83624f79
RR
825 {
826 wxMenuItem *item = (wxMenuItem*)node->Data();
827 if (item->GetId() == id)
c626a8b7 828 {
83624f79 829 return item;
c626a8b7 830 }
83624f79
RR
831 node = node->Next();
832 }
96fd301f 833
83624f79
RR
834 /* Not finding anything here can be correct
835 * when search the entire menu system for
836 * an entry -> no error message. */
8bbe427f 837
83624f79 838 return (wxMenuItem *) NULL;
96fd301f 839}
c801d85f
KB
840
841void wxMenu::SetInvokingWindow( wxWindow *win )
842{
83624f79 843 m_invokingWindow = win;
6de97a3b 844}
c801d85f 845
96fd301f 846wxWindow *wxMenu::GetInvokingWindow()
c801d85f 847{
83624f79 848 return m_invokingWindow;
6de97a3b 849}
c801d85f 850
c626a8b7
VZ
851// Update a menu and all submenus recursively. source is the object that has
852// the update event handlers defined for it. If NULL, the menu or associated
853// window will be used.
631f1bfe
JS
854void wxMenu::UpdateUI(wxEvtHandler* source)
855{
856 if (!source && GetInvokingWindow())
857 source = GetInvokingWindow()->GetEventHandler();
858 if (!source)
859 source = GetEventHandler();
860 if (!source)
861 source = this;
862
863 wxNode* node = GetItems().First();
864 while (node)
865 {
866 wxMenuItem* item = (wxMenuItem*) node->Data();
867 if ( !item->IsSeparator() )
868 {
869 wxWindowID id = item->GetId();
870 wxUpdateUIEvent event(id);
871 event.SetEventObject( source );
872
873 if (source->ProcessEvent(event))
874 {
875 if (event.GetSetText())
876 SetLabel(id, event.GetText());
877 if (event.GetSetChecked())
878 Check(id, event.GetChecked());
879 if (event.GetSetEnabled())
880 Enable(id, event.GetEnabled());
881 }
882
883 if (item->GetSubMenu())
884 item->GetSubMenu()->UpdateUI(source);
885 }
886 node = node->Next();
887 }
888}
889