]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/listctrl.cpp
replace @b Note with @note; replace '' with "
[wxWidgets.git] / src / generic / listctrl.cpp
index f040ab1d53331c927490fff2f259bfe6ea1dddb9..a3419d15c7d37337ddf6bc6dcf2afbf71760a4ea 100644 (file)
@@ -42,6 +42,7 @@
     #include "wx/dcclient.h"
     #include "wx/dcscreen.h"
     #include "wx/math.h"
+    #include "wx/settings.h"
 #endif
 
 #include "wx/imaglist.h"
@@ -242,7 +243,7 @@ private:
 //  wxListLineData (internal)
 //-----------------------------------------------------------------------------
 
-WX_DECLARE_EXPORTED_LIST(wxListItemData, wxListItemDataList);
+WX_DECLARE_LIST(wxListItemData, wxListItemDataList);
 #include "wx/listimpl.cpp"
 WX_DEFINE_LIST(wxListItemDataList)
 
@@ -374,7 +375,7 @@ private:
                            int width);
 };
 
-WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData, wxListLineDataArray);
+WX_DECLARE_OBJARRAY(wxListLineData, wxListLineDataArray);
 #include "wx/arrimpl.cpp"
 WX_DEFINE_OBJARRAY(wxListLineDataArray)
 
@@ -463,7 +464,7 @@ public:
 
     wxTextCtrl *GetText() const { return m_text; }
 
-    void AcceptChangesAndFinish();
+    void EndEdit( bool discardChanges );
 
 protected:
     void OnChar( wxKeyEvent &event );
@@ -471,14 +472,13 @@ protected:
     void OnKillFocus( wxFocusEvent &event );
 
     bool AcceptChanges();
-    void Finish();
+    void Finish( bool setfocus );
 
 private:
     wxListMainWindow   *m_owner;
     wxTextCtrl         *m_text;
     wxString            m_startValue;
     size_t              m_itemEdited;
-    bool                m_finished;
     bool                m_aboutToFinish;
 
     DECLARE_EVENT_TABLE()
@@ -488,7 +488,7 @@ private:
 //  wxListMainWindow (internal)
 //-----------------------------------------------------------------------------
 
-WX_DECLARE_EXPORTED_LIST(wxListHeaderData, wxListHeaderDataList);
+WX_DECLARE_LIST(wxListHeaderData, wxListHeaderDataList);
 #include "wx/listimpl.cpp"
 WX_DEFINE_LIST(wxListHeaderDataList)
 
@@ -579,6 +579,8 @@ public:
     // bring the selected item into view, scrolling to it if necessary
     void MoveToItem(size_t item);
 
+    bool ScrollList( int WXUNUSED(dx), int dy );
+
     // bring the current item into view
     void MoveToFocus() { MoveToItem(m_current); }
 
@@ -590,17 +592,12 @@ public:
         return m_textctrlWrapper ? m_textctrlWrapper->GetText() : NULL;
     }
 
-    void FinishEditing(wxTextCtrl *text)
+    void ResetTextControl(wxTextCtrl *text)
     {
         delete text;
         m_textctrlWrapper = NULL;
-        SetFocusIgnoringChildren();
     }
 
-    // suspend/resume redrawing the control
-    void Freeze();
-    void Thaw();
-
     void OnRenameTimer();
     bool OnRenameAccept(size_t itemEdit, const wxString& value);
     void OnRenameCancelled(size_t itemEdit);
@@ -847,9 +844,6 @@ private:
     wxBrush *m_highlightBrush,
             *m_highlightUnfocusedBrush;
 
-    // if this is > 0, the control is frozen and doesn't redraw itself
-    size_t m_freezeCount;
-
     // wrapper around the text control currently used for in place editing or
     // NULL if no item is being edited
     wxListTextCtrlWrapper *m_textctrlWrapper;
