home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / os2 / checklst.cpp < prev    next >
C/C++ Source or Header  |  2002-12-27  |  14KB  |  474 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name:        checklst.cpp
  3. // Purpose:     implementation of wxCheckListBox class
  4. // Author:      David Webster
  5. // Modified by:
  6. // Created:     10/13/99
  7. // RCS-ID:      $Id: CHECKLST.CPP,v 1.12.2.1 2002/12/27 14:49:34 JS Exp $
  8. // Copyright:   (c) David Webster
  9. // Licence:     wxWindows licence
  10. ///////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // headers & declarations
  14. // ============================================================================
  15.  
  16. // For compilers that support precompilation, includes "wx.h".
  17. #include "wx/wxprec.h"
  18.  
  19. #if wxUSE_OWNER_DRAWN
  20.  
  21. #include "wx/object.h"
  22. #include "wx/colour.h"
  23. #include "wx/font.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"
  32. #include "wx/log.h"
  33.  
  34. #define INCL_PM
  35. #include <os2.h>
  36.  
  37. // ----------------------------------------------------------------------------
  38. // private functions
  39. // ----------------------------------------------------------------------------
  40.  
  41. // get item (converted to right type)
  42. #define GetItem(n)    ((wxCheckListBoxItem *)(GetItem(n)))
  43.  
  44. // ============================================================================
  45. // implementation
  46. // ============================================================================
  47.  
  48. IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox, wxListBox)
  49.  
  50. // ----------------------------------------------------------------------------
  51. // declaration and implementation of wxCheckListBoxItem class
  52. // ----------------------------------------------------------------------------
  53.  
  54. class wxCheckListBoxItem : public wxOwnerDrawn
  55. {
  56.     friend class wxCheckListBox;
  57. public:
  58.     //
  59.     // ctor
  60.     //
  61.     wxCheckListBoxItem( wxCheckListBox* pParent
  62.                        ,size_t          nIndex
  63.                       );
  64.  
  65.     //
  66.     // Drawing functions
  67.     //
  68.     virtual bool OnDrawItem( wxDC&         rDc
  69.                             ,const wxRect& rRect
  70.                             ,wxODAction    eAct
  71.                             ,wxODStatus    eStat
  72.                            );
  73.  
  74.     //
  75.     // Simple accessors
  76.     //
  77.     bool IsChecked(void) const  { return m_bChecked; }
  78.     void Check(bool bCheck);
  79.     void Toggle(void) { Check(!IsChecked()); }
  80.  
  81. private:
  82.     bool                            m_bChecked;
  83.     wxCheckListBox*                 m_pParent;
  84.     size_t                          m_nIndex;
  85. }; // end of CLASS wxCheckListBoxItem
  86.  
  87. wxCheckListBoxItem::wxCheckListBoxItem (
  88.   wxCheckListBox*                   pParent
  89. , size_t                            nIndex
  90. )
  91. : wxOwnerDrawn( ""
  92.                ,TRUE // checkable
  93.               )
  94. {
  95.     m_bChecked = FALSE;
  96.     m_pParent  = pParent;
  97.     m_nIndex   = nIndex;
  98.  
  99.     //
  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
  103.     //
  104.     SetMarginWidth(GetDefaultMarginWidth());
  105. } // end of wxCheckListBoxItem::wxCheckListBoxItem
  106.  
  107. bool wxCheckListBoxItem::OnDrawItem (
  108.   wxDC&                             rDc
  109. , const wxRect&                     rRect
  110. , wxODAction                        eAct
  111. , wxODStatus                        eStat
  112. )
  113. {
  114.     wxRect                          vRect = rRect;
  115.  
  116.     ::WinQueryWindowRect( m_pParent->GetHWND()
  117.                          ,&rDc.m_vRclPaint
  118.                         );
  119.     if (IsChecked())
  120.         eStat = (wxOwnerDrawn::wxODStatus)(eStat | wxOwnerDrawn::wxODChecked);
  121.  
  122.     //
  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 wxWindows coords.
  126.     //
  127.     vRect.x += 5;
  128.     vRect.y -= 3;
  129.     if (wxOwnerDrawn::OnDrawItem( rDc
  130.                                  ,vRect
  131.                                  ,eAct
  132.                                  ,eStat))
  133.     {
  134.         size_t                      nCheckWidth  = GetDefaultMarginWidth();
  135.         size_t                      nCheckHeight = m_pParent->GetItemHeight();
  136.         int                         nParentHeight;
  137.         int                         nX = rRect.GetX();
  138.         int                         nY = rRect.GetY();
  139.         int                         nOldY = nY;
  140.         wxColour                    vColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
  141.         wxPen                       vPenBack;
  142.         wxPen                       vPenGray;
  143.         wxPen                       vPenPrev;
  144.  
  145.         m_pParent->GetSize( NULL
  146.                            ,&nParentHeight
  147.                           );
  148.  
  149.         nY = nParentHeight - nY - nCheckHeight;
  150.         vPenBack = wxPen(vColour, 1, wxSOLID);
  151.         vPenGray = wxPen(wxColour(127, 127, 127), 1, wxSOLID);
  152.  
  153.         //
  154.         // Erase the 1-pixel border
  155.         //
  156.         rDc.SetPen(vPenBack);
  157.         rDc.DrawRectangle( nX
  158.                           ,nY
  159.                           ,nCheckWidth
  160.                           ,nCheckHeight
  161.                          );
  162.  
  163.         //
  164.         // Now we draw the smaller rectangle
  165.         //
  166.         nY++;
  167.         nCheckWidth  -= 2;
  168.         nCheckHeight -= 2;
  169.  
  170.         //
  171.         // Draw hollow gray rectangle
  172.         //
  173.         rDc.SetPen(vPenGray);
  174.         rDc.DrawRectangle( nX
  175.                           ,nY
  176.                           ,nCheckWidth
  177.                           ,nCheckHeight
  178.                          );
  179.  
  180.         nX++;
  181.         if (IsChecked())
  182.         {
  183.             //
  184.             // Draw the check by loading the sys standard bitmap and drawing it
  185.             //
  186.             HBITMAP                 hChkBmp = ::WinGetSysBitmap( HWND_DESKTOP
  187.                                                                 ,SBMP_MENUCHECK
  188.                                                                );
  189.             POINTL                  vPoint = {nX, nOldY + 3};
  190.  
  191.             ::WinDrawBitmap( rDc.GetHPS()
  192.                             ,hChkBmp
  193.                             ,NULL
  194.                             ,&vPoint
  195.                             ,NULL
  196.                             ,NULL
  197.                             ,DBM_NORMAL
  198.                            );
  199.         }
  200.         return TRUE;
  201.     }
  202.     return FALSE;
  203. } // end of wxCheckListBoxItem::OnDrawItem
  204.  
  205. //
  206. // Change the state of the item and redraw it
  207. //
  208. void wxCheckListBoxItem::Check (
  209.   bool                              bCheck
  210. )
  211. {
  212.     m_bChecked = bCheck;
  213.  
  214.     //
  215.     // Index may be chanegd because new items were added/deleted
  216.     //
  217.     if (m_pParent->GetItemIndex(this) != (int)m_nIndex)
  218.     {
  219.         //
  220.         // Update it
  221.         //
  222.         int                         nIndex = m_pParent->GetItemIndex(this);
  223.  
  224.         wxASSERT_MSG(nIndex != wxNOT_FOUND, wxT("what does this item do here?"));
  225.  
  226.         m_nIndex = (size_t)nIndex;
  227.     }
  228.  
  229.     HWND                            hWndListbox = (HWND)m_pParent->GetHWND();
  230.     RECTL                           rUpdate;
  231.     MRESULT                         mRc;
  232.  
  233.     wxCommandEvent                  vEvent( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
  234.                                            ,m_pParent->GetId()
  235.                                           );
  236.  
  237.     vEvent.SetInt(m_nIndex);
  238.     vEvent.SetEventObject(m_pParent);
  239.     m_pParent->ProcessCommand(vEvent);
  240. } // end of wxCheckListBoxItem::Check
  241.  
  242. // ----------------------------------------------------------------------------
  243. // implementation of wxCheckListBox class
  244. // ----------------------------------------------------------------------------
  245.  
  246. // define event table
  247. // ------------------
  248. BEGIN_EVENT_TABLE(wxCheckListBox, wxListBox)
  249.   EVT_CHAR(wxCheckListBox::OnChar)
  250.   EVT_LEFT_DOWN(wxCheckListBox::OnLeftClick)
  251. END_EVENT_TABLE()
  252.  
  253. //
  254. // Control creation
  255. // ----------------
  256. //
  257.  
  258. //
  259. // Default ctor: use Create() to really create the control
  260. //
  261. wxCheckListBox::wxCheckListBox()
  262. : wxListBox()
  263. {
  264. } // end of wxCheckListBox::wxCheckListBox
  265.  
  266. //
  267. // Ctor which creates the associated control
  268. //
  269. wxCheckListBox::wxCheckListBox (
  270.   wxWindow*                         pParent
  271. , wxWindowID                        vId
  272. , const wxPoint&                    rPos
  273. , const wxSize&                     rSize
  274. , int                               nStrings
  275. , const wxString                    asChoices[]
  276. , long                              lStyle
  277. , const wxValidator&                rVal
  278. , const wxString&                   rsName
  279. )
  280.               : wxListBox()
  281. {
  282.     Create( pParent
  283.            ,vId
  284.            ,rPos
  285.            ,rSize
  286.            ,nStrings
  287.            ,asChoices
  288.            ,lStyle | wxLB_OWNERDRAW
  289.            ,rVal
  290.            ,rsName
  291.           );
  292. } // end of wxCheckListBox::wxCheckListBox
  293.  
  294. void wxCheckListBox::Delete(
  295.   int                               N
  296. )
  297. {
  298.     wxCHECK_RET( N >= 0 && N < m_nNumItems,
  299.                  wxT("invalid index in wxListBox::Delete") );
  300.     wxListBox::Delete(N);
  301.  
  302.     //
  303.     // Free memory
  304.     //
  305.     delete m_aItems[N];
  306.     m_aItems.RemoveAt(N);
  307. } // end of wxCheckListBox::Delete
  308.  
  309. void wxCheckListBox::InsertItems (
  310.   int                               nItems
  311. , const wxString                    asItems[]
  312. , int                               nPos
  313. )
  314. {
  315.     int                             i;
  316.  
  317.     wxCHECK_RET( nPos >= 0 && nPos <= m_nNumItems,
  318.                  wxT("invalid index in wxCheckListBox::InsertItems") );
  319.  
  320.     wxListBox::InsertItems( nItems
  321.                            ,asItems
  322.                            ,nPos
  323.                           );
  324.     for (i = 0; i < nItems; i++)
  325.     {
  326.         wxOwnerDrawn*               pNewItem = CreateItem((size_t)(nPos + i));
  327.  
  328.         pNewItem->SetName(asItems[i]);
  329.         m_aItems.Insert(pNewItem, (size_t)(nPos + i));
  330.         ::WinSendMsg( (HWND)GetHWND()
  331.                      ,LM_SETITEMHANDLE
  332.                      ,(MPARAM)(i + nPos)
  333.                      ,MPFROMP(pNewItem)
  334.                     );
  335.     }
  336. } // end of wxCheckListBox::InsertItems
  337.  
  338. bool wxCheckListBox::SetFont (
  339.   const wxFont&                     rFont
  340. )
  341. {
  342.     size_t                          i;
  343.  
  344.     for (i = 0; i < m_aItems.GetCount(); i++)
  345.         m_aItems[i]->SetFont(rFont);
  346.     wxListBox::SetFont(rFont);
  347.     return TRUE;
  348. } // end of wxCheckListBox::SetFont
  349.  
  350. //
  351. // Create/retrieve item
  352. // --------------------
  353. //
  354.  
  355. //
  356. // Create a check list box item
  357. //
  358. wxOwnerDrawn* wxCheckListBox::CreateItem (
  359.   size_t                            nIndex
  360. )
  361. {
  362.     wxCheckListBoxItem*             pItem = new wxCheckListBoxItem( this
  363.                                                                    ,nIndex
  364.                                                                   );
  365.     return pItem;
  366. } // end of wxCheckListBox::CreateItem
  367.  
  368. //
  369. // Return item size
  370. // ----------------
  371. //
  372. long wxCheckListBox::OS2OnMeasure (
  373.   WXMEASUREITEMSTRUCT*             pItem
  374. )
  375. {
  376.     if (!pItem)
  377.         pItem = (WXMEASUREITEMSTRUCT*)new OWNERITEM;
  378.     if (wxListBox::OS2OnMeasure(pItem) )
  379.     {
  380.         POWNERITEM                  pStruct = (POWNERITEM)pItem;
  381.  
  382.         //
  383.         // Save item height
  384.         //
  385.         m_nItemHeight = pStruct->rclItem.yTop - pStruct->rclItem.yBottom;
  386.  
  387.         //
  388.         // Add place for the check mark
  389.         //
  390.         pStruct->rclItem.xRight += wxOwnerDrawn::GetDefaultMarginWidth();
  391.         return long(MRFROM2SHORT((USHORT)m_nItemHeight, (USHORT)(pStruct->rclItem.xRight - pStruct->rclItem.xLeft)));
  392.     }
  393.     return 0L;
  394. } // end of wxCheckListBox::CreateItem
  395.  
  396. //
  397. // Check items
  398. // -----------
  399. //
  400. bool wxCheckListBox::IsChecked (
  401.   size_t                            uiIndex
  402. ) const
  403. {
  404.     return GetItem(uiIndex)->IsChecked();
  405. } // end of wxCheckListBox::IsChecked
  406.  
  407. void wxCheckListBox::Check (
  408.   size_t                            uiIndex
  409. , bool                              bCheck
  410. )
  411. {
  412.     GetItem(uiIndex)->Check(bCheck);
  413. } // end of wxCheckListBox::Check
  414.  
  415. //
  416. // Process events
  417. // --------------
  418. //
  419. void wxCheckListBox::OnChar (
  420.   wxKeyEvent&                       rEvent
  421. )
  422. {
  423.     if (rEvent.KeyCode() == WXK_SPACE)
  424.         GetItem(GetSelection())->Toggle();
  425.     else
  426.         rEvent.Skip();
  427. } // end of wxCheckListBox::OnChar
  428.  
  429. void wxCheckListBox::OnLeftClick (
  430.   wxMouseEvent&                     rEvent
  431. )
  432. {
  433.     //
  434.     // Clicking on the item selects it, clicking on the checkmark toggles
  435.     //
  436.     if (rEvent.GetX() <= wxOwnerDrawn::GetDefaultMarginWidth())
  437.     {
  438.         int                         nParentHeight;
  439.         wxScreenDC                  vDc;
  440.         wxCoord                     vHeight;
  441.  
  442.         GetSize( NULL
  443.                 ,&nParentHeight
  444.                );
  445.         vDc.SetFont(GetFont());
  446.         vHeight = vDc.GetCharHeight() * 2.5;
  447.  
  448.         //
  449.         // This, of course, will not work if the LB is scrolled
  450.         //
  451.         int                         nY = rEvent.GetY();
  452.  
  453.         nY = nParentHeight - (nY + vHeight);
  454.  
  455.         size_t                      nItem = (size_t)(nY / vHeight);
  456.  
  457.         if (nItem < (size_t)m_nNumItems)
  458.             GetItem(nItem)->Toggle();
  459.         //
  460.         // else: it's not an error, just click outside of client zone
  461.         //
  462.     }
  463.     else
  464.     {
  465.         //
  466.         // Implement default behaviour: clicking on the item selects it
  467.         //
  468.         rEvent.Skip();
  469.     }
  470. } // end of wxCheckListBox::OnLeftClick
  471.  
  472. #endif
  473.  
  474.