]>
Commit | Line | Data |
---|---|---|
ffecfa5a | 1 | ///////////////////////////////////////////////////////////////////////////// |
e2731512 | 2 | // Name: src/palmos/menu.cpp |
ffecfa5a | 3 | // Purpose: wxMenu, wxMenuBar, wxMenuItem |
e2731512 | 4 | // Author: William Osborne - minimal working wxPalmOS port |
ffecfa5a JS |
5 | // Modified by: |
6 | // Created: 10/12/04 | |
e2731512 | 7 | // RCS-ID: $Id$ |
ffecfa5a JS |
8 | // Copyright: (c) William Osborne |
9 | // Licence: wxWindows licence | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | // =========================================================================== | |
13 | // declarations | |
14 | // =========================================================================== | |
15 | ||
16 | // --------------------------------------------------------------------------- | |
17 | // headers | |
18 | // --------------------------------------------------------------------------- | |
19 | ||
ffecfa5a JS |
20 | // For compilers that support precompilation, includes "wx.h". |
21 | #include "wx/wxprec.h" | |
22 | ||
23 | #ifdef __BORLANDC__ | |
24 | #pragma hdrstop | |
25 | #endif | |
26 | ||
27 | #if wxUSE_MENUS | |
28 | ||
3b3dc801 WS |
29 | #include "wx/menu.h" |
30 | ||
ffecfa5a JS |
31 | #ifndef WX_PRECOMP |
32 | #include "wx/frame.h" | |
ffecfa5a JS |
33 | #include "wx/utils.h" |
34 | #include "wx/intl.h" | |
35 | #include "wx/log.h" | |
36 | #endif | |
37 | ||
38 | #if wxUSE_OWNER_DRAWN | |
39 | #include "wx/ownerdrw.h" | |
40 | #endif | |
41 | ||
6afc1b46 | 42 | #ifdef __WXPALMOS6__ |
20bc5ad8 | 43 | #include <Loader.h> |
6afc1b46 VZ |
44 | #else // __WXPALMOS5__ |
45 | #include <UIResources.h> // MenuRscType | |
46 | #endif | |
47 | ||
20bc5ad8 WS |
48 | #include <Form.h> |
49 | #include <Menu.h> | |
50 | ||
ffecfa5a JS |
51 | // ---------------------------------------------------------------------------- |
52 | // global variables | |
53 | // ---------------------------------------------------------------------------- | |
54 | ||
55 | extern wxMenu *wxCurrentPopupMenu; | |
56 | ||
57 | // ---------------------------------------------------------------------------- | |
58 | // constants | |
59 | // ---------------------------------------------------------------------------- | |
60 | ||
61 | // the (popup) menu title has this special id | |
62 | static const int idMenuTitle = -3; | |
63 | ||
64 | // ---------------------------------------------------------------------------- | |
65 | // private functions | |
66 | // ---------------------------------------------------------------------------- | |
67 | ||
68 | // ============================================================================ | |
69 | // implementation | |
70 | // ============================================================================ | |
71 | ||
7ec69821 | 72 | #include "wx/listimpl.cpp" |
ffecfa5a | 73 | |
412e0d47 | 74 | WX_DEFINE_LIST( wxMenuInfoList ) |
ffecfa5a JS |
75 | |
76 | #if wxUSE_EXTENDED_RTTI | |
77 | ||
78 | WX_DEFINE_FLAGS( wxMenuStyle ) | |
79 | ||
80 | wxBEGIN_FLAGS( wxMenuStyle ) | |
81 | wxFLAGS_MEMBER(wxMENU_TEAROFF) | |
82 | wxEND_FLAGS( wxMenuStyle ) | |
83 | ||
84 | IMPLEMENT_DYNAMIC_CLASS_XTI(wxMenu, wxEvtHandler,"wx/menu.h") | |
85 | ||
86 | wxCOLLECTION_TYPE_INFO( wxMenuItem * , wxMenuItemList ) ; | |
87 | ||
88 | template<> void wxCollectionToVariantArray( wxMenuItemList const &theList, wxxVariantArray &value) | |
89 | { | |
90 | wxListCollectionToVariantArray<wxMenuItemList::compatibility_iterator>( theList , value ) ; | |
91 | } | |
92 | ||
93 | wxBEGIN_PROPERTIES_TABLE(wxMenu) | |
94 | wxEVENT_PROPERTY( Select , wxEVT_COMMAND_MENU_SELECTED , wxCommandEvent) | |
95 | wxPROPERTY( Title, wxString , SetTitle, GetTitle, wxString(), 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) | |
96 | wxREADONLY_PROPERTY_FLAGS( MenuStyle , wxMenuStyle , long , GetStyle , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style | |
97 | wxPROPERTY_COLLECTION( MenuItems , wxMenuItemList , wxMenuItem* , Append , GetMenuItems , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) | |
98 | wxEND_PROPERTIES_TABLE() | |
99 | ||
100 | wxBEGIN_HANDLERS_TABLE(wxMenu) | |
101 | wxEND_HANDLERS_TABLE() | |
102 | ||
103 | wxDIRECT_CONSTRUCTOR_2( wxMenu , wxString , Title , long , MenuStyle ) | |
104 | ||
105 | WX_DEFINE_FLAGS( wxMenuBarStyle ) | |
106 | ||
107 | wxBEGIN_FLAGS( wxMenuBarStyle ) | |
108 | wxFLAGS_MEMBER(wxMB_DOCKABLE) | |
109 | wxEND_FLAGS( wxMenuBarStyle ) | |
110 | ||
111 | // the negative id would lead the window (its superclass !) to vetoe streaming out otherwise | |
112 | bool wxMenuBarStreamingCallback( const wxObject *WXUNUSED(object), wxWriter * , wxPersister * , wxxVariantArray & ) | |
113 | { | |
114 | return true ; | |
115 | } | |
116 | ||
117 | IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxMenuBar, wxWindow ,"wx/menu.h",wxMenuBarStreamingCallback) | |
118 | ||
119 | IMPLEMENT_DYNAMIC_CLASS_XTI(wxMenuInfo, wxObject , "wx/menu.h" ) | |
120 | ||
121 | wxBEGIN_PROPERTIES_TABLE(wxMenuInfo) | |
122 | wxREADONLY_PROPERTY( Menu , wxMenu* , GetMenu , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) | |
123 | wxREADONLY_PROPERTY( Title , wxString , GetTitle , wxString() , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) | |
124 | wxEND_PROPERTIES_TABLE() | |
125 | ||
126 | wxBEGIN_HANDLERS_TABLE(wxMenuInfo) | |
127 | wxEND_HANDLERS_TABLE() | |
128 | ||
4055ed82 | 129 | wxCONSTRUCTOR_2( wxMenuInfo , wxMenu* , Menu , wxString , Title ) |
ffecfa5a JS |
130 | |
131 | wxCOLLECTION_TYPE_INFO( wxMenuInfo * , wxMenuInfoList ) ; | |
132 | ||
133 | template<> void wxCollectionToVariantArray( wxMenuInfoList const &theList, wxxVariantArray &value) | |
134 | { | |
135 | wxListCollectionToVariantArray<wxMenuInfoList::compatibility_iterator>( theList , value ) ; | |
136 | } | |
137 | ||
138 | wxBEGIN_PROPERTIES_TABLE(wxMenuBar) | |
139 | wxPROPERTY_COLLECTION( MenuInfos , wxMenuInfoList , wxMenuInfo* , Append , GetMenuInfos , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) | |
140 | wxEND_PROPERTIES_TABLE() | |
141 | ||
142 | wxBEGIN_HANDLERS_TABLE(wxMenuBar) | |
143 | wxEND_HANDLERS_TABLE() | |
144 | ||
145 | wxCONSTRUCTOR_DUMMY( wxMenuBar ) | |
146 | ||
147 | #else | |
148 | IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler) | |
149 | IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxWindow) | |
150 | IMPLEMENT_DYNAMIC_CLASS(wxMenuInfo, wxObject) | |
151 | #endif | |
152 | ||
153 | const wxMenuInfoList& wxMenuBar::GetMenuInfos() const | |
154 | { | |
155 | wxMenuInfoList* list = const_cast< wxMenuInfoList* >( &m_menuInfos ) ; | |
156 | WX_CLEAR_LIST( wxMenuInfoList , *list ) ; | |
157 | for( size_t i = 0 ; i < GetMenuCount() ; ++i ) | |
158 | { | |
159 | wxMenuInfo* info = new wxMenuInfo() ; | |
52af3158 | 160 | info->Create( const_cast<wxMenuBar*>(this)->GetMenu(i) , GetMenuLabel(i) ) ; |
ffecfa5a JS |
161 | list->Append( info ) ; |
162 | } | |
163 | return m_menuInfos ; | |
164 | } | |
165 | ||
166 | // --------------------------------------------------------------------------- | |
167 | // wxMenu construction, adding and removing menu items | |
168 | // --------------------------------------------------------------------------- | |
169 | ||
170 | // Construct a menu with optional title (then use append) | |
171 | void wxMenu::Init() | |
172 | { | |
173 | } | |
174 | ||
175 | // The wxWindow destructor will take care of deleting the submenus. | |
176 | wxMenu::~wxMenu() | |
177 | { | |
178 | } | |
179 | ||
180 | void wxMenu::Break() | |
181 | { | |
182 | } | |
183 | ||
184 | void wxMenu::Attach(wxMenuBarBase *menubar) | |
185 | { | |
186 | wxMenuBase::Attach(menubar); | |
187 | } | |
188 | ||
189 | #if wxUSE_ACCEL | |
190 | ||
191 | int wxMenu::FindAccel(int id) const | |
192 | { | |
193 | return wxNOT_FOUND; | |
194 | } | |
195 | ||
196 | void wxMenu::UpdateAccel(wxMenuItem *item) | |
197 | { | |
198 | } | |
199 | ||
200 | #endif // wxUSE_ACCEL | |
201 | ||
202 | // append a new item or submenu to the menu | |
203 | bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) | |
204 | { | |
205 | if ( IsAttached() && GetMenuBar()->IsAttached() ) | |
206 | { | |
4055ed82 | 207 | // Regenerate the menu resource |
ffecfa5a JS |
208 | GetMenuBar()->Refresh(); |
209 | } | |
4055ed82 WS |
210 | |
211 | return true; | |
ffecfa5a JS |
212 | } |
213 | ||
214 | void wxMenu::EndRadioGroup() | |
215 | { | |
216 | } | |
217 | ||
218 | wxMenuItem* wxMenu::DoAppend(wxMenuItem *item) | |
219 | { | |
9a83f860 | 220 | wxCHECK_MSG( item, NULL, wxT("NULL item in wxMenu::DoAppend") ); |
ffecfa5a JS |
221 | |
222 | if(!wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item)) | |
223 | { | |
224 | return NULL; | |
225 | } | |
226 | else if(IsAttached() && GetMenuBar()->IsAttached()) | |
227 | { | |
4055ed82 | 228 | // Regenerate the menu resource |
ffecfa5a JS |
229 | GetMenuBar()->Refresh(); |
230 | } | |
4055ed82 WS |
231 | |
232 | return item; | |
ffecfa5a JS |
233 | } |
234 | ||
235 | wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item) | |
236 | { | |
237 | if (wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos)) | |
238 | return item; | |
239 | else | |
4055ed82 | 240 | return NULL; |
ffecfa5a JS |
241 | } |
242 | ||
243 | wxMenuItem *wxMenu::DoRemove(wxMenuItem *item) | |
244 | { | |
245 | // we need to find the items position in the child list | |
246 | size_t pos; | |
247 | wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst(); | |
248 | for ( pos = 0; node; pos++ ) | |
249 | { | |
250 | if ( node->GetData() == item ) | |
251 | break; | |
252 | ||
253 | node = node->GetNext(); | |
254 | } | |
255 | ||
256 | // DoRemove() (unlike Remove) can only be called for existing item! | |
257 | wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") ); | |
258 | ||
259 | // remove the item from the menu | |
260 | wxMenuItem *ret=wxMenuBase::DoRemove(item); | |
4055ed82 | 261 | |
ffecfa5a JS |
262 | if ( IsAttached() && GetMenuBar()->IsAttached() ) |
263 | { | |
4055ed82 | 264 | // Regenerate the menu resource |
ffecfa5a JS |
265 | GetMenuBar()->Refresh(); |
266 | } | |
4055ed82 | 267 | |
ffecfa5a JS |
268 | return ret; |
269 | } | |
270 | ||
271 | // --------------------------------------------------------------------------- | |
272 | // accelerator helpers | |
273 | // --------------------------------------------------------------------------- | |
274 | ||
275 | #if wxUSE_ACCEL | |
276 | ||
277 | // create the wxAcceleratorEntries for our accels and put them into provided | |
278 | // array - return the number of accels we have | |
279 | size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const | |
280 | { | |
281 | size_t count = GetAccelCount(); | |
282 | for ( size_t n = 0; n < count; n++ ) | |
283 | { | |
284 | *accels++ = *m_accels[n]; | |
285 | } | |
286 | ||
287 | return count; | |
288 | } | |
289 | ||
290 | #endif // wxUSE_ACCEL | |
291 | ||
292 | // --------------------------------------------------------------------------- | |
293 | // set wxMenu title | |
294 | // --------------------------------------------------------------------------- | |
295 | ||
296 | void wxMenu::SetTitle(const wxString& label) | |
297 | { | |
298 | m_title = label; | |
299 | ||
300 | if ( IsAttached() && GetMenuBar()->IsAttached() ) | |
301 | { | |
4055ed82 | 302 | // Regenerate the menu resource |
ffecfa5a JS |
303 | GetMenuBar()->Refresh(); |
304 | } | |
305 | } | |
306 | ||
307 | // --------------------------------------------------------------------------- | |
308 | // event processing | |
309 | // --------------------------------------------------------------------------- | |
310 | ||
311 | bool wxMenu::PalmCommand(WXUINT WXUNUSED(param), WXWORD id) | |
312 | { | |
313 | return false; | |
314 | } | |
315 | ||
316 | // --------------------------------------------------------------------------- | |
317 | // other | |
318 | // --------------------------------------------------------------------------- | |
319 | ||
320 | wxWindow *wxMenu::GetWindow() const | |
321 | { | |
322 | return NULL; | |
323 | } | |
324 | ||
325 | // --------------------------------------------------------------------------- | |
326 | // Menu Bar | |
327 | // --------------------------------------------------------------------------- | |
328 | ||
329 | void wxMenuBar::Init() | |
330 | { | |
331 | } | |
332 | ||
333 | wxMenuBar::wxMenuBar() | |
334 | { | |
335 | } | |
336 | ||
337 | wxMenuBar::wxMenuBar( long WXUNUSED(style) ) | |
338 | { | |
339 | } | |
340 | ||
294ea16d | 341 | wxMenuBar::wxMenuBar(size_t count, wxMenu *menus[], const wxString titles[], long WXUNUSED(style)) |
ffecfa5a JS |
342 | { |
343 | } | |
344 | ||
345 | wxMenuBar::~wxMenuBar() | |
346 | { | |
347 | } | |
348 | ||
349 | // --------------------------------------------------------------------------- | |
350 | // wxMenuBar helpers | |
351 | // --------------------------------------------------------------------------- | |
352 | ||
353 | void wxMenuBar::Refresh() | |
354 | { | |
355 | wxCHECK_RET( IsAttached(), wxT("can't refresh unattached menubar") ); | |
356 | ||
357 | // Regenerate the menu resource | |
358 | LoadMenu(); | |
359 | } | |
360 | ||
361 | WXHMENU wxMenuBar::Create() | |
362 | { | |
363 | return NULL; | |
364 | } | |
365 | ||
366 | int wxMenuBar::PalmPositionForWxMenu(wxMenu *menu, int wxpos) | |
367 | { | |
368 | return -1; | |
369 | } | |
370 | ||
371 | // --------------------------------------------------------------------------- | |
372 | // wxMenuBar functions to work with the top level submenus | |
373 | // --------------------------------------------------------------------------- | |
374 | ||
375 | void wxMenuBar::EnableTop(size_t pos, bool enable) | |
376 | { | |
377 | // Palm OS does not have support for grayed or disabled items | |
378 | } | |
379 | ||
52af3158 | 380 | void wxMenuBar::SetMenuLabel(size_t pos, const wxString& label) |
ffecfa5a JS |
381 | { |
382 | wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") ); | |
383 | ||
52af3158 | 384 | m_titles[pos] = label; |
ffecfa5a JS |
385 | |
386 | if ( !IsAttached() ) | |
387 | { | |
388 | return; | |
389 | } | |
390 | ||
391 | // Regenerate the menu resource | |
392 | Refresh(); | |
393 | } | |
394 | ||
52af3158 | 395 | wxString wxMenuBar::GetMenuLabel(size_t pos) const |
ffecfa5a JS |
396 | { |
397 | wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString, | |
52af3158 | 398 | wxT("invalid menu index in wxMenuBar::GetMenuLabel") ); |
ffecfa5a | 399 | |
52af3158 | 400 | return m_titles[pos]; |
ffecfa5a JS |
401 | } |
402 | ||
403 | // --------------------------------------------------------------------------- | |
404 | // wxMenuBar construction | |
405 | // --------------------------------------------------------------------------- | |
406 | ||
407 | wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title) | |
408 | { | |
409 | wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title); | |
410 | if ( !menuOld ) | |
411 | return NULL; | |
412 | ||
52af3158 | 413 | m_titles[pos] = title; |
ffecfa5a JS |
414 | |
415 | if ( IsAttached() ) | |
416 | { | |
417 | // Regenerate the menu resource | |
418 | Refresh(); | |
419 | } | |
420 | ||
421 | return menuOld; | |
422 | } | |
423 | ||
424 | bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title) | |
425 | { | |
426 | if ( !wxMenuBarBase::Insert(pos, menu, title) ) | |
4055ed82 | 427 | return false; |
ffecfa5a | 428 | |
52af3158 | 429 | m_titles.Insert(title, pos); |
ffecfa5a JS |
430 | |
431 | if ( IsAttached() ) | |
432 | { | |
433 | // Regenerate the menu resource | |
434 | Refresh(); | |
435 | } | |
436 | ||
4055ed82 | 437 | return true; |
ffecfa5a JS |
438 | } |
439 | ||
440 | bool wxMenuBar::Append(wxMenu *menu, const wxString& title) | |
441 | { | |
442 | if ( !wxMenuBarBase::Append(menu, title) ) | |
4055ed82 | 443 | return false; |
ffecfa5a | 444 | |
52af3158 | 445 | m_titles.Add(title); |
ffecfa5a JS |
446 | |
447 | if(IsAttached()) | |
448 | { | |
449 | // Regenerate the menu resource | |
450 | Refresh(); | |
451 | } | |
452 | ||
4055ed82 | 453 | return true; |
ffecfa5a JS |
454 | } |
455 | ||
456 | wxMenu *wxMenuBar::Remove(size_t pos) | |
457 | { | |
458 | wxMenu *menu = wxMenuBarBase::Remove(pos); | |
459 | if ( !menu ) | |
460 | return NULL; | |
461 | ||
462 | m_titles.RemoveAt(pos); | |
463 | ||
464 | if (IsAttached()) | |
465 | { | |
466 | // Regenerate the menu resource | |
467 | Refresh(); | |
468 | } | |
469 | ||
470 | return menu; | |
471 | } | |
472 | ||
473 | #if wxUSE_ACCEL | |
474 | ||
475 | void wxMenuBar::RebuildAccelTable() | |
476 | { | |
477 | } | |
478 | ||
479 | #endif // wxUSE_ACCEL | |
480 | ||
481 | int wxMenuBar::ProcessCommand(int ItemID) | |
482 | { | |
483 | if(!IsAttached()) | |
484 | return -1; | |
4055ed82 | 485 | |
ffecfa5a JS |
486 | int MenuNum=(ItemID/1000)-1; |
487 | int ItemNum=(ItemID-(1000*(MenuNum+1))); | |
4055ed82 | 488 | |
ffecfa5a JS |
489 | // Should never happen, but it doesn't hurt to check anyway. |
490 | if(MenuNum>GetMenuCount()) | |
491 | return -1; | |
492 | ||
493 | // Get the menu | |
494 | wxMenu *ActiveMenu=GetMenu(MenuNum); | |
4055ed82 | 495 | |
ffecfa5a JS |
496 | // Make sure this is a valid item. |
497 | if(ItemNum>ActiveMenu->GetMenuItemCount()) | |
498 | return -1; | |
499 | ||
500 | // Get the item | |
501 | wxMenuItem *ActiveItem=ActiveMenu->FindItemByPosition(ItemNum); | |
502 | int ActiveID=ActiveItem->GetId(); | |
503 | ||
504 | return ActiveID; | |
505 | } | |
506 | ||
4055ed82 WS |
507 | /* Palm OS does not have good dynamic menu support. About all you can do with |
508 | * the standard API calls is to add new items to an existing drop-down menu and | |
509 | * hide/show items in a drop-down menu. It is impossible to add, hide, or | |
510 | * change the label on a drop-down menu. | |
511 | * | |
512 | * The easiest and simplest way around this limitation is to modify the Palm OS | |
513 | * MenuBarType structure directly. This gives limited ability to change the | |
514 | * label on a drop-down menu. I have not been able to find a safe way to add, | |
ffecfa5a | 515 | * delete, or resize drop-down menus in OS 6. |
4055ed82 | 516 | * |
ffecfa5a | 517 | * The following routine attempt to work around these limitations present in the |
4055ed82 | 518 | * Palm OS API to provide limited dynamic menu support. This solution is far |
ffecfa5a JS |
519 | * from perfect, but the only other option is to wait for PalmSource to add full |
520 | * dynamic menu support, or to recreate the Palm OS menu system from scratch. | |
4055ed82 | 521 | * |
ffecfa5a JS |
522 | * This system is limited in that no more than 4 drop-down menus are allowed per |
523 | * menu bar, and the label for each drop-down menu is limited to 8 characters of | |
524 | * text. However, this menu system should work for most applications. | |
4055ed82 WS |
525 | * |
526 | * Basically the menu routines select one of four menu bars, depending on | |
527 | * whether or not the requested menu bar has one, two, three, or four drop-down | |
ffecfa5a | 528 | * menus. |
4055ed82 WS |
529 | * |
530 | * These four "template" menu bars contain one, two, three, or four drop-down | |
531 | * menus. Each menu has a dummy menu item attached to it to allow the Palm OS | |
ffecfa5a | 532 | * MenuAddItem function to add the real items. |
4055ed82 WS |
533 | * |
534 | * The labels on the drop-down menus are then replaced with the labels of the | |
ffecfa5a | 535 | * real menus. |
4055ed82 WS |
536 | * |
537 | * The menu is then attached to the active window and the MenuAddItem API | |
538 | * function is called to add the items to each drop-down menu. Finally, | |
ffecfa5a JS |
539 | * MenuHideItem is called to remove the dummy items from each drop-down menu. |
540 | */ | |
541 | void wxMenuBar::LoadMenu() | |
542 | { | |
543 | int i=0; | |
544 | int j=0; | |
6afc1b46 | 545 | #ifdef __WXPALMOS6__ |
ffecfa5a JS |
546 | // Handle to the currently running application database |
547 | DmOpenRef AppDB; | |
548 | ||
549 | // Get app database reference - needed for some Palm OS Menu API calls. | |
550 | SysGetModuleDatabase(SysGetRefNum(), NULL, &AppDB); | |
6afc1b46 | 551 | #endif // __WXPALMOS6__ |
ffecfa5a JS |
552 | |
553 | // Get the number of menus | |
554 | int NumMenus=GetMenuCount(); | |
555 | ||
556 | // Set up the pointers and handles | |
4055ed82 | 557 | char *PalmOSMenuBarPtr; |
ffecfa5a | 558 | MemHandle PalmOSMenuBar; |
4055ed82 | 559 | |
ffecfa5a JS |
560 | // Load the menu template and set up the menu pointers |
561 | if(NumMenus==1) | |
562 | { | |
6afc1b46 VZ |
563 | PalmOSMenuBar = POS_DmGetResource (AppDB, MenuRscType, 1000); |
564 | PalmOSMenuBarPtr = (char *)MemHandleLock (PalmOSMenuBar); | |
ffecfa5a | 565 | |
6afc1b46 | 566 | PalmOSMenuBarPtr += 74; |
ffecfa5a JS |
567 | } |
568 | else if(NumMenus==2) | |
569 | { | |
6afc1b46 VZ |
570 | PalmOSMenuBar = POS_DmGetResource (AppDB, MenuRscType, 2000); |
571 | PalmOSMenuBarPtr = (char *)MemHandleLock (PalmOSMenuBar); | |
ffecfa5a | 572 | |
6afc1b46 | 573 | PalmOSMenuBarPtr += 116; |
ffecfa5a JS |
574 | } |
575 | else if(NumMenus==3) | |
576 | { | |
6afc1b46 VZ |
577 | PalmOSMenuBar = POS_DmGetResource (AppDB, MenuRscType, 3000); |
578 | PalmOSMenuBarPtr = (char *)MemHandleLock (PalmOSMenuBar); | |
ffecfa5a | 579 | |
6afc1b46 | 580 | PalmOSMenuBarPtr += 158; |
ffecfa5a JS |
581 | } |
582 | else | |
583 | { | |
4055ed82 | 584 | // We support a maximum of 4 menus, so make sure that do not create |
ffecfa5a JS |
585 | // more than we can handle. |
586 | NumMenus=4; | |
587 | ||
6afc1b46 VZ |
588 | PalmOSMenuBar = POS_DmGetResource (AppDB, MenuRscType, 4000); |
589 | PalmOSMenuBarPtr = (char *)MemHandleLock (PalmOSMenuBar); | |
ffecfa5a | 590 | |
6afc1b46 | 591 | PalmOSMenuBarPtr += 200; |
ffecfa5a | 592 | } |
4055ed82 | 593 | |
ffecfa5a JS |
594 | // Set the proper names for the drop-down triggers. |
595 | for(i=0;i<NumMenus;i++) | |
596 | { | |
597 | // Clear out the old label | |
598 | char buffer[8]={' ',' ',' ',' ',' ',' ',' ',' '}; | |
599 | MemMove(PalmOSMenuBarPtr,buffer,8); | |
4055ed82 | 600 | |
ffecfa5a JS |
601 | wxString MenuTitle=m_titles.Item(i); |
602 | ||
603 | // Make sure we don't copy more than 8 bytes for the label | |
6afc1b46 VZ |
604 | int LengthToCopy = MenuTitle.length(); |
605 | if(LengthToCopy > 8) | |
606 | LengthToCopy = 8; | |
ffecfa5a | 607 | |
6afc1b46 | 608 | MemMove(PalmOSMenuBarPtr,(char*)(&MenuTitle),LengthToCopy); |
ffecfa5a JS |
609 | PalmOSMenuBarPtr+=11; |
610 | } | |
611 | ||
612 | // We are done with the menu pointer. | |
4055ed82 | 613 | MemHandleUnlock(PalmOSMenuBar); |
ffecfa5a JS |
614 | DmReleaseResource(PalmOSMenuBar); |
615 | ||
4055ed82 | 616 | // We must make the menu active before we can add items to the drop-down |
ffecfa5a | 617 | // triggers. |
6afc1b46 | 618 | POS_FrmSetMenu (FrmGetActiveForm(), AppDB, NumMenus * 1000); |
ffecfa5a | 619 | |
4055ed82 WS |
620 | /* Add the menu items to the drop-down triggers. This must be done after |
621 | * setting the triggers, because setting the names of drop-down triggers | |
622 | * that have a variable number of items requires carefull calculation of | |
ffecfa5a JS |
623 | * the offsets in the MenuBarType structure. Setting the triggers first |
624 | * avoids this. | |
625 | */ | |
626 | for(i=0;i<NumMenus;i++) | |
627 | { | |
628 | wxMenu *CurrentMenu=GetMenu(i); | |
4055ed82 | 629 | |
ffecfa5a JS |
630 | for(j=0;j<CurrentMenu->GetMenuItemCount();j++) |
631 | { | |
632 | wxMenuItem *CurrentItem=CurrentMenu->FindItemByPosition(j); | |
633 | wxString ItemLabel=CurrentItem->GetLabel(); | |
4055ed82 | 634 | |
ffecfa5a JS |
635 | if(CurrentItem->IsSeparator()==true) |
636 | { | |
637 | char Separator=MenuSeparatorChar; | |
638 | if(j==0) | |
639 | MenuAddItem(9000+i,((i*1000)+1000)+j,0x00,&Separator); | |
640 | else | |
641 | MenuAddItem(((i*1000)+1000)+j-1,((i*1000)+1000)+j,0x00,&Separator); | |
642 | } | |
643 | else | |
644 | { | |
645 | if(j==0) | |
6afc1b46 | 646 | MenuAddItem(9000+i,((i*1000)+1000)+j,0x00,(char *)(&ItemLabel)); |
ffecfa5a | 647 | else |
6afc1b46 | 648 | MenuAddItem(((i*1000)+1000)+j-1,((i*1000)+1000)+j,0x00,(char *)(&ItemLabel)); |
ffecfa5a JS |
649 | } |
650 | } | |
4055ed82 | 651 | |
ffecfa5a JS |
652 | // Hide the dummy menu item, since we don't need it anymore. |
653 | MenuHideItem(9000+i); | |
654 | } | |
655 | } | |
656 | ||
657 | void wxMenuBar::Attach(wxFrame *frame) | |
658 | { | |
17131ffd WS |
659 | // before attaching preprocess menus to not include wxID_EXIT item |
660 | // as PalmOS guidelines suggest | |
661 | ||
662 | wxMenuItem *item; | |
663 | wxMenu *menu; | |
664 | int i; | |
665 | ||
666 | while( item = FindItem(wxID_EXIT) ) | |
667 | { | |
668 | menu = item->GetMenu(); | |
669 | if( !menu ) break; // something broken ? | |
670 | ||
671 | size_t count = menu->GetMenuItemCount(); | |
672 | if( count == 0 ) break; // something broken ? | |
673 | ||
674 | // if EXIT is last item in menu | |
675 | if( menu->FindItemByPosition( count - 1 ) == item ) | |
676 | { | |
677 | menu->Destroy( item ); | |
678 | ||
679 | // was more than one item? | |
680 | // was previous separator ? | |
681 | if( count > 2 ) | |
682 | { | |
683 | item = menu->FindItemByPosition( count - 2 ); | |
684 | if(item && item->IsSeparator()) | |
685 | menu->Destroy( item ); | |
686 | } | |
687 | } | |
688 | ||
689 | // if EXIT is first item in menu | |
690 | else if( menu->FindItemByPosition( 0 ) == item ) | |
691 | { | |
692 | menu->Destroy( item ); | |
693 | ||
694 | // was more than one item? | |
695 | // was previous separator ? | |
696 | if( count > 2 ) | |
697 | { | |
698 | item = menu->FindItemByPosition( 0 ); | |
699 | if(item && item->IsSeparator()) | |
700 | menu->Destroy( item ); | |
701 | } | |
702 | } | |
703 | ||
704 | // if EXIT is in the middle but before and after are selectors | |
705 | else | |
706 | { | |
707 | i = 1; // 0 case already done | |
708 | while ( (i < count) && (menu->FindItemByPosition( 0 ) != item) ) | |
709 | { | |
710 | i++; | |
711 | } | |
712 | ||
713 | if (i >= count) break; | |
714 | if (menu->FindItemByPosition( i ) != item) break; | |
715 | menu->Destroy( item ); | |
716 | item = menu->FindItemByPosition( i ); | |
717 | if ( item && | |
718 | item->IsSeparator() && | |
719 | menu->FindItemByPosition( i-1 )->IsSeparator() ) | |
720 | { | |
721 | // noe need for two neighbouring separators | |
722 | menu->Destroy( item ); | |
723 | } | |
724 | } | |
725 | } | |
726 | ||
727 | // check if we received any empty menu! | |
728 | i = 0; | |
729 | while(i < GetMenuCount()) | |
730 | { | |
731 | menu = GetMenu(i); | |
732 | ||
733 | if( menu && (menu->GetMenuItemCount()==0) ) | |
734 | { | |
735 | menu = Remove( i ); | |
736 | delete menu; | |
737 | } | |
738 | else | |
739 | i++; | |
740 | } | |
741 | ||
ffecfa5a | 742 | wxMenuBarBase::Attach(frame); |
ffecfa5a | 743 | |
4055ed82 | 744 | LoadMenu(); |
ffecfa5a | 745 | } |
ffecfa5a JS |
746 | |
747 | void wxMenuBar::Detach() | |
748 | { | |
749 | wxMenuBarBase::Detach(); | |
750 | } | |
751 | ||
752 | #endif // wxUSE_MENUS |