@@ -1414,7 +1408,7 @@ bool wxListLineData::SetAttributes(wxDC *dc,
 #ifdef __WXMAC__
     {
         if (m_owner->HasFocus()
-#ifdef __WXMAC__
+#if !defined(__WXUNIVERSAL__)
                 && IsControlActive( (ControlRef)m_owner->GetHandle() )
 #endif
         )
@@ -1448,7 +1442,7 @@ bool wxListLineData::SetAttributes(wxDC *dc,
         if ( highlighted )
             dc->SetBrush( *m_owner->GetHighlightBrush() );
         else
-            dc->SetBrush(wxBrush(attr->GetBackgroundColour(), wxSOLID));
+            dc->SetBrush(wxBrush(attr->GetBackgroundColour(), wxBRUSHSTYLE_SOLID));
 
         dc->SetPen( *wxTRANSPARENT_PEN );
 
@@ -1478,7 +1472,7 @@ void wxListLineData::Draw( wxDC *dc )
         {
             int flags = wxCONTROL_SELECTED;
             if (m_owner->HasFocus()
-#ifdef __WXMAC__
+#if defined( __WXMAC__ ) && !defined(__WXUNIVERSAL__)
                 && IsControlActive( (ControlRef)m_owner->GetHandle() )
 #endif
             )
@@ -1540,11 +1534,7 @@ void wxListLineData::DrawInReportMode( wxDC *dc,
         if (highlighted)
         {
             int flags = wxCONTROL_SELECTED;
-            if (m_owner->HasFocus()
-#ifdef __WXMAC__
-                && IsControlActive( (ControlRef)m_owner->GetHandle() )
-#endif
-            )
+            if (m_owner->HasFocus())
                 flags |= wxCONTROL_FOCUSED;
             wxRendererNative::Get().DrawItemSelectionRect( m_owner, *dc, rectHL, flags );
         }
@@ -1575,6 +1565,9 @@ void wxListLineData::DrawInReportMode( wxDC *dc,
         int xOld = x;
         x += width;
 
+        const int wText = width - 8;
+        wxDCClipper clipper(*dc, xOld, rect.y, wText, rect.height);
+
         if ( item->HasImage() )
         {
             int ix, iy;
@@ -1588,7 +1581,7 @@ void wxListLineData::DrawInReportMode( wxDC *dc,
         }
 
         if ( item->HasText() )
-            DrawTextFormatted(dc, item->GetText(), col, xOld, yMid, width - 8);
+            DrawTextFormatted(dc, item->GetText(), col, xOld, yMid, wText);
     }
 }
 
@@ -1797,7 +1790,7 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
     GetClientSize( &w, &h );
     m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
 
-    dc.SetBackgroundMode(wxTRANSPARENT);
+    dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
     dc.SetTextForeground(GetForegroundColour());
 
     int x = HEADER_OFFSET_X;
@@ -1906,6 +1899,9 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
 
 void wxListHeaderWindow::DrawCurrent()
 {
+#if 1
+    m_owner->SetColumnWidth( m_column, m_currentX - m_minX );
+#else
     int x1 = m_currentX;
     int y1 = 0;
     m_owner->ClientToScreen( &x1, &y1 );
@@ -1928,6 +1924,7 @@ void wxListHeaderWindow::DrawCurrent()
 
     dc.SetPen( wxNullPen );
     dc.SetBrush( wxNullBrush );
+#endif
 }
 
 void wxListHeaderWindow::OnMouse( wxMouseEvent &event )
@@ -2120,7 +2117,6 @@ wxListTextCtrlWrapper::wxListTextCtrlWrapper(wxListMainWindow *owner,
 {
     m_owner = owner;
     m_text = text;
-    m_finished = false;
     m_aboutToFinish = false;
 
     wxRect rectLabel = owner->GetLineLabelRect(itemEdit);
@@ -2136,19 +2132,37 @@ wxListTextCtrlWrapper::wxListTextCtrlWrapper(wxListMainWindow *owner,
     m_text->PushEventHandler(this);
 }
 
-void wxListTextCtrlWrapper::Finish()
+void wxListTextCtrlWrapper::EndEdit(bool discardChanges)
 {
-    if ( !m_finished )
+    m_aboutToFinish = true;
+
+    if ( discardChanges )
     {
-        m_finished = true;
+        m_owner->OnRenameCancelled(m_itemEdited);
 
-        m_text->RemoveEventHandler(this);
-        m_owner->FinishEditing(m_text);
+        Finish( true );
+    }
+    else
+    {
+        // Notify the owner about the changes
+        AcceptChanges();
 
-        wxPendingDelete.Append( this );
+        // Even if vetoed, close the control (consistent with MSW)
+        Finish( true );
     }
 }
 
+void wxListTextCtrlWrapper::Finish( bool setfocus )
+{
+    m_text->RemoveEventHandler(this);
+    m_owner->ResetTextControl( m_text );
+
+    wxPendingDelete.Append( this );
+
+    if (setfocus)
+        m_owner->SetFocusIgnoringChildren();
+}
+
 bool wxListTextCtrlWrapper::AcceptChanges()
 {
     const wxString value = m_text->GetValue();
@@ -2168,28 +2182,16 @@ bool wxListTextCtrlWrapper::AcceptChanges()
     return true;
 }
 
-void wxListTextCtrlWrapper::AcceptChangesAndFinish()
-{
-    m_aboutToFinish = true;
-
-    // Notify the owner about the changes
-    AcceptChanges();
-
-    // Even if vetoed, close the control (consistent with MSW)
-    Finish();
-}
-
 void wxListTextCtrlWrapper::OnChar( wxKeyEvent &event )
 {
     switch ( event.m_keyCode )
     {
         case WXK_RETURN:
-            AcceptChangesAndFinish();
+            EndEdit( false );
             break;
 
         case WXK_ESCAPE:
-            m_owner->OnRenameCancelled( m_itemEdited );
-            Finish();
+            EndEdit( true );
             break;
 
         default:
@@ -2199,35 +2201,32 @@ void wxListTextCtrlWrapper::OnChar( wxKeyEvent &event )
 
 void wxListTextCtrlWrapper::OnKeyUp( wxKeyEvent &event )
 {
-    if (m_finished)
+    if (m_aboutToFinish)
     {
-        event.Skip();
-        return;
+        // auto-grow the textctrl:
+        wxSize parentSize = m_owner->GetSize();
+        wxPoint myPos = m_text->GetPosition();
+        wxSize mySize = m_text->GetSize();
+        int sx, sy;
+        m_text->GetTextExtent(m_text->GetValue() + _T("MM"), &sx, &sy);
+        if (myPos.x + sx > parentSize.x)
+            sx = parentSize.x - myPos.x;
+       if (mySize.x > sx)
+            sx = mySize.x;
+       m_text->SetSize(sx, wxDefaultCoord);
     }
 
-    // auto-grow the textctrl:
-    wxSize parentSize = m_owner->GetSize();
-    wxPoint myPos = m_text->GetPosition();
-    wxSize mySize = m_text->GetSize();
-    int sx, sy;
-    m_text->GetTextExtent(m_text->GetValue() + _T("MM"), &sx, &sy);
-    if (myPos.x + sx > parentSize.x)
-        sx = parentSize.x - myPos.x;
-    if (mySize.x > sx)
-        sx = mySize.x;
-    m_text->SetSize(sx, wxDefaultCoord);
-
     event.Skip();
 }
 
 void wxListTextCtrlWrapper::OnKillFocus( wxFocusEvent &event )
 {
-    if ( !m_finished && !m_aboutToFinish )
+    if ( !m_aboutToFinish )
     {
         if ( !AcceptChanges() )
             m_owner->OnRenameCancelled( m_itemEdited );
 
-        Finish();
+        Finish( false );
     }
 
     // We must let the native text control handle focus
@@ -2280,8 +2279,6 @@ void wxListMainWindow::Init()
     m_lineLastClicked =
     m_lineSelectSingleOnUp =
     m_lineBeforeLastClicked = (size_t)-1;
-
-    m_freezeCount = 0;
 }
 
 wxListMainWindow::wxListMainWindow()
@@ -2309,7 +2306,7 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent,
                             (
                                 wxSYS_COLOUR_HIGHLIGHT
                             ),
-                            wxSOLID
+                            wxBRUSHSTYLE_SOLID
                          );
 
     m_highlightUnfocusedBrush = new wxBrush
@@ -2318,7 +2315,7 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent,
                                  (
                                      wxSYS_COLOUR_BTNSHADOW
                                  ),
-                                 wxSOLID
+                                 wxBRUSHSTYLE_SOLID
                               );
 
     SetScrollbars( 0, 0, 0, 0, 0, 0 );
@@ -2458,9 +2455,9 @@ wxRect wxListMainWindow::GetLineLabelRect(size_t line) const
     }
 
     wxRect rect;
-    rect.x = HEADER_OFFSET_X;
+    rect.x = image_x + HEADER_OFFSET_X;
     rect.y = GetLineY(line);
-    rect.width = GetColumnWidth(0);
+    rect.width = GetColumnWidth(0) - image_x;
     rect.height = GetLineHeight();
 
     return rect;
@@ -2700,32 +2697,23 @@ void wxListMainWindow::RefreshSelected()
     }
 }
 
-void wxListMainWindow::Freeze()
-{
-    m_freezeCount++;
-}
-
-void wxListMainWindow::Thaw()
-{
-    wxCHECK_RET( m_freezeCount > 0, _T("thawing unfrozen list control?") );
-
-    if ( --m_freezeCount == 0 )
-        Refresh();
-}
-
 void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
 {
     // Note: a wxPaintDC must be constructed even if no drawing is
     // done (a Windows requirement).
     wxPaintDC dc( this );
 
-    if ( IsEmpty() || m_freezeCount )
+    if ( IsEmpty() )
+    {
         // nothing to draw or not the moment to draw it
         return;
+    }
 
     if ( m_dirty )
+    {
         // delay the repainting until we calculate all the items positions
         return;
+    }
 
     PrepareDC( dc );
 
@@ -2776,7 +2764,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
 
         if ( HasFlag(wxLC_HRULES) )
         {
-            wxPen pen(GetRuleColour(), 1, wxSOLID);
+            wxPen pen(GetRuleColour(), 1, wxPENSTYLE_SOLID);
             wxSize clientSize = GetClientSize();
 
             size_t i = visibleFrom;
@@ -2802,7 +2790,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
         // Draw vertical rules if required
         if ( HasFlag(wxLC_VRULES) && !IsEmpty() )
         {
-            wxPen pen(GetRuleColour(), 1, wxSOLID);
+            wxPen pen(GetRuleColour(), 1, wxPENSTYLE_SOLID);
             wxRect firstItemRect, lastItemRect;
 
             GetItemRect(visibleFrom, firstItemRect);
@@ -2864,9 +2852,10 @@ void wxListMainWindow::HighlightAll( bool on )
             RefreshLine(m_current);
         }
     }
-    else // multi sel
+    else // multi selection
     {
-        HighlightLines(0, GetItemCount() - 1, on);
+        if ( !IsEmpty() )
+            HighlightLines(0, GetItemCount() - 1, on);
     }
 }
 
@@ -3001,11 +2990,11 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event )
     // listctrl because the order of events is different (or something like
     // that), so explicitly end the edit if it is active.
     if ( event.LeftDown() && m_textctrlWrapper )
-        m_textctrlWrapper->AcceptChangesAndFinish();
+        m_textctrlWrapper->EndEdit( false );
 #endif // __WXMAC__
 
     if ( event.LeftDown() )
-        SetFocus();
+        SetFocusIgnoringChildren();
 
     event.SetEventObject( GetParent() );
     if ( GetParent()->GetEventHandler()->ProcessEvent( event) )
@@ -3023,8 +3012,13 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event )
         if (event.RightDown())
         {
             SendNotify( (size_t)-1, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, event.GetPosition() );
-            // Allow generation of context menu event
-            event.Skip();
+
+            wxContextMenuEvent evtCtx(
+                wxEVT_CONTEXT_MENU,
+                GetParent()->GetId(),
+                ClientToScreen(event.GetPosition()));
+            evtCtx.SetEventObject(GetParent());
+            GetParent()->GetEventHandler()->ProcessEvent(evtCtx);
         }
         return;
     }
@@ -3101,8 +3095,13 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event )
         if (event.RightDown())
         {
             SendNotify( (size_t) -1, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, event.GetPosition() );
-            // Allow generation of context menu event
-            event.Skip();
+
+            wxContextMenuEvent evtCtx(
+                wxEVT_CONTEXT_MENU,
+                GetParent()->GetId(),
+                ClientToScreen(event.GetPosition()));
+            evtCtx.SetEventObject(GetParent());
+            GetParent()->GetEventHandler()->ProcessEvent(evtCtx);
         }
         else
         {
@@ -3150,15 +3149,12 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event )
                 (hitResult == wxLIST_HITTEST_ONITEMLABEL) &&
                 HasFlag(wxLC_EDIT_LABELS) )
             {
-                if (InReportView())
+                if ( !InReportView() ||
+                        GetLineLabelRect(current).Contains(x, y) )
                 {
-                    wxRect label = GetLineLabelRect( current );
-                    if (label.Contains( x, y ))
-                        m_renameTimer->Start( 250, true );
-
+                    int dclick = wxSystemSettings::GetMetric(wxSYS_DCLICK_MSEC);
+                    m_renameTimer->Start(dclick > 0 ? dclick : 250, true);
                 }
-                else
-                    m_renameTimer->Start( 250, true );
             }
         }
 
