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