1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/menuitem.cpp
3 // Purpose: wxMenuItem implementation
4 // Author: David Webster
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
13 // headers & declarations
14 // ============================================================================
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
19 #include "wx/menuitem.h"
20 #include "wx/stockitem.h"
24 #include "wx/bitmap.h"
25 #include "wx/settings.h"
26 #include "wx/window.h"
29 #include "wx/string.h"
37 #include "wx/os2/private.h"
39 // ---------------------------------------------------------------------------
41 // ---------------------------------------------------------------------------
44 #define GetHMenuOf(menu) ((HMENU)menu->GetHMenu())
46 // conditional compilation
48 #define OWNER_DRAWN_ONLY( code ) if ( IsOwnerDrawn() ) code
49 #else // !wxUSE_OWNER_DRAWN
50 #define OWNER_DRAWN_ONLY( code )
51 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
53 // ============================================================================
55 // ============================================================================
57 // ----------------------------------------------------------------------------
58 // dynamic classes implementation
59 // ----------------------------------------------------------------------------
61 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
, wxObject
)
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
70 wxMenuItem::wxMenuItem(
73 , const wxString
& rsText
74 , const wxString
& rsHelp
78 : wxMenuItemBase( pParentMenu
80 ,wxPMTextToLabel(rsText
)
86 , wxOwnerDrawn( wxPMTextToLabel(rsText
)
87 ,eKind
== wxITEM_CHECK
91 wxASSERT_MSG(pParentMenu
!= NULL
, wxT("a menu item should have a parent"));
92 memset(&m_vMenuData
, '\0', sizeof(m_vMenuData
));
93 m_vMenuData
.id
= (USHORT
)nId
;
96 } // end of wxMenuItem::wxMenuItem
98 wxMenuItem::wxMenuItem(
101 , const wxString
& rsText
102 , const wxString
& rsHelp
106 : wxMenuItemBase( pParentMenu
108 ,wxPMTextToLabel(rsText
)
110 ,bIsCheckable
? wxITEM_CHECK
: wxITEM_NORMAL
113 #if wxUSE_OWNER_DRAWN
114 , wxOwnerDrawn( wxPMTextToLabel(rsText
)
117 #endif // owner drawn
119 wxASSERT_MSG(pParentMenu
!= NULL
, wxT("a menu item should have a parent"));
120 memset(&m_vMenuData
, '\0', sizeof(m_vMenuData
));
121 m_vMenuData
.id
= (USHORT
)nId
;
124 } // end of wxMenuItem::wxMenuItem
126 void wxMenuItem::Init()
128 m_vRadioGroup
.m_nStart
= -1;
129 m_bIsRadioGroupStart
= FALSE
;
131 #if wxUSE_OWNER_DRAWN
133 // Set default menu colors
135 #define SYS_COLOR(c) (wxSystemSettings::GetColour(wxSYS_COLOUR_##c))
137 SetTextColour(SYS_COLOR(MENUTEXT
));
138 SetBackgroundColour(SYS_COLOR(MENU
));
141 // We don't want normal items be owner-drawn
147 // Tell the owner drawing code to to show the accel string as well
149 SetAccelString(m_text
.AfterFirst(_T('\t')));
150 #endif // wxUSE_OWNER_DRAWN
151 } // end of wxMenuItem::Init
153 wxMenuItem::~wxMenuItem()
155 } // end of wxMenuItem::~wxMenuItem
162 // Return the id for calling Win32 API functions
164 int wxMenuItem::GetRealId() const
166 return m_subMenu
? (int)m_subMenu
->GetHMenu() : GetId();
167 } // end of wxMenuItem::GetRealId
172 bool wxMenuItem::IsChecked() const
174 USHORT uFlag
= SHORT1FROMMR(::WinSendMsg( GetHMenuOf(m_parentMenu
)
176 ,MPFROM2SHORT(GetId(), TRUE
)
177 ,MPFROMSHORT(MIA_CHECKED
)
180 return (uFlag
& MIA_CHECKED
) == MIA_CHECKED
;
181 } // end of wxMenuItem::IsChecked
183 wxString
wxMenuItemBase::GetLabelFromText(
184 const wxString
& rsText
189 for (const wxChar
* zPc
= rsText
.c_str(); *zPc
; zPc
++)
191 if (*zPc
== wxT('~') || *zPc
== wxT('&'))
194 // '~' is the escape character for OS/2PM and '&' is the one for
195 // wxWidgets - skip both of them
202 } // end of wxMenuItemBase::GetLabelFromText
208 void wxMenuItem::SetAsRadioGroupStart()
210 m_bIsRadioGroupStart
= true;
211 } // end of wxMenuItem::SetAsRadioGroupStart
213 void wxMenuItem::SetRadioGroupStart(
217 wxASSERT_MSG( !m_bIsRadioGroupStart
218 ,_T("should only be called for the next radio items")
221 m_vRadioGroup
.m_nStart
= nStart
;
222 } // wxMenuItem::SetRadioGroupStart
224 void wxMenuItem::SetRadioGroupEnd(
228 wxASSERT_MSG( m_bIsRadioGroupStart
229 ,_T("should only be called for the first radio item")
231 m_vRadioGroup
.m_nEnd
= nEnd
;
232 } // end of wxMenuItem::SetRadioGroupEnd
237 void wxMenuItem::Enable(
243 if (m_isEnabled
== bEnable
)
246 bOk
= (bool)::WinSendMsg( GetHMenuOf(m_parentMenu
)
248 ,MPFROM2SHORT(GetRealId(), TRUE
)
249 ,MPFROM2SHORT(MIA_DISABLED
, FALSE
)
252 bOk
= (bool)::WinSendMsg( GetHMenuOf(m_parentMenu
)
254 ,MPFROM2SHORT(GetRealId(), TRUE
)
255 ,MPFROM2SHORT(MIA_DISABLED
, MIA_DISABLED
)
259 wxLogLastError(wxT("EnableMenuItem"));
261 wxMenuItemBase::Enable(bEnable
);
262 } // end of wxMenuItem::Enable
264 void wxMenuItem::Check(
270 wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
271 if (m_isChecked
== bCheck
)
274 HMENU hMenu
= GetHmenuOf(m_parentMenu
);
276 if (GetKind() == wxITEM_RADIO
)
279 // It doesn't make sense to uncheck a radio item - what would this do?
285 // Get the index of this item in the menu
287 const wxMenuItemList
& rItems
= m_parentMenu
->GetMenuItems();
288 int nPos
= rItems
.IndexOf(this);
290 wxCHECK_RET( nPos
!= wxNOT_FOUND
291 ,_T("menuitem not found in the menu items list?")
295 // Get the radio group range
300 if (m_bIsRadioGroupStart
)
303 // We already have all information we need
306 nEnd
= m_vRadioGroup
.m_nEnd
;
308 else // next radio group item
311 // Get the radio group end from the start item
313 nStart
= m_vRadioGroup
.m_nStart
;
314 nEnd
= rItems
.Item(nStart
)->GetData()->m_vRadioGroup
.m_nEnd
;
318 // Also uncheck all the other items in this radio group
320 wxMenuItemList::compatibility_iterator node
= rItems
.Item(nStart
);
322 for (int n
= nStart
; n
<= nEnd
&& node
; n
++)
328 ,MPFROM2SHORT(n
, TRUE
)
329 ,MPFROM2SHORT(MIA_CHECKED
, MIA_CHECKED
)
334 node
->GetData()->m_isChecked
= FALSE
;
337 ,MPFROM2SHORT(n
, TRUE
)
338 ,MPFROM2SHORT(MIA_CHECKED
, FALSE
)
341 node
= node
->GetNext();
347 bOk
= (bool)::WinSendMsg( hMenu
349 ,MPFROM2SHORT(GetRealId(), TRUE
)
350 ,MPFROM2SHORT(MIA_CHECKED
, MIA_CHECKED
)
353 bOk
= (bool)::WinSendMsg( hMenu
355 ,MPFROM2SHORT(GetRealId(), TRUE
)
356 ,MPFROM2SHORT(MIA_CHECKED
, FALSE
)
361 wxLogLastError(wxT("CheckMenuItem"));
363 wxMenuItemBase::Check(bCheck
);
364 } // end of wxMenuItem::Check
366 void wxMenuItem::SetText( const wxString
& rText
)
369 // Don't do anything if label didn't change
372 wxString sText
= wxPMTextToLabel(rText
);
378 wxASSERT_MSG(wxIsStockID(GetId()), wxT("A non-stock menu item with an empty label?"));
379 sText
= wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR
|wxSTOCK_WITH_MNEMONIC
);
382 wxMenuItemBase::SetText(sText
);
383 OWNER_DRAWN_ONLY(wxOwnerDrawn::SetName(sText
));
384 #if wxUSE_OWNER_DRAWN
386 SetAccelString(sText
.AfterFirst(_T('\t')));
388 SetAccelString(rText
.AfterFirst(_T('\t')));
389 #endif // wxUSE_OWNER_DRAWN
391 HWND hMenu
= GetHmenuOf(m_parentMenu
);
393 wxCHECK_RET(hMenu
, wxT("menuitem without menu"));
396 m_parentMenu
->UpdateAccel(this);
397 #endif // wxUSE_ACCEL
399 USHORT uId
= (USHORT
)GetRealId();
403 if (!::WinSendMsg( hMenu
405 ,MPFROM2SHORT(uId
, TRUE
)
409 wxLogLastError(wxT("GetMenuState"));
413 uFlagsOld
= vItem
.afStyle
;
416 uFlagsOld
|= MIS_SUBMENU
;
421 #if wxUSE_OWNER_DRAWN
424 uFlagsOld
|= MIS_OWNERDRAW
;
430 uFlagsOld
|= MIS_TEXT
;
431 pData
= (BYTE
*)sText
.c_str();
437 if (!::WinSendMsg( hMenu
439 ,MPFROM2SHORT(uId
, TRUE
)
443 wxLogLastError(wxT("ModifyMenu"));
449 if (::WinSendMsg( hMenu
455 wxLogLastError(wxT("ModifyMenu"));
458 } // end of wxMenuItem::SetText
460 void wxMenuItem::SetCheckable(
464 wxMenuItemBase::SetCheckable(bCheckable
);
465 OWNER_DRAWN_ONLY(wxOwnerDrawn::SetCheckable(bCheckable
));
466 } // end of wxMenuItem::SetCheckable
468 // ----------------------------------------------------------------------------
470 // ----------------------------------------------------------------------------
472 wxMenuItem
* wxMenuItemBase::New(
475 , const wxString
& rName
476 , const wxString
& rHelp
481 return new wxMenuItem( pParentMenu
488 } // end of wxMenuItemBase::New