@@ -3284,16 +3280,65 @@ void wxListMainWindow::MoveToItem(size_t item)
             Scroll( -1, rect.y / hLine );
         if (rect.y + rect.height + 5 > view_y + client_h)
             Scroll( -1, (rect.y + rect.height - client_h + hLine) / hLine );
+
+#ifdef __WXMAC__
+        // At least on Mac the visible lines value will get reset inside of
+        // Scroll *before* it actually scrolls the window because of the
+        // Update() that happens there, so it will still have the wrong value.
+        // So let's reset it again and wait for it to be recalculated in the
+        // next paint event.  I would expect this problem to show up in wxGTK
+        // too but couldn't duplicate it there.  Perhaps the order of events
+        // is different...  --Robin
+        ResetVisibleLinesRange();
+#endif
     }
     else // !report
     {
+        int sx = -1,
+            sy = -1;
+
         if (rect.x-view_x < 5)
-            Scroll( (rect.x - 5) / SCROLL_UNIT_X, -1 );
+            sx = (rect.x - 5) / SCROLL_UNIT_X;
         if (rect.x + rect.width - 5 > view_x + client_w)
-            Scroll( (rect.x + rect.width - client_w + SCROLL_UNIT_X) / SCROLL_UNIT_X, -1 );
+            sx = (rect.x + rect.width - client_w + SCROLL_UNIT_X) / SCROLL_UNIT_X;
+
+        if (rect.y-view_y < 5)
+            sy = (rect.y - 5) / hLine;
+        if (rect.y + rect.height - 5 > view_y + client_h)
+            sy = (rect.y + rect.height - client_h + hLine) / hLine;
+
+        Scroll(sx, sy);
     }
 }
 
