]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/listctrl.cpp
better focus handling (blind fix)
[wxWidgets.git] / src / generic / listctrl.cpp
index 595d70345b52e924fdbe295452e9c61bd929d071..2744044c86fbd12e0dc895a9547b174a2158dd48 100644 (file)
@@ -9,9 +9,10 @@
 /////////////////////////////////////////////////////////////////////////////
 
 /*
 /////////////////////////////////////////////////////////////////////////////
 
 /*
-   TODO for better virtual list control support:
+   TODO
 
 
-   1. we need to implement searching/sorting somehow
+   1. we need to implement searching/sorting for virtual controls somehow
+   2. when changing selection the lines are refreshed twice
  */
 
 // ============================================================================
  */
 
 // ============================================================================
@@ -1630,10 +1631,6 @@ void wxListLineData::DrawInReportMode( wxDC *dc,
                                        const wxRect& rectHL,
                                        bool highlighted )
 {
                                        const wxRect& rectHL,
                                        bool highlighted )
 {
-    // use our own flag if we maintain it
-    if ( !IsVirtual() )
-        highlighted = m_highlighted;
-
     // TODO: later we should support setting different attributes for
     //       different columns - to do it, just add "col" argument to
     //       GetAttr() and move these lines into the loop below
     // TODO: later we should support setting different attributes for
     //       different columns - to do it, just add "col" argument to
     //       GetAttr() and move these lines into the loop below
@@ -2421,6 +2418,15 @@ bool wxListMainWindow::HighlightLine( size_t line, bool highlight )
 
 void wxListMainWindow::RefreshLine( size_t line )
 {
 
 void wxListMainWindow::RefreshLine( size_t line )
 {
+    if ( HasFlag(wxLC_REPORT) )
+    {
+        size_t visibleFrom, visibleTo;
+        GetVisibleLinesRange(&visibleFrom, &visibleTo);
+
+        if ( line < visibleFrom || line > visibleTo )
+            return;
+    }
+
     wxRect rect = GetLineRect(line);
 
     CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
     wxRect rect = GetLineRect(line);
 
     CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
@@ -2555,7 +2561,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
             GetLine(line)->DrawInReportMode( &dc,
                                              rectLine,
                                              GetLineHighlightRect(line),
             GetLine(line)->DrawInReportMode( &dc,
                                              rectLine,
                                              GetLineHighlightRect(line),
-                                             IsHighlighted(line) );
+                                             m_hasFocus && IsHighlighted(line) );
         }
 
         if ( HasFlag(wxLC_HRULES) )
         }
 
         if ( HasFlag(wxLC_HRULES) )
@@ -2612,15 +2618,18 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
         }
     }
 
         }
     }
 
-    if ( HasCurrent() && m_hasFocus )
+    if ( HasCurrent() )
     {
     {
+        // don't draw rect outline under Max if we already have the background
+        // color
 #ifdef __WXMAC__
 #ifdef __WXMAC__
-        // no rect outline, we already have the background color
-#else
-        dc.SetPen( *wxBLACK_PEN );
-        dc.SetBrush( *wxTRANSPARENT_BRUSH );
-        dc.DrawRectangle( GetLineHighlightRect(m_current) );
-#endif
+        if ( !m_hasFocus )
+#endif // !__WXMAC__
+        {
+            dc.SetPen( *wxBLACK_PEN );
+            dc.SetBrush( *wxTRANSPARENT_BRUSH );
+            dc.DrawRectangle( GetLineHighlightRect(m_current) );
+        }
     }
 
     dc.EndDrawing();
     }
 
     dc.EndDrawing();
