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::GetLabelText( 
 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::GetLabelText 
 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::SetItemLabel( const wxString
& rText 
) 
 369     // Don't do anything if label didn't change 
 372     wxString                        sText 
= wxPMTextToLabel(rText
); 
 376     // wxMenuItemBase will do stock ID checks 
 377     wxMenuItemBase::SetItemLabel(sText
); 
 379     // m_text could now be different from 'text' if we are a stock menu item, 
 380     // so use only m_text below 
 382     OWNER_DRAWN_ONLY(wxOwnerDrawn::SetName(m_text
)); 
 383 #if  wxUSE_OWNER_DRAWN 
 385         SetAccelString(m_text
.AfterFirst(_T('\t'))); 
 387         SetAccelString(rText
.AfterFirst(_T('\t'))); 
 388 #endif // wxUSE_OWNER_DRAWN 
 390     HWND                            hMenu 
= GetHmenuOf(m_parentMenu
); 
 392     wxCHECK_RET(hMenu
, wxT("menuitem without menu")); 
 395     m_parentMenu
->UpdateAccel(this); 
 396 #endif // wxUSE_ACCEL 
 398     USHORT   uId 
= (USHORT
)GetRealId(); 
 402     if (!::WinSendMsg( hMenu
 
 404                       ,MPFROM2SHORT(uId
, TRUE
) 
 408         wxLogLastError(wxT("GetMenuState")); 
 412         uFlagsOld 
= vItem
.afStyle
; 
 415             uFlagsOld 
|= MIS_SUBMENU
; 
 420 #if wxUSE_OWNER_DRAWN 
 423             uFlagsOld 
|= MIS_OWNERDRAW
; 
 429             uFlagsOld 
|= MIS_TEXT
; 
 430             pData 
= (char*) m_text
.wx_str(); 
 436         if (!::WinSendMsg( hMenu
 
 438                           ,MPFROM2SHORT(uId
, TRUE
) 
 442             wxLogLastError(wxT("ModifyMenu")); 
 448         if (::WinSendMsg( hMenu
 
 454             wxLogLastError(wxT("ModifyMenu")); 
 457 } // end of wxMenuItem::SetText 
 459 void wxMenuItem::SetCheckable( 
 463     wxMenuItemBase::SetCheckable(bCheckable
); 
 464     OWNER_DRAWN_ONLY(wxOwnerDrawn::SetCheckable(bCheckable
)); 
 465 } // end of wxMenuItem::SetCheckable 
 467 // ---------------------------------------------------------------------------- 
 469 // ---------------------------------------------------------------------------- 
 471 wxMenuItem
* wxMenuItemBase::New( 
 474 , const wxString
&                   rName
 
 475 , const wxString
&                   rHelp
 
 480     return new wxMenuItem( pParentMenu
 
 487 } // end of wxMenuItemBase::New