+bool wxListMainWindow::ScrollList(int WXUNUSED(dx), int dy)
+{
+    if ( !InReportView() )
+    {
+        // TODO: this should work in all views but is not implemented now
+        return false;
+    }
+
+    size_t top, bottom;
+    GetVisibleLinesRange(&top, &bottom);
+
+    if ( bottom == (size_t)-1 )
+        return 0;
+
+    ResetVisibleLinesRange();
+
+    int hLine = GetLineHeight();
+
+    Scroll(-1, top + dy / hLine);
+
+#ifdef __WXMAC__
+    // see comment in MoveToItem() for why we do this
+    ResetVisibleLinesRange();
+#endif
+
+    return true;
+}
+
 // ----------------------------------------------------------------------------
 // keyboard handling
 // ----------------------------------------------------------------------------
@@ -3410,16 +3455,8 @@ void wxListMainWindow::OnChar( wxKeyEvent &event )
     ke.SetEventObject( parent );
     if (parent->GetEventHandler()->ProcessEvent( ke )) return;
 
-    if (event.GetKeyCode() == WXK_TAB)
-    {
-        wxNavigationKeyEvent nevent;
-        nevent.SetWindowChange( event.ControlDown() );
-        nevent.SetDirection( !event.ShiftDown() );
-        nevent.SetEventObject( GetParent()->GetParent() );
-        nevent.SetCurrentFocus( m_parent );
-        if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent ))
-            return;
-    }
+    if ( HandleAsNavigationKey(event) )
+        return;
 
     // no item -> nothing to do
     if (!HasCurrent())
