]> git.saurik.com Git - wxWidgets.git/blobdiff - src/univ/listbox.cpp
Override GetPixelSize on OS X as the base impl creates a wxScreenDC each time, which...
[wxWidgets.git] / src / univ / listbox.cpp
index 58917edc04daa2d1efc9176add6b734c17f4ccbc..7657a08ac6cdc569717c8af40d9d6bb3d5d16c6a 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        univ/listbox.cpp
+// Name:        src/univ/listbox.cpp
 // Purpose:     wxListBox implementation
 // Author:      Vadim Zeitlin
 // Modified by:
 #include "wx/univ/inphand.h"
 #include "wx/univ/theme.h"
 
+// ----------------------------------------------------------------------------
+// wxStdListboxInputHandler: handles mouse and kbd in a single or multi
+// selection listbox
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxStdListboxInputHandler : public wxStdInputHandler
+{
+public:
+    // if pressing the mouse button in a multiselection listbox should toggle
+    // the item under mouse immediately, then specify true as the second
+    // parameter (this is the standard behaviour, under GTK the item is toggled
+    // only when the mouse is released in the multi selection listbox)
+    wxStdListboxInputHandler(wxInputHandler *inphand,
+                             bool toggleOnPressAlways = true);
+
+    // base class methods
+    virtual bool HandleKey(wxInputConsumer *consumer,
+                           const wxKeyEvent& event,
+                           bool pressed);
+    virtual bool HandleMouse(wxInputConsumer *consumer,
+                             const wxMouseEvent& event);
+    virtual bool HandleMouseMove(wxInputConsumer *consumer,
+                                 const wxMouseEvent& event);
+
+protected:
+    // return the item under mouse, 0 if the mouse is above the listbox or
+    // GetCount() if it is below it
+    int HitTest(const wxListBox *listbox, const wxMouseEvent& event);
+
+    // parts of HitTest(): first finds the pseudo (because not in range) index
+    // of the item and the second one adjusts it if necessary - that is if the
+    // third one returns false
+    int HitTestUnsafe(const wxListBox *listbox, const wxMouseEvent& event);
+    int FixItemIndex(const wxListBox *listbox, int item);
+    bool IsValidIndex(const wxListBox *listbox, int item);
+
+    // init m_btnCapture and m_actionMouse
+    wxControlAction SetupCapture(wxListBox *lbox,
+                                 const wxMouseEvent& event,
+                                 int item);
+
+    wxRenderer *m_renderer;
+
+    // the button which initiated the mouse capture (currently 0 or 1)
+    int m_btnCapture;
+
+    // the action to perform when the mouse moves while we capture it
+    wxControlAction m_actionMouse;
+
+    // the ctor parameter toggleOnPressAlways (see comments near it)
+    bool m_toggleOnPressAlways;
+
+    // do we track the mouse outside the window when it is captured?
+    bool m_trackMouseOutside;
+};
+
 // ============================================================================
 // implementation of wxListBox
 // ============================================================================