@@ -2657,7 +2666,11 @@ void wxListMainWindow::SendNotify( size_t line,
     if ( point != wxDefaultPosition )
         le.m_pointDrag = point;
 
     if ( point != wxDefaultPosition )
         le.m_pointDrag = point;
 
-    if ( command != wxEVT_COMMAND_LIST_DELETE_ITEM )
+    // don't try to get the line info for virtual list controls: the main
+    // program has it anyhow and if we did it would result in accessing all
+    // the lines, even those which are not visible now and this is precisely
+    // what we're trying to avoid
+    if ( !IsVirtual() && (command != wxEVT_COMMAND_LIST_DELETE_ITEM) )
     {
         GetLine(line)->GetItem( 0, le.m_item );
     }
     {
         GetLine(line)->GetItem( 0, le.m_item );
     }
@@ -3163,11 +3176,16 @@ void wxListMainWindow::OnChar( wxKeyEvent &event )
                 le.m_itemIndex = m_current;
                 GetLine(m_current)->GetItem( 0, le.m_item );
                 GetParent()->GetEventHandler()->ProcessEvent( le );
                 le.m_itemIndex = m_current;
                 GetLine(m_current)->GetItem( 0, le.m_item );
                 GetParent()->GetEventHandler()->ProcessEvent( le );
+
+                if ( IsHighlighted(m_current) )
+                {
+                    // don't unselect the item in single selection mode
+                    break;
+                }
+                //else: select it in ReverseHighlight() below if unselected
             }
             }
-            else
-            {
-                ReverseHighlight(m_current);
-            }
+
+            ReverseHighlight(m_current);
             break;
 
         case WXK_RETURN:
             break;
 
         case WXK_RETURN:
@@ -3488,8 +3506,9 @@ void wxListMainWindow::SetItemState( long litem, long state, long stateMask )
                   _T("invalid list ctrl item index in SetItem") );
 
     size_t oldCurrent = m_current;
                   _T("invalid list ctrl item index in SetItem") );
 
     size_t oldCurrent = m_current;
-    size_t item = (size_t)litem;    // sdafe because of the check above
+    size_t item = (size_t)litem;    // safe because of the check above
 
 
+    // do we need to change the focus?
     if ( stateMask & wxLIST_STATE_FOCUSED )
     {
         if ( state & wxLIST_STATE_FOCUSED )
     if ( stateMask & wxLIST_STATE_FOCUSED )
     {
         if ( state & wxLIST_STATE_FOCUSED )
@@ -3501,9 +3520,13 @@ void wxListMainWindow::SetItemState( long litem, long state, long stateMask )
                 m_current = item;
                 OnFocusLine( m_current );
 
                 m_current = item;
                 OnFocusLine( m_current );
 
-                if ( IsSingleSel() && (oldCurrent != (size_t)-1) )
+                if ( oldCurrent != (size_t)-1 )
                 {
                 {
-                    HighlightLine(oldCurrent, FALSE);
+                    if ( IsSingleSel() )
+                    {
+                        HighlightLine(oldCurrent, FALSE);
+                    }
+
                     RefreshLine(oldCurrent);
                 }
 
                     RefreshLine(oldCurrent);
                 }
 
@@ -3517,10 +3540,13 @@ void wxListMainWindow::SetItemState( long litem, long state, long stateMask )
             {
                 OnUnfocusLine( m_current );
                 m_current = (size_t)-1;
             {
                 OnUnfocusLine( m_current );
                 m_current = (size_t)-1;
+
+                RefreshLine( oldCurrent );
             }
         }
     }
 
             }
         }
     }
 
+    // do we need to change the selection state?
     if ( stateMask & wxLIST_STATE_SELECTED )
     {
         bool on = (state & wxLIST_STATE_SELECTED) != 0;
     if ( stateMask & wxLIST_STATE_SELECTED )
     {
         bool on = (state & wxLIST_STATE_SELECTED) != 0;
@@ -3781,7 +3807,7 @@ void wxListMainWindow::RefreshAll()
     Refresh();
 
     wxListHeaderWindow *headerWin = GetListCtrl()->m_headerWin;
     Refresh();
 
     wxListHeaderWindow *headerWin = GetListCtrl()->m_headerWin;
-    if ( headerWin )
+    if ( headerWin && headerWin->m_dirty )
     {
         headerWin->m_dirty = FALSE;
         headerWin->Refresh();
     {
         headerWin->m_dirty = FALSE;
         headerWin->Refresh();
@@ -3881,6 +3907,7 @@ void wxListMainWindow::DeleteItem( long lindex )
         m_lines.RemoveAt( index );
     }
 
         m_lines.RemoveAt( index );
     }
 
+    // we need to refresh the (vert) scrollbar as the number of items changed
     m_dirty = TRUE;
 
     SendNotify( index, wxEVT_COMMAND_LIST_DELETE_ITEM );
     m_dirty = TRUE;
 
     SendNotify( index, wxEVT_COMMAND_LIST_DELETE_ITEM );