@@ -5001,12 +5038,12 @@ bool wxGenericListCtrl::Create(wxWindow *parent,
 
     m_mainWin = new wxListMainWindow( this, wxID_ANY, wxPoint(0, 0), size, style );
 
-#ifdef  __WXMAC_CARBON__
+#ifdef __WXMAC__
     // Human Interface Guidelines ask us for a special font in this case
     if ( GetWindowVariant() == wxWINDOW_VARIANT_NORMAL )
     {
         wxFont font;
-        font.MacCreateThemeFont( kThemeViewsFont );
+        font.MacCreateFromThemeFont( kThemeViewsFont );
         SetFont( font );
     }
 #endif
@@ -5015,11 +5052,11 @@ bool wxGenericListCtrl::Create(wxWindow *parent,
     {
         CreateHeaderWindow();
 
-#ifdef  __WXMAC_CARBON__
+#ifdef __WXMAC__
         if (m_headerWin)
         {
             wxFont font;
-            font.MacCreateThemeFont( kThemeSmallSystemFont );
+            font.MacCreateFromThemeFont( kThemeSmallSystemFont );
             m_headerWin->SetFont( font );
             CalculateAndSetHeaderHeight();
         }
@@ -5550,9 +5587,9 @@ long wxGenericListCtrl::InsertColumn( long col, const wxString &heading,
     return InsertColumn( col, item );
 }
 
-bool wxGenericListCtrl::ScrollList( int WXUNUSED(dx), int WXUNUSED(dy) )
+bool wxGenericListCtrl::ScrollList( int dx, int dy )
 {
-    return 0;
+    return m_mainWin->ScrollList(dx, dy);
 }
 
 // Sort items.
@@ -5860,14 +5897,4 @@ void wxGenericListCtrl::Refresh(bool eraseBackground, const wxRect *rect)
     }
 }
 
-void wxGenericListCtrl::Freeze()
-{
-    m_mainWin->Freeze();
-}
-
-void wxGenericListCtrl::Thaw()
-{
-    m_mainWin->Thaw();
-}
-
 #endif // wxUSE_LISTCTRL