]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/vlbox.cpp
split string.{h,cpp} into {string,stringimpl,arrstr}.{h,cpp} to make the files more...
[wxWidgets.git] / src / generic / vlbox.cpp
index d2e6964fdd392d5bf21fe7581175cb4c6d559761..a9bfc5ceb6ac9929297f6ecffece386f0e288acf 100644 (file)
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////////
-// Name:        generic/vlbox.cpp
+// Name:        src/generic/vlbox.cpp
 // Purpose:     implementation of wxVListBox
 // Author:      Vadim Zeitlin
 // Modified by:
 
 #if wxUSE_LISTBOX
 
+#include "wx/vlbox.h"
+
 #ifndef WX_PRECOMP
     #include "wx/settings.h"
     #include "wx/dcclient.h"
+    #include "wx/listbox.h"
 #endif //WX_PRECOMP
 
-#include "wx/vlbox.h"
 #include "wx/dcbuffer.h"
 #include "wx/selstore.h"
+#include "wx/renderer.h"
 
 // ----------------------------------------------------------------------------
 // event tables
@@ -45,6 +48,9 @@ BEGIN_EVENT_TABLE(wxVListBox, wxVScrolledWindow)
     EVT_KEY_DOWN(wxVListBox::OnKeyDown)
     EVT_LEFT_DOWN(wxVListBox::OnLeftDown)
     EVT_LEFT_DCLICK(wxVListBox::OnLeftDClick)
+
+    EVT_SET_FOCUS(wxVListBox::OnSetOrKillFocus)
+    EVT_KILL_FOCUS(wxVListBox::OnSetOrKillFocus)
 END_EVENT_TABLE()
 
 // ============================================================================
@@ -62,7 +68,6 @@ void wxVListBox::Init()
     m_current =
     m_anchor = wxNOT_FOUND;
     m_selStore = NULL;
