Motif files added.
[wxWidgets.git] / src / motif / menu.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: menu.cpp
3 // Purpose: wxMenu, wxMenuBar, wxMenuItem
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 17/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12
13 // ============================================================================
14 // headers & declarations
15 // ============================================================================
16
17 // wxWindows headers
18 // -----------------
19
20 #ifdef __GNUG__
21 #pragma implementation "menu.h"
22 #pragma implementation "menuitem.h"
23 #endif
24
25 #include "wx/menu.h"
26 #include "wx/menuitem.h"
27 #include "wx/log.h"
28 #include "wx/utils.h"
29
30 #include <Xm/Label.h>
31 #include <Xm/LabelG.h>
32 #include <Xm/CascadeBG.h>
33 #include <Xm/CascadeB.h>
34 #include <Xm/SeparatoG.h>
35 #include <Xm/PushBG.h>
36 #include <Xm/ToggleB.h>
37 #include <Xm/ToggleBG.h>
38 #include <Xm/RowColumn.h>
39
40 // other standard headers
41 // ----------------------
42 #include <string.h>
43
44 void wxMenuItemCallback (Widget w, XtPointer clientData,
45 XtPointer ptr);
46 void wxMenuItemArmCallback (Widget w, XtPointer clientData,
47 XtPointer ptr);
48 void wxMenuItemDisarmCallback (Widget w, XtPointer clientData,
49 XtPointer ptr);
50
51 #if !USE_SHARED_LIBRARY
52 IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
53 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
54 #endif
55
56 // ============================================================================
57 // implementation
58 // ============================================================================
59
60 // Menus
61
62 // Construct a menu with optional title (then use append)
63 wxMenu::wxMenu(const wxString& title, const wxFunction func)
64 {
65 m_title = title;
66 m_parent = (wxEvtHandler*) NULL;
67 m_eventHandler = this;
68 m_noItems = 0;
69 m_menuBar = NULL;
70
71 //// Motif-specific members
72 m_numColumns = 1;
73 m_menuWidget = (WXWidget) NULL;
74 m_popupShell = (WXWidget) NULL;
75 m_buttonWidget = (WXWidget) NULL;
76 m_menuId = 0;
77 m_topMenu = (wxMenu*) NULL;
78 m_ownedByMenuBar = FALSE;
79 m_menuParent = (wxMenu*) NULL;
80
81 if (m_title != "")
82 {
83 Append(-2, m_title) ;
84 AppendSeparator() ;
85 }
86
87 Callback(func);
88
89 // TODO create menu
90 }
91
92 // The wxWindow destructor will take care of deleting the submenus.
93 wxMenu::~wxMenu()
94 {
95 // TODO destroy menu and children
96
97 wxNode *node = m_menuItems.First();
98 while (node)
99 {
100 wxMenuItem *item = (wxMenuItem *)node->Data();
101
102 // Delete child menus.
103 // Beware: they must not be appended to children list!!!
104 // (because order of delete is significant)
105 if (item->GetSubMenu())
106 item->DeleteSubMenu();
107
108 wxNode *next = node->Next();
109 delete item;
110 delete node;
111 node = next;
112 }
113 }
114
115 void wxMenu::Break()
116 {
117 // TODO
118 }
119
120 // function appends a new item or submenu to the menu
121 void wxMenu::Append(wxMenuItem *pItem)
122 {
123 // TODO
124
125 wxCHECK_RET( pItem != NULL, "can't append NULL item to the menu" );
126
127 m_menuItems.Append(pItem);
128
129 m_noItems++;
130 }
131
132 void wxMenu::AppendSeparator()
133 {
134 // TODO
135 Append(new wxMenuItem(this, ID_SEPARATOR));
136 }
137
138 // Pullright item
139 void wxMenu::Append(int Id, const wxString& label, wxMenu *SubMenu,
140 const wxString& helpString)
141 {
142 Append(new wxMenuItem(this, Id, label, helpString, FALSE, SubMenu));
143 }
144
145 // Ordinary menu item
146 void wxMenu::Append(int Id, const wxString& label,
147 const wxString& helpString, bool checkable)
148 {
149 // 'checkable' parameter is useless for Windows.
150 Append(new wxMenuItem(this, Id, label, helpString, checkable));
151 }
152
153 void wxMenu::Delete(int id)
154 {
155 wxNode *node;
156 wxMenuItem *item;
157 int pos;
158
159 for (pos = 0, node = m_menuItems.First(); node; node = node->Next(), pos++) {
160 item = (wxMenuItem *)node->Data();
161 if (item->GetId() == id)
162 break;
163 }
164
165 if (!node)
166 return;
167
168 m_menuItems.DeleteNode(node);
169 delete item;
170
171 // TODO
172 }
173
174 void wxMenu::Enable(int Id, bool Flag)
175 {
176 wxMenuItem *item = FindItemForId(Id);
177 wxCHECK_RET( item != NULL, "can't enable non-existing menu item" );
178
179 item->Enable(Flag);
180 }
181
182 bool wxMenu::Enabled(int Id) const
183 {
184 wxMenuItem *item = FindItemForId(Id);
185 wxCHECK( item != NULL, FALSE );
186
187 return item->IsEnabled();
188 }
189
190 void wxMenu::Check(int Id, bool Flag)
191 {
192 wxMenuItem *item = FindItemForId(Id);
193 wxCHECK_RET( item != NULL, "can't get status of non-existing menu item" );
194
195 item->Check(Flag);
196 }
197
198 bool wxMenu::Checked(int Id) const
199 {
200 wxMenuItem *item = FindItemForId(Id);
201 wxCHECK( item != NULL, FALSE );
202
203 return item->IsChecked();
204 }
205
206 void wxMenu::SetTitle(const wxString& label)
207 {
208 m_title = label ;
209 // TODO
210 }
211
212 const wxString wxMenu::GetTitle() const
213 {
214 return m_title;
215 }
216
217 void wxMenu::SetLabel(int id, const wxString& label)
218 {
219 wxMenuItem *item = FindItemForId(id) ;
220 if (item==NULL)
221 return;
222
223 if (item->GetSubMenu()==NULL)
224 {
225 // TODO
226 }
227 else
228 {
229 // TODO
230 }
231 item->SetName(label);
232 }
233
234 wxString wxMenu::GetLabel(int Id) const
235 {
236 // TODO
237 return wxString("") ;
238 }
239
240 // Finds the item id matching the given string, -1 if not found.
241 int wxMenu::FindItem (const wxString& itemString) const
242 {
243 char buf1[200];
244 char buf2[200];
245 wxStripMenuCodes ((char *)(const char *)itemString, buf1);
246
247 for (wxNode * node = m_menuItems.First (); node; node = node->Next ())
248 {
249 wxMenuItem *item = (wxMenuItem *) node->Data ();
250 if (item->GetSubMenu())
251 {
252 int ans = item->GetSubMenu()->FindItem(itemString);
253 if (ans > -1)
254 return ans;
255 }
256 if ( !item->IsSeparator() )
257 {
258 wxStripMenuCodes((char *)item->GetName().c_str(), buf2);
259 if (strcmp(buf1, buf2) == 0)
260 return item->GetId();
261 }
262 }
263
264 return -1;
265 }
266
267 wxMenuItem *wxMenu::FindItemForId(int itemId, wxMenu ** itemMenu) const
268 {
269 if (itemMenu)
270 *itemMenu = NULL;
271 for (wxNode * node = m_menuItems.First (); node; node = node->Next ())
272 {
273 wxMenuItem *item = (wxMenuItem *) node->Data ();
274
275 if (item->GetId() == itemId)
276 {
277 if (itemMenu)
278 *itemMenu = (wxMenu *) this;
279 return item;
280 }
281
282 if (item->GetSubMenu())
283 {
284 wxMenuItem *ans = item->GetSubMenu()->FindItemForId (itemId, itemMenu);
285 if (ans)
286 return ans;
287 }
288 }
289
290 if (itemMenu)
291 *itemMenu = NULL;
292 return NULL;
293 }
294
295 void wxMenu::SetHelpString(int itemId, const wxString& helpString)
296 {
297 wxMenuItem *item = FindItemForId (itemId);
298 if (item)
299 item->SetHelp(helpString);
300 }
301
302 wxString wxMenu::GetHelpString (int itemId) const
303 {
304 wxMenuItem *item = FindItemForId (itemId);
305 wxString str("");
306 return (item == NULL) ? str : item->GetHelp();
307 }
308
309 void wxMenu::ProcessCommand(wxCommandEvent & event)
310 {
311 bool processed = FALSE;
312
313 // Try a callback
314 if (m_callback)
315 {
316 (void) (*(m_callback)) (*this, event);
317 processed = TRUE;
318 }
319
320 // Try the menu's event handler
321 if ( !processed && GetEventHandler())
322 {
323 processed = GetEventHandler()->ProcessEvent(event);
324 }
325 /* TODO
326 // Try the window the menu was popped up from (and up
327 // through the hierarchy)
328 if ( !processed && GetInvokingWindow())
329 processed = GetInvokingWindow()->ProcessEvent(event);
330 */
331 }
332
333 bool wxWindow::PopupMenu(wxMenu *menu, int x, int y)
334 {
335 // TODO
336 return FALSE;
337 }
338
339 // Menu Bar
340 wxMenuBar::wxMenuBar()
341 {
342 m_eventHandler = this;
343 m_menuCount = 0;
344 m_menus = NULL;
345 m_titles = NULL;
346 m_menuBarFrame = NULL;
347
348 // TODO
349 }
350
351 wxMenuBar::wxMenuBar(int n, wxMenu *menus[], const wxString titles[])
352 {
353 m_eventHandler = this;
354 m_menuCount = n;
355 m_menus = menus;
356 m_titles = new wxString[n];
357 int i;
358 for ( i = 0; i < n; i++ )
359 m_titles[i] = titles[i];
360 m_menuBarFrame = NULL;
361
362 // TODO
363 }
364
365 wxMenuBar::~wxMenuBar()
366 {
367 int i;
368 for (i = 0; i < m_menuCount; i++)
369 {
370 delete m_menus[i];
371 }
372 delete[] m_menus;
373 delete[] m_titles;
374
375 // TODO
376 }
377
378 // Must only be used AFTER menu has been attached to frame,
379 // otherwise use individual menus to enable/disable items
380 void wxMenuBar::Enable(int id, bool flag)
381 {
382 wxMenu *itemMenu = NULL;
383 wxMenuItem *item = FindItemForId(id, &itemMenu) ;
384 if (!item)
385 return;
386
387 // TODO
388 }
389
390 void wxMenuBar::EnableTop(int pos, bool flag)
391 {
392 // TODO
393 }
394
395 // Must only be used AFTER menu has been attached to frame,
396 // otherwise use individual menus
397 void wxMenuBar::Check(int id, bool flag)
398 {
399 wxMenu *itemMenu = NULL;
400 wxMenuItem *item = FindItemForId(id, &itemMenu) ;
401 if (!item)
402 return;
403
404 if (!item->IsCheckable())
405 return ;
406
407 // TODO
408 }
409
410 bool wxMenuBar::Checked(int id) const
411 {
412 wxMenu *itemMenu = NULL;
413 wxMenuItem *item = FindItemForId(id, &itemMenu) ;
414 if (!item)
415 return FALSE;
416
417 // TODO
418 return FALSE;
419 }
420
421 bool wxMenuBar::Enabled(int id) const
422 {
423 wxMenu *itemMenu = NULL;
424 wxMenuItem *item = FindItemForId(id, &itemMenu) ;
425 if (!item)
426 return FALSE;
427
428 // TODO
429 return FALSE ;
430 }
431
432
433 void wxMenuBar::SetLabel(int id, const wxString& label)
434 {
435 wxMenu *itemMenu = NULL;
436 wxMenuItem *item = FindItemForId(id, &itemMenu) ;
437
438 if (!item)
439 return;
440
441 // TODO
442 }
443
444 wxString wxMenuBar::GetLabel(int id) const
445 {
446 wxMenu *itemMenu = NULL;
447 wxMenuItem *item = FindItemForId(id, &itemMenu) ;
448
449 if (!item)
450 return wxString("");
451
452 // TODO
453 return wxString("") ;
454 }
455
456 void wxMenuBar::SetLabelTop(int pos, const wxString& label)
457 {
458 // TODO
459 }
460
461 wxString wxMenuBar::GetLabelTop(int pos) const
462 {
463 // TODO
464 return wxString("");
465 }
466
467 bool wxMenuBar::OnDelete(wxMenu *a_menu, int pos)
468 {
469 // TODO
470 return FALSE;
471 }
472
473 bool wxMenuBar::OnAppend(wxMenu *a_menu, const char *title)
474 {
475 // TODO
476 return FALSE;
477 }
478
479 void wxMenuBar::Append (wxMenu * menu, const wxString& title)
480 {
481 if (!OnAppend(menu, title))
482 return;
483
484 m_menuCount ++;
485 wxMenu **new_menus = new wxMenu *[m_menuCount];
486 wxString *new_titles = new wxString[m_menuCount];
487 int i;
488
489 for (i = 0; i < m_menuCount - 1; i++)
490 {
491 new_menus[i] = m_menus[i];
492 m_menus[i] = NULL;
493 new_titles[i] = m_titles[i];
494 m_titles[i] = "";
495 }
496 if (m_menus)
497 {
498 delete[]m_menus;
499 delete[]m_titles;
500 }
501 m_menus = new_menus;
502 m_titles = new_titles;
503
504 m_menus[m_menuCount - 1] = (wxMenu *)menu;
505 m_titles[m_menuCount - 1] = title;
506
507 // TODO
508 }
509
510 void wxMenuBar::Delete(wxMenu * menu, int i)
511 {
512 int j;
513 int ii = (int) i;
514
515 if (menu != 0)
516 {
517 for (ii = 0; ii < m_menuCount; ii++)
518 {
519 if (m_menus[ii] == menu)
520 break;
521 }
522 if (ii >= m_menuCount)
523 return;
524 } else
525 {
526 if (ii < 0 || ii >= m_menuCount)
527 return;
528 menu = m_menus[ii];
529 }
530
531 if (!OnDelete(menu, ii))
532 return;
533
534 menu->SetParent(NULL);
535
536 -- m_menuCount;
537 for (j = ii; j < m_menuCount; j++)
538 {
539 m_menus[j] = m_menus[j + 1];
540 m_titles[j] = m_titles[j + 1];
541 }
542 }
543
544 // Find the menu menuString, item itemString, and return the item id.
545 // Returns -1 if none found.
546 int wxMenuBar::FindMenuItem (const wxString& menuString, const wxString& itemString) const
547 {
548 char buf1[200];
549 char buf2[200];
550 wxStripMenuCodes ((char *)(const char *)menuString, buf1);
551 int i;
552 for (i = 0; i < m_menuCount; i++)
553 {
554 wxStripMenuCodes ((char *)(const char *)m_titles[i], buf2);
555 if (strcmp (buf1, buf2) == 0)
556 return m_menus[i]->FindItem (itemString);
557 }
558 return -1;
559 }
560
561 wxMenuItem *wxMenuBar::FindItemForId (int Id, wxMenu ** itemMenu) const
562 {
563 if (itemMenu)
564 *itemMenu = NULL;
565
566 wxMenuItem *item = NULL;
567 int i;
568 for (i = 0; i < m_menuCount; i++)
569 if ((item = m_menus[i]->FindItemForId (Id, itemMenu)))
570 return item;
571 return NULL;
572 }
573
574 void wxMenuBar::SetHelpString (int Id, const wxString& helpString)
575 {
576 int i;
577 for (i = 0; i < m_menuCount; i++)
578 {
579 if (m_menus[i]->FindItemForId (Id))
580 {
581 m_menus[i]->SetHelpString (Id, helpString);
582 return;
583 }
584 }
585 }
586
587 wxString wxMenuBar::GetHelpString (int Id) const
588 {
589 int i;
590 for (i = 0; i < m_menuCount; i++)
591 {
592 if (m_menus[i]->FindItemForId (Id))
593 return wxString(m_menus[i]->GetHelpString (Id));
594 }
595 return wxString("");
596 }
597
598