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