@@ -168,7 +224,7 @@ int wxCMPFUNC_CONV wxListBoxSortNoCase(wxString* s1, wxString* s2)
 
 int wxListBox::DoAppendOnly(const wxString& item)
 {
-    size_t index;
+    unsigned int index;
 
     if ( IsSorted() )
     {
@@ -211,14 +267,14 @@ int wxListBox::DoAppend(const wxString& item)
     return index;
 }
 
-void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
+void wxListBox::DoInsertItems(const wxArrayString& items, unsigned int pos)
 {
     // the position of the item being added to a sorted listbox can't be
     // specified
     wxCHECK_RET( !IsSorted(), _T("can't insert items into sorted listbox") );
 
-    size_t count = items.GetCount();
-    for ( size_t n = 0; n < count; n++ )
+    unsigned int count = items.GetCount();
+    for ( unsigned int n = 0; n < count; n++ )
     {
         m_strings->Insert(items[n], pos + n);
         m_itemsClientData.Insert(NULL, pos + n);
@@ -241,16 +297,16 @@ void wxListBox::DoSetItems(const wxArrayString& items, void **clientData)
 {
     DoClear();
 
-    size_t count = items.GetCount();
+    unsigned int count = items.GetCount();
     if ( !count )
         return;
 
     m_strings->Alloc(count);
 
     m_itemsClientData.Alloc(count);
-    for ( size_t n = 0; n < count; n++ )
+    for ( unsigned int n = 0; n < count; n++ )
     {
-        size_t index = DoAppendOnly(items[n]);
+        unsigned int index = DoAppendOnly(items[n]);
 
         m_itemsClientData.Insert(clientData ? clientData[n] : NULL, index);
     }
@@ -260,7 +316,7 @@ void wxListBox::DoSetItems(const wxArrayString& items, void **clientData)
     RefreshAll();
 }
 
-void wxListBox::SetString(int n, const wxString& s)
+void wxListBox::SetString(unsigned int n, const wxString& s)
 {
     wxCHECK_RET( !IsSorted(), _T("can't set string in sorted listbox") );
 
@@ -282,7 +338,7 @@ void wxListBox::SetString(int n, const wxString& s)
             m_updateScrollbarX = true;
         }
         // or also decreased if the old string was the longest one
-        else if ( n == m_maxWidthItem )
+        else if ( n == (unsigned int)m_maxWidthItem )
         {
             RefreshHorzScrollbar();
         }
@@ -301,8 +357,8 @@ void wxListBox::DoClear()
 
     if ( HasClientObjectData() )
     {
-        size_t count = m_itemsClientData.GetCount();
-        for ( size_t n = 0; n < count; n++ )
+        unsigned int count = m_itemsClientData.GetCount();
+        for ( unsigned int n = 0; n < count; n++ )
         {
             delete (wxClientData *) m_itemsClientData[n];
         }
@@ -325,9 +381,9 @@ void wxListBox::Clear()
     RefreshAll();
 }
 
-void wxListBox::Delete(int n)
+void wxListBox::Delete(unsigned int n)
 {
-    wxCHECK_RET( n >= 0 && n < GetCount(),
+    wxCHECK_RET( IsValid(n),
                  _T("invalid index in wxListBox::Delete") );
 
     // do it before removing the index as otherwise the last item will not be
@@ -344,11 +400,11 @@ void wxListBox::Delete(int n)
     m_itemsClientData.RemoveAt(n);
 
     // when the item disappears we must not keep using its index
-    if ( n == m_current )
+    if ( (int)n == m_current )
     {
         m_current = -1;
     }
-    else if ( n < m_current )
+    else if ( (int)n < m_current )
     {
         m_current--;
     }
@@ -357,15 +413,15 @@ void wxListBox::Delete(int n)
     // update the selections array: the indices of all seletected items after
     // the one being deleted must change and the item itselfm ust be removed
     int index = wxNOT_FOUND;
-    size_t count = m_selections.GetCount();
-    for ( size_t item = 0; item < count; item++ )
+    unsigned int count = m_selections.GetCount();
+    for ( unsigned int item = 0; item < count; item++ )
     {
-        if ( m_selections[item] == n )
+        if ( m_selections[item] == (int)n )
         {
             // remember to delete it later
             index = item;
         }
-        else if ( m_selections[item] > n )
+        else if ( m_selections[item] > (int)n )
         {
             // to account for the index shift
             m_selections[item]--;
@@ -382,7 +438,7 @@ void wxListBox::Delete(int n)
     m_updateScrollbarY = true;
 
     // finally, if the longest item was deleted the scrollbar may disappear
-    if ( n == m_maxWidthItem )
+    if ( (int)n == m_maxWidthItem )
     {
         RefreshHorzScrollbar();
     }
@@ -392,22 +448,22 @@ void wxListBox::Delete(int n)
 // client data handling
 // ----------------------------------------------------------------------------
 
-void wxListBox::DoSetItemClientData(int n, void* clientData)
+void wxListBox::DoSetItemClientData(unsigned int n, void* clientData)
 {
     m_itemsClientData[n] = clientData;
 }
 
-void *wxListBox::DoGetItemClientData(int n) const
+void *wxListBox::DoGetItemClientData(unsigned int n) const
 {
     return m_itemsClientData[n];
 }
 
-void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
+void wxListBox::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
 {
     m_itemsClientData[n] = clientData;
 }
 
-wxClientData* wxListBox::DoGetItemClientObject(int n) const
+wxClientData* wxListBox::DoGetItemClientObject(unsigned int n) const
 {
     return (wxClientData *)m_itemsClientData[n];
 }
@@ -427,6 +483,7 @@ void wxListBox::DoSetSelection(int n, bool select)
                 // selecting an item in a single selection listbox deselects
                 // all the others
                 DeselectAll();
+                return;
             }
 
             m_selections.Add(n);
@@ -461,10 +518,10 @@ void wxListBox::DoSetSelection(int n, bool select)
 
 int wxListBox::GetSelection() const
 {
-    wxCHECK_MSG( !HasMultipleSelection(), -1,
+    wxCHECK_MSG( !HasMultipleSelection(), wxNOT_FOUND,
                  _T("use wxListBox::GetSelections for ths listbox") );
 
-    return m_selections.IsEmpty() ? -1 : m_selections[0];
+    return m_selections.IsEmpty() ? wxNOT_FOUND : m_selections[0];
 }
 
 int wxCMPFUNC_CONV wxCompareInts(int *n, int *m)
@@ -476,7 +533,7 @@ int wxListBox::GetSelections(wxArrayInt& selections) const
 {
     // always return sorted array to the user
     selections = m_selections;
-    size_t count = m_selections.GetCount();
+    unsigned int count = m_selections.GetCount();
 
     // don't call sort on an empty array
     if ( count )
@@ -574,9 +631,9 @@ void wxListBox::UpdateScrollbars()
     wxSize size = GetClientSize();
 
     // is our height enough to show all items?
-    int nLines = GetCount();
+    unsigned int nLines = GetCount();
     wxCoord lineHeight = GetLineHeight();
-    bool showScrollbarY = nLines*lineHeight > size.y;
+    bool showScrollbarY = (int)nLines*lineHeight > size.y;
 
     // check the width too if required
     wxCoord charWidth, maxWidth;
@@ -705,9 +762,9 @@ void wxListBox::DoDraw(wxControlRenderer *renderer)
 
     // get the items which must be redrawn
     wxCoord lineHeight = GetLineHeight();
-    size_t itemFirst = yTop / lineHeight,
-           itemLast = (yBottom + lineHeight - 1) / lineHeight,
-           itemMax = m_strings->GetCount();
+    unsigned int itemFirst = yTop / lineHeight,
+                 itemLast = (yBottom + lineHeight - 1) / lineHeight,
+                 itemMax = m_strings->GetCount();
 
     if ( itemFirst >= itemMax )
         return;
@@ -776,8 +833,8 @@ wxCoord wxListBox::GetMaxWidth() const
     {
         wxListBox *self = wxConstCast(this, wxListBox);
         wxCoord width;
-        size_t count = m_strings->GetCount();
-        for ( size_t n = 0; n < count; n++ )
+        unsigned int count = m_strings->GetCount();
+        for ( unsigned int n = 0; n < count; n++ )
         {
             GetTextExtent(this->GetString(n), &width, NULL);
             if ( width > m_maxWidth )
@@ -833,8 +890,8 @@ wxSize wxListBox::DoGetBestClientSize() const
     wxCoord width = 0,
             height = 0;
 
-    size_t count = m_strings->GetCount();
-    for ( size_t n = 0; n < count; n++ )
+    unsigned int count = m_strings->GetCount();
+    for ( unsigned int n = 0; n < count; n++ )
     {
         wxCoord w,h;
         GetTextExtent(this->GetString(n), &w, &h);
@@ -913,8 +970,8 @@ void wxListBox::SetCurrentItem(int n)
 
 bool wxListBox::FindItem(const wxString& prefix, bool strictlyAfter)
 {
-    int count = GetCount();
-    if ( !count )
+    unsigned int count = GetCount();
+    if ( count==0 )
     {
         // empty listbox, we can't find anything in it
         return false;
@@ -927,7 +984,7 @@ bool wxListBox::FindItem(const wxString& prefix, bool strictlyAfter)
     {
         // the following line will set first correctly to 0 if there is no
         // selection (m_current == -1)
-        first = m_current == count - 1 ? 0 : m_current + 1;
+        first = m_current == (int)(count - 1) ? 0 : m_current + 1;
     }
     else // start with the current
     {
@@ -937,13 +994,13 @@ bool wxListBox::FindItem(const wxString& prefix, bool strictlyAfter)
     int last = first == 0 ? count - 1 : first - 1;
 
     // if this is not true we'd never exit from the loop below!
-    wxASSERT_MSG( first < count && last < count, _T("logic error") );
+    wxASSERT_MSG( first < (int)count && last < (int)count, _T("logic error") );
 
     // precompute it outside the loop
     size_t len = prefix.length();
 
     // loop over all items in the listbox
-    for ( int item = first; item != last; item < count - 1 ? item++ : item = 0 )
+    for ( int item = first; item != (int)last; item < (int)(count - 1) ? item++ : item = 0 )
     {
         if ( wxStrnicmp(this->GetString(item).c_str(), prefix, len) == 0 )
         {
@@ -1055,8 +1112,8 @@ void wxListBox::ExtendSelection(int itemTo)
         SetSelection(n);
     }
 
-    int count = GetCount();
-    for ( ; n < count; n++ )
+    unsigned int count = GetCount();
+    for ( ; n < (int)count; n++ )
     {
         Deselect(n);
     }
@@ -1190,6 +1247,14 @@ bool wxListBox::PerformAction(const wxControlAction& action,
     return true;
 }
 
+/* static */
+wxInputHandler *wxListBox::GetStdInputHandler(wxInputHandler *handlerDef)
+{
+    static wxStdListboxInputHandler s_handler(handlerDef);
+
+    return &s_handler;
+}
+
 // ============================================================================
 // implementation of wxStdListboxInputHandler
 // ============================================================================
@@ -1230,7 +1295,7 @@ int wxStdListboxInputHandler::FixItemIndex(const wxListBox *lbox,
         // mouse is above the first item
         item = 0;
     }
-    else if ( item >= lbox->GetCount() )
+    else if ( (unsigned int)item >= lbox->GetCount() )
     {
         // mouse is below the last item
         item = lbox->GetCount() - 1;
@@ -1241,7 +1306,7 @@ int wxStdListboxInputHandler::FixItemIndex(const wxListBox *lbox,
 
 bool wxStdListboxInputHandler::IsValidIndex(const wxListBox *lbox, int item)
 {
-    return item >= 0 && item < lbox->GetCount();
+    return item >= 0 && (unsigned int)item < lbox->GetCount();
 }
 
 wxControlAction
@@ -1340,14 +1405,10 @@ bool wxStdListboxInputHandler::HandleKey(wxInputConsumer *consumer,
                 break;
 
             case WXK_PAGEUP:
-
-            case WXK_PRIOR:
                 action = wxACTION_LISTBOX_PAGEUP;
                 break;
 
             case WXK_PAGEDOWN:
-
-            case WXK_NEXT:
                 action = wxACTION_LISTBOX_PAGEDOWN;
                 break;