]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/menuitem.cpp
compilation fix
[wxWidgets.git] / src / os2 / menuitem.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: menuitem.cpp
3// Purpose: wxMenuItem implementation
4// Author: David Webster
5// Modified by:
6// Created: 10/10/98
7// RCS-ID: $Id$
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// headers & declarations
14// ============================================================================
15
16#ifdef __GNUG__
17 #pragma implementation "menuitem.h"
18#endif
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifndef WX_PRECOMP
24 #include "wx/font.h"
25 #include "wx/bitmap.h"
26 #include "wx/settings.h"
27 #include "wx/font.h"
28 #include "wx/window.h"
29 #include "wx/accel.h"
30 #include "wx/menu.h"
31 #include "wx/string.h"
32#endif
33
34#include "wx/menuitem.h"
35#include "wx/log.h"
36
37#if wxUSE_ACCEL
38 #include "wx/accel.h"
39#endif // wxUSE_ACCEL
40
41#include "wx/os2/private.h"
42
43// ---------------------------------------------------------------------------
44// macro
45// ---------------------------------------------------------------------------
46
47// hide the ugly cast
48#define GetHMenuOf(menu) ((HMENU)menu->GetHMenu())
49
50// conditional compilation
51#if wxUSE_OWNER_DRAWN
52 #define OWNER_DRAWN_ONLY( code ) if ( IsOwnerDrawn() ) code
53#else // !wxUSE_OWNER_DRAWN
54 #define OWNER_DRAWN_ONLY( code )
55#endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
56
57// ----------------------------------------------------------------------------
58// static function for translating menu labels
59// ----------------------------------------------------------------------------
60
61static wxString TextToLabel(
62 const wxString& rsTitle
63)
64{
65 wxString sTitle;
66 const wxChar* zPc;
67
68 if (rsTitle.IsEmpty())
69 return(sTitle);
70
71 for (zPc = rsTitle.c_str(); *zPc != wxT('\0'); zPc++)
72 {
73 if (*zPc == wxT('&'))
74 {
75 if (*(zPc + 1) == wxT('&'))
76 {
77 zPc++;
78 sTitle << wxT('&');
79 }
80 else
81 sTitle << wxT('~');
82 }
83 else
84 {
85 if ( *zPc == wxT('~'))
86 {
87 //
88 // Tildes must be doubled to prevent them from being
89 // interpreted as accelerator character prefix by PM ???
90 //
91 sTitle << *zPc;
92 }
93 sTitle << *zPc;
94 }
95 }
96 return(sTitle);
97} // end of TextToLabel
98
99// ============================================================================
100// implementation
101// ============================================================================
102
103// ----------------------------------------------------------------------------
104// dynamic classes implementation
105// ----------------------------------------------------------------------------
106
107IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject)
108
109// ----------------------------------------------------------------------------
110// wxMenuItem
111// ----------------------------------------------------------------------------
112
113// ctor & dtor
114// -----------
115
116wxMenuItem::wxMenuItem(
117 wxMenu* pParentMenu
118, int nId
119, const wxString& rsText
120, const wxString& rsHelp
121, wxItemKind eKind
122, wxMenu* pSubMenu
123)
124: wxMenuItemBase( pParentMenu
125 ,nId
126 ,TextToLabel(rsText)
127 ,rsHelp
128 ,eKind
129 ,pSubMenu
130 )
131#if wxUSE_OWNER_DRAWN
132, wxOwnerDrawn( TextToLabel(rsText)
133 ,eKind == wxITEM_CHECK
134 )
135#endif // owner drawn
136{
137 wxASSERT_MSG(pParentMenu != NULL, wxT("a menu item should have a parent"));
138 memset(&m_vMenuData, '\0', sizeof(m_vMenuData));
139 m_vMenuData.id = (USHORT)nId;
140
141 Init();
142} // end of wxMenuItem::wxMenuItem
143
144wxMenuItem::wxMenuItem(
145 wxMenu* pParentMenu
146, int nId
147, const wxString& rsText
148, const wxString& rsHelp
149, bool bIsCheckable
150, wxMenu* pSubMenu
151)
152: wxMenuItemBase( pParentMenu
153 ,nId
154 ,TextToLabel(rsText)
155 ,rsHelp
156 ,bIsCheckable ? wxITEM_CHECK : wxITEM_NORMAL
157 ,pSubMenu
158 )
159#if wxUSE_OWNER_DRAWN
160, wxOwnerDrawn( TextToLabel(rsText)
161 ,bIsCheckable
162 )
163#endif // owner drawn
164{
165 wxASSERT_MSG(pParentMenu != NULL, wxT("a menu item should have a parent"));
166 memset(&m_vMenuData, '\0', sizeof(m_vMenuData));
167 m_vMenuData.id = (USHORT)nId;
168
169 Init();
170} // end of wxMenuItem::wxMenuItem
171
172void wxMenuItem::Init()
173{
174 m_vRadioGroup.m_nStart = -1;
175 m_bIsRadioGroupStart = FALSE;
176
177#if wxUSE_OWNER_DRAWN
178 //
179 // Set default menu colors
180 //
181 #define SYS_COLOR(c) (wxSystemSettings::GetColour(wxSYS_COLOUR_##c))
182
183 SetTextColour(SYS_COLOR(MENUTEXT));
184 SetBackgroundColour(SYS_COLOR(MENU));
185
186 //
187 // We don't want normal items be owner-drawn
188 //
189 ResetOwnerDrawn();
190 #undef SYS_COLOR
191
192 //
193 // Tell the owner drawing code to to show the accel string as well
194 //
195 SetAccelString(m_text.AfterFirst(_T('\t')));
196#endif // wxUSE_OWNER_DRAWN
197} // end of wxMenuItem::Init
198
199wxMenuItem::~wxMenuItem()
200{
201} // end of wxMenuItem::~wxMenuItem
202
203//
204// Misc
205// ----
206
207//
208// Return the id for calling Win32 API functions
209//
210int wxMenuItem::GetRealId() const
211{
212 return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId();
213} // end of wxMenuItem::GetRealId
214
215//
216// Get item state
217// --------------
218bool wxMenuItem::IsChecked() const
219{
220 USHORT uFlag = SHORT1FROMMR(::WinSendMsg( GetHMenuOf(m_parentMenu)
221 ,MM_QUERYITEMATTR
222 ,MPFROM2SHORT(GetId(), TRUE)
223 ,MPFROMSHORT(MIA_CHECKED)
224 ));
225
226 return (uFlag & MIA_CHECKED);
227} // end of wxMenuItem::IsChecked
228
229wxString wxMenuItemBase::GetLabelFromText(
230 const wxString& rsText
231)
232{
233 wxString sLabel;
234
235 for (const char* zPc = rsText.c_str(); *zPc; zPc++)
236 {
237 if (*zPc == wxT('~') || *zPc == wxT('&'))
238 {
239 //
240 // '~' is the escape character for OS/2PM and '&' is the one for
241 // wxWindows - skip both of them
242 //
243 continue;
244 }
245 sLabel += *zPc;
246 }
247 return sLabel;
248} // end of wxMenuItemBase::GetLabelFromText
249
250//
251// Radio group stuff
252// -----------------
253//
254void wxMenuItem::SetAsRadioGroupStart()
255{
256 m_bIsRadioGroupStart = TRUE;
257} // end of wxMenuItem::SetAsRadioGroupStart
258
259void wxMenuItem::SetRadioGroupStart(
260 int nStart
261)
262{
263 wxASSERT_MSG( !m_bIsRadioGroupStart
264 ,_T("should only be called for the next radio items")
265 );
266
267 m_vRadioGroup.m_nStart = nStart;
268} // wxMenuItem::SetRadioGroupStart
269
270void wxMenuItem::SetRadioGroupEnd(
271 int nEnd
272)
273{
274 wxASSERT_MSG( m_bIsRadioGroupStart
275 ,_T("should only be called for the first radio item")
276 );
277 m_vRadioGroup.m_nEnd = nEnd;
278} // end of wxMenuItem::SetRadioGroupEnd
279
280// change item state
281// -----------------
282
283void wxMenuItem::Enable(
284 bool bEnable
285)
286{
287 bool bOk;
288
289 if (m_isEnabled == bEnable)
290 return;
291 if (bEnable)
292 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
293 ,MM_SETITEMATTR
294 ,MPFROM2SHORT(GetRealId(), TRUE)
295 ,MPFROM2SHORT(MIA_DISABLED, FALSE)
296 );
297 else
298 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
299 ,MM_SETITEMATTR
300 ,MPFROM2SHORT(GetRealId(), TRUE)
301 ,MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED)
302 );
303 if (!bOk)
304 {
305 wxLogLastError("EnableMenuItem");
306 }
307 wxMenuItemBase::Enable(bEnable);
308} // end of wxMenuItem::Enable
309
310void wxMenuItem::Check(
311 bool bCheck
312)
313{
314 bool bOk;
315
316 wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
317 if (m_isChecked == bCheck)
318 return;
319
320 HMENU hMenu = GetHmenuOf(m_parentMenu);
321
322 if (GetKind() == wxITEM_RADIO)
323 {
324 //
325 // It doesn't make sense to uncheck a radio item - what would this do?
326 //
327 if (!bCheck)
328 return;
329
330 //
331 // Get the index of this item in the menu
332 //
333 const wxMenuItemList& rItems = m_parentMenu->GetMenuItems();
334 int nPos = rItems.IndexOf(this);
335
336 wxCHECK_RET( nPos != wxNOT_FOUND
337 ,_T("menuitem not found in the menu items list?")
338 );
339
340 //
341 // Get the radio group range
342 //
343 int nStart;
344 int nEnd;
345
346 if (m_bIsRadioGroupStart)
347 {
348 //
349 // We already have all information we need
350 //
351 nStart = nPos;
352 nEnd = m_vRadioGroup.m_nEnd;
353 }
354 else // next radio group item
355 {
356 //
357 // Get the radio group end from the start item
358 //
359 nStart = m_vRadioGroup.m_nStart;
360 nEnd = rItems.Item(nStart)->GetData()->m_vRadioGroup.m_nEnd;
361 }
362
363 //
364 // Also uncheck all the other items in this radio group
365 //
366 wxMenuItemList::Node* pNode = rItems.Item(nStart);
367
368 for (int n = nStart; n <= nEnd && pNode; n++)
369 {
370 if (n == nPos)
371 {
372 ::WinSendMsg( hMenu
373 ,MM_SETITEMATTR
374 ,MPFROM2SHORT(n, TRUE)
375 ,MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED)
376 );
377 }
378 if (n != nPos)
379 {
380 pNode->GetData()->m_isChecked = FALSE;
381 ::WinSendMsg( hMenu
382 ,MM_SETITEMATTR
383 ,MPFROM2SHORT(n, TRUE)
384 ,MPFROM2SHORT(MIA_CHECKED, FALSE)
385 );
386 }
387 pNode = pNode->GetNext();
388 }
389 }
390 else // check item
391 {
392 if (bCheck)
393 bOk = (bool)::WinSendMsg( hMenu
394 ,MM_SETITEMATTR
395 ,MPFROM2SHORT(GetRealId(), TRUE)
396 ,MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED)
397 );
398 else
399 bOk = (bool)::WinSendMsg( hMenu
400 ,MM_SETITEMATTR
401 ,MPFROM2SHORT(GetRealId(), TRUE)
402 ,MPFROM2SHORT(MIA_CHECKED, FALSE)
403 );
404 }
405 if (!bOk)
406 {
407 wxLogLastError("CheckMenuItem");
408 }
409 wxMenuItemBase::Check(bCheck);
410} // end of wxMenuItem::Check
411
412void wxMenuItem::SetText(
413 const wxString& rText
414)
415{
416 //
417 // Don't do anything if label didn't change
418 //
419
420 wxString sText = TextToLabel(rText);
421 if (m_text == sText)
422 return;
423
424 wxMenuItemBase::SetText(sText);
425 OWNER_DRAWN_ONLY(wxOwnerDrawn::SetName(sText));
426
427 HWND hMenu = GetHmenuOf(m_parentMenu);
428
429 wxCHECK_RET(hMenu, wxT("menuitem without menu"));
430
431#if wxUSE_ACCEL
432 m_parentMenu->UpdateAccel(this);
433#endif // wxUSE_ACCEL
434
435 USHORT uId = GetRealId();
436 MENUITEM vItem;
437 USHORT uFlagsOld;
438
439 if (!::WinSendMsg( hMenu
440 ,MM_QUERYITEM
441 ,MPFROM2SHORT(uId, TRUE)
442 ,(MPARAM)&vItem
443 ))
444 {
445 wxLogLastError("GetMenuState");
446 }
447 else
448 {
449 uFlagsOld = vItem.afStyle;
450 if (IsSubMenu())
451 {
452 uFlagsOld |= MIS_SUBMENU;
453 }
454
455 BYTE* pData;
456
457#if wxUSE_OWNER_DRAWN
458 if (IsOwnerDrawn())
459 {
460 uFlagsOld |= MIS_OWNERDRAW;
461 pData = (BYTE*)this;
462 }
463 else
464#endif //owner drawn
465 {
466 uFlagsOld |= MIS_TEXT;
467 pData = (BYTE*)sText.c_str();
468 }
469
470 //
471 // Set the style
472 //
473 if (!::WinSendMsg( hMenu
474 ,MM_SETITEM
475 ,MPFROM2SHORT(uId, TRUE)
476 ,(MPARAM)&vItem
477 ))
478 {
479 wxLogLastError(wxT("ModifyMenu"));
480 }
481
482 //
483 // Set the text
484 //
485 if (::WinSendMsg( hMenu
486 ,MM_SETITEMTEXT
487 ,MPFROMSHORT(uId)
488 ,(MPARAM)pData
489 ))
490 {
491 wxLogLastError(wxT("ModifyMenu"));
492 }
493 }
494} // end of wxMenuItem::SetText
495
496void wxMenuItem::SetCheckable(
497 bool bCheckable
498)
499{
500 wxMenuItemBase::SetCheckable(bCheckable);
501 OWNER_DRAWN_ONLY(wxOwnerDrawn::SetCheckable(bCheckable));
502} // end of wxMenuItem::SetCheckable
503
504// ----------------------------------------------------------------------------
505// wxMenuItemBase
506// ----------------------------------------------------------------------------
507
508wxMenuItem* wxMenuItemBase::New(
509 wxMenu* pParentMenu
510, int nId
511, const wxString& rName
512, const wxString& rHelp
513, wxItemKind kind
514, wxMenu* pSubMenu
515)
516{
517 return new wxMenuItem( pParentMenu
518 ,nId
519 ,rName
520 ,rHelp
521 ,kind
522 ,pSubMenu
523 );
524} // end of wxMenuItemBase::New
525