1 /////////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     implementation of wxCheckListBox class 
   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" 
  21 #include "wx/object.h" 
  22 #include "wx/colour.h" 
  24 #include "wx/bitmap.h" 
  25 #include "wx/window.h" 
  26 #include "wx/listbox.h" 
  27 #include "wx/ownerdrw.h" 
  28 #include "wx/settings.h" 
  29 #include "wx/dcmemory.h" 
  30 #include "wx/dcscreen.h" 
  31 #include "wx/os2/checklst.h" 
  37 // ---------------------------------------------------------------------------- 
  39 // ---------------------------------------------------------------------------- 
  41 // get item (converted to right type) 
  42 #define GetItem(n)    ((wxCheckListBoxItem *)(GetItem(n))) 
  44 // ============================================================================ 
  46 // ============================================================================ 
  48 IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox
, wxListBox
) 
  50 // ---------------------------------------------------------------------------- 
  51 // declaration and implementation of wxCheckListBoxItem class 
  52 // ---------------------------------------------------------------------------- 
  54 class wxCheckListBoxItem 
: public wxOwnerDrawn
 
  56     friend class wxCheckListBox
; 
  61     wxCheckListBoxItem( wxCheckListBox
* pParent
 
  68     virtual bool OnDrawItem( wxDC
&         rDc
 
  77     bool IsChecked(void) const  { return m_bChecked
; } 
  78     void Check(bool bCheck
); 
  79     void Toggle(void) { Check(!IsChecked()); } 
  83     wxCheckListBox
*                 m_pParent
; 
  85 }; // end of CLASS wxCheckListBoxItem 
  87 wxCheckListBoxItem::wxCheckListBoxItem ( 
  88   wxCheckListBox
*                   pParent
 
  91 : wxOwnerDrawn( wxEmptyString
 
 100     // We don't initialize m_nCheckHeight/Width vars because it's 
 101     // done in OnMeasure while they are used only in OnDraw and we 
 102     // know that there will always be OnMeasure before OnDraw 
 104     SetMarginWidth(GetDefaultMarginWidth()); 
 105 } // end of wxCheckListBoxItem::wxCheckListBoxItem 
 107 bool wxCheckListBoxItem::OnDrawItem ( 
 109 , const wxRect
&                     rRect
 
 114     wxRect                          vRect 
= rRect
; 
 116     ::WinQueryWindowRect( m_pParent
->GetHWND() 
 120         eStat 
= (wxOwnerDrawn::wxODStatus
)(eStat 
| wxOwnerDrawn::wxODChecked
); 
 123     // Unfortunately PM doesn't quite get the text position exact.  We need to alter 
 124     // it down and to the right, just a little bit.  The coords in rRect are OS/2 
 125     // coords not wxWidgets coords. 
 129     if (wxOwnerDrawn::OnDrawItem( rDc
 
 134         size_t                      nCheckWidth  
= GetDefaultMarginWidth(); 
 135         size_t                      nCheckHeight 
= m_pParent
->GetItemHeight(); 
 137         int                         nX 
= rRect
.GetX(); 
 138         int                         nY 
= rRect
.GetY(); 
 140         wxColour                    
vColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
)); 
 145         m_pParent
->GetSize( NULL
 
 149         nY 
= nParentHeight 
- nY 
- nCheckHeight
; 
 150         vPenBack 
= wxPen(vColour
, 1, wxSOLID
); 
 151         vPenGray 
= wxPen(wxColour(127, 127, 127), 1, wxSOLID
); 
 154         // Erase the 1-pixel border 
 156         rDc
.SetPen(vPenBack
); 
 157         rDc
.DrawRectangle( nX
 
 164         // Now we draw the smaller rectangle 
 171         // Draw hollow gray rectangle 
 173         rDc
.SetPen(vPenGray
); 
 174         rDc
.DrawRectangle( nX
 
 184             // Draw the check by loading the sys standard bitmap and drawing it 
 186             HBITMAP                 hChkBmp 
= ::WinGetSysBitmap( HWND_DESKTOP
 
 189             POINTL                  vPoint 
= {nX
, nOldY 
+ 3}; 
 191             ::WinDrawBitmap( rDc
.GetHPS() 
 203 } // end of wxCheckListBoxItem::OnDrawItem 
 206 // Change the state of the item and redraw it 
 208 void wxCheckListBoxItem::Check ( 
 215     // Index may be chanegd because new items were added/deleted 
 217     if (m_pParent
->GetItemIndex(this) != (int)m_nIndex
) 
 222         int                         nIndex 
= m_pParent
->GetItemIndex(this); 
 224         wxASSERT_MSG(nIndex 
!= wxNOT_FOUND
, wxT("what does this item do here?")); 
 226         m_nIndex 
= (size_t)nIndex
; 
 230     wxCommandEvent                  
vEvent( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
 
 234     vEvent
.SetInt(m_nIndex
); 
 235     vEvent
.SetEventObject(m_pParent
); 
 236     m_pParent
->ProcessCommand(vEvent
); 
 237 } // end of wxCheckListBoxItem::Check 
 239 // ---------------------------------------------------------------------------- 
 240 // implementation of wxCheckListBox class 
 241 // ---------------------------------------------------------------------------- 
 243 // define event table 
 244 // ------------------ 
 245 BEGIN_EVENT_TABLE(wxCheckListBox
, wxListBox
) 
 246   EVT_CHAR(wxCheckListBox::OnChar
) 
 247   EVT_LEFT_DOWN(wxCheckListBox::OnLeftClick
) 
 256 // Default ctor: use Create() to really create the control 
 258 wxCheckListBox::wxCheckListBox() 
 261 } // end of wxCheckListBox::wxCheckListBox 
 264 // Ctor which creates the associated control 
 266 wxCheckListBox::wxCheckListBox ( 
 269 , const wxPoint
&                    rPos
 
 270 , const wxSize
&                     rSize
 
 272 , const wxString                    asChoices
[] 
 274 , const wxValidator
&                rVal
 
 275 , const wxString
&                   rsName
 
 285            ,lStyle 
| wxLB_OWNERDRAW
 
 289 } // end of wxCheckListBox::wxCheckListBox 
 291 wxCheckListBox::wxCheckListBox ( 
 294 , const wxPoint
&                    rPos
 
 295 , const wxSize
&                     rSize
 
 296 , const wxArrayString
&              asChoices
 
 298 , const wxValidator
&                rVal
 
 299 , const wxString
&                   rsName
 
 303     wxCArrayString 
chs(asChoices
); 
 310            ,lStyle 
| wxLB_OWNERDRAW
 
 314 } // end of wxCheckListBox::wxCheckListBox 
 316 void wxCheckListBox::Delete( 
 320     wxCHECK_RET( N 
>= 0 && N 
< m_nNumItems
, 
 321                  wxT("invalid index in wxListBox::Delete") ); 
 322     wxListBox::Delete(N
); 
 328     m_aItems
.RemoveAt(N
); 
 329 } // end of wxCheckListBox::Delete 
 331 void wxCheckListBox::InsertItems ( 
 333 , const wxString                    asItems
[] 
 339     wxCHECK_RET( nPos 
>= 0 && nPos 
<= m_nNumItems
, 
 340                  wxT("invalid index in wxCheckListBox::InsertItems") ); 
 342     wxListBox::InsertItems( nItems
 
 346     for (i 
= 0; i 
< nItems
; i
++) 
 348         wxOwnerDrawn
*               pNewItem 
= CreateItem((size_t)(nPos 
+ i
)); 
 350         pNewItem
->SetName(asItems
[i
]); 
 351         m_aItems
.Insert(pNewItem
, (size_t)(nPos 
+ i
)); 
 352         ::WinSendMsg( (HWND
)GetHWND() 
 358 } // end of wxCheckListBox::InsertItems 
 360 bool wxCheckListBox::SetFont ( 
 366     for (i 
= 0; i 
< m_aItems
.GetCount(); i
++) 
 367         m_aItems
[i
]->SetFont(rFont
); 
 368     wxListBox::SetFont(rFont
); 
 370 } // end of wxCheckListBox::SetFont 
 373 // Create/retrieve item 
 374 // -------------------- 
 378 // Create a check list box item 
 380 wxOwnerDrawn
* wxCheckListBox::CreateItem ( 
 384     wxCheckListBoxItem
*             pItem 
= new wxCheckListBoxItem( this 
 388 } // end of wxCheckListBox::CreateItem 
 394 long wxCheckListBox::OS2OnMeasure ( 
 395   WXMEASUREITEMSTRUCT
*             pItem
 
 399         pItem 
= (WXMEASUREITEMSTRUCT
*)new OWNERITEM
; 
 400     if (wxListBox::OS2OnMeasure(pItem
) ) 
 402         POWNERITEM                  pStruct 
= (POWNERITEM
)pItem
; 
 407         m_nItemHeight 
= pStruct
->rclItem
.yTop 
- pStruct
->rclItem
.yBottom
; 
 410         // Add place for the check mark 
 412         pStruct
->rclItem
.xRight 
+= wxOwnerDrawn::GetDefaultMarginWidth(); 
 413         return long(MRFROM2SHORT((USHORT
)m_nItemHeight
, (USHORT
)(pStruct
->rclItem
.xRight 
- pStruct
->rclItem
.xLeft
))); 
 416 } // end of wxCheckListBox::CreateItem 
 422 bool wxCheckListBox::IsChecked ( 
 426     return GetItem(uiIndex
)->IsChecked(); 
 427 } // end of wxCheckListBox::IsChecked 
 429 void wxCheckListBox::Check ( 
 434     GetItem(uiIndex
)->Check(bCheck
); 
 435 } // end of wxCheckListBox::Check 
 441 void wxCheckListBox::OnChar ( 
 445     if (rEvent
.GetKeyCode() == WXK_SPACE
) 
 446         GetItem(GetSelection())->Toggle(); 
 449 } // end of wxCheckListBox::OnChar 
 451 void wxCheckListBox::OnLeftClick ( 
 456     // Clicking on the item selects it, clicking on the checkmark toggles 
 458     if (rEvent
.GetX() <= wxOwnerDrawn::GetDefaultMarginWidth()) 
 467         vDc
.SetFont(GetFont()); 
 468         vHeight 
= (wxCoord
)(vDc
.GetCharHeight() * 2.5); 
 471         // This, of course, will not work if the LB is scrolled 
 473         int                         nY 
= rEvent
.GetY(); 
 475         nY 
= nParentHeight 
- (nY 
+ vHeight
); 
 477         size_t                      nItem 
= (size_t)(nY 
/ vHeight
); 
 479         if (nItem 
< (size_t)m_nNumItems
) 
 480             GetItem(nItem
)->Toggle(); 
 482         // else: it's not an error, just click outside of client zone 
 488         // Implement default behaviour: clicking on the item selects it 
 492 } // end of wxCheckListBox::OnLeftClick