-    m_doubleBuffer = NULL;
 }
 
 bool wxVListBox::Create(wxWindow *parent,
@@ -82,7 +87,10 @@ bool wxVListBox::Create(wxWindow *parent,
     // make sure the native widget has the right colour since we do
     // transparent drawing by default
     SetBackgroundColour(GetBackgroundColour());
-    m_colBgSel = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
+
+    // leave m_colBgSel in an invalid state: it means for OnDrawBackground()
+    // to use wxRendererNative instead of painting selection bg ourselves
+    m_colBgSel = wxNullColour;
 
     // flicker-free drawing requires this
     SetBackgroundStyle(wxBG_STYLE_CUSTOM);
@@ -92,7 +100,6 @@ bool wxVListBox::Create(wxWindow *parent,
 
 wxVListBox::~wxVListBox()
 {
-    delete m_doubleBuffer;    
     delete m_selStore;
 }
 
@@ -231,7 +238,7 @@ bool wxVListBox::DoSetCurrent(int current)
             // it is, indeed, only partly visible, so scroll it into view to
             // make it entirely visible
             while ( (size_t)m_current == GetLastVisibleLine() &&
-                    ScrollToLine(GetVisibleBegin()+1) );
+                    ScrollToLine(GetVisibleBegin()+1) ) ;
 
             // but in any case refresh it as even if it was only partly visible
             // before we need to redraw it entirely as its background changed
@@ -262,7 +269,10 @@ void wxVListBox::SetSelection(int selection)
 
     if ( HasMultipleSelection() )
     {
-        Select(selection);
+        if (selection != wxNOT_FOUND)
+            Select(selection);
+        else
+            DeselectAll();
         m_anchor = selection;
     }
 
@@ -296,6 +306,16 @@ int wxVListBox::GetNextSelected(unsigned long& cookie) const
     return wxNOT_FOUND;
 }
 
+void wxVListBox::RefreshSelected()
+{
+    // only refresh those items which are currently visible and selected:
+    for ( size_t n = GetVisibleBegin(), end = GetVisibleEnd(); n < end; n++ )
+    {
+        if ( IsSelected(n) )
+            RefreshLine(n);
+    }
+}
+
 // ----------------------------------------------------------------------------
 // wxVListBox appearance parameters
 // ----------------------------------------------------------------------------
@@ -332,47 +352,52 @@ void wxVListBox::OnDrawSeparator(wxDC& WXUNUSED(dc),
 
 void wxVListBox::OnDrawBackground(wxDC& dc, const wxRect& rect, size_t n) const
 {
-    // we need to render selected and current items differently
-    const bool isSelected = IsSelected(n),
-               isCurrent = IsCurrent(n);
-    if ( isSelected || isCurrent )
+    if ( m_colBgSel.IsOk() )
     {
-        if ( isSelected )
-        {
-            dc.SetBrush(wxBrush(m_colBgSel, wxSOLID));
-        }
-        else // !selected
+        // we need to render selected and current items differently
+        const bool isSelected = IsSelected(n),
+                   isCurrent = IsCurrent(n);
+        if ( isSelected || isCurrent )
         {
-            dc.SetBrush(*wxTRANSPARENT_BRUSH);
+            if ( isSelected )
+            {
+                dc.SetBrush(wxBrush(m_colBgSel, wxSOLID));
+            }
+            else // !selected
+            {
+                dc.SetBrush(*wxTRANSPARENT_BRUSH);
+            }
+            dc.SetPen(*(isCurrent ? wxBLACK_PEN : wxTRANSPARENT_PEN));
+            dc.DrawRectangle(rect);
         }
-
-        dc.SetPen(*(isCurrent ? wxBLACK_PEN : wxTRANSPARENT_PEN));
-
-        dc.DrawRectangle(rect);
+        //else: do nothing for the normal items
+    }
+    else // use wxRendererNative for a more native look&feel:
+    {
+        int flags = 0;
+        if ( IsSelected(n) )
+            flags |= wxCONTROL_SELECTED;
+        if ( IsCurrent(n) )
+            flags |= wxCONTROL_CURRENT;
+        if ( wxWindow::FindFocus() == wx_const_cast(wxVListBox*, this) )
+            flags |= wxCONTROL_FOCUSED;
+
+        wxRendererNative::Get().DrawItemSelectionRect(
+            wx_const_cast(wxVListBox *, this), dc, rect, flags);
     }
-    //else: do nothing for the normal items
 }
 
 void wxVListBox::OnPaint(wxPaintEvent& WXUNUSED(event))
 {
-    // If size is larger, recalculate double buffer bitmap
     wxSize clientSize = GetClientSize();
 
-    if ( !m_doubleBuffer ||
-         clientSize.x > m_doubleBuffer->GetWidth() ||
-         clientSize.y > m_doubleBuffer->GetHeight() )
-    {
-        delete m_doubleBuffer;
-        m_doubleBuffer = new wxBitmap(clientSize.x+25,clientSize.y+25);
-    }
-
-    wxBufferedPaintDC dc(this,*m_doubleBuffer);
+    wxAutoBufferedPaintDC dc(this);
 
     // the update rectangle
     wxRect rectUpdate = GetUpdateClientRect();
 
-    // Fill it with background colour
-    dc.SetBrush(GetBackgroundColour());
+    // fill it with background colour
+    dc.SetBackground(GetBackgroundColour());
     dc.Clear();
 
     // the bounding rectangle of the current line
@@ -380,8 +405,8 @@ void wxVListBox::OnPaint(wxPaintEvent& WXUNUSED(event))
     rectLine.width = clientSize.x;
 
     // iterate over all visible lines
-    const size_t lineMax = GetLastVisibleLine();
-    for ( size_t line = GetFirstVisibleLine(); line <= lineMax; line++ )
+    const size_t lineMax = GetVisibleEnd();
+    for ( size_t line = GetFirstVisibleLine(); line < lineMax; line++ )
     {
         const wxCoord hLine = OnGetLineHeight(line);
 
@@ -416,6 +441,15 @@ void wxVListBox::OnPaint(wxPaintEvent& WXUNUSED(event))
     }
 }
 
+void wxVListBox::OnSetOrKillFocus(wxFocusEvent& WXUNUSED(event))
+{
+    // we need to repaint the selection when we get the focus since
+    // wxRendererNative in general draws the focused selection differently
+    // from the unfocused selection (see OnDrawItem):
+    RefreshSelected();
+}
+
+
 // ============================================================================
 // wxVListBox keyboard/mouse handling
 // ============================================================================
@@ -636,7 +670,7 @@ void wxVListBox::OnLeftDClick(wxMouseEvent& eventMouse)
         {
             OnLeftDown(eventMouse);
         }
-    
+
     }
 }
 
@@ -645,8 +679,6 @@ void wxVListBox::OnLeftDClick(wxMouseEvent& eventMouse)
 // use the same default attributes as wxListBox
 // ----------------------------------------------------------------------------
 
-#include "wx/listbox.h"
-
 //static
 wxVisualAttributes
 wxVListBox::GetClassDefaultAttributes(wxWindowVariant variant)