]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/listctrl.cpp
basic blitting implementation
[wxWidgets.git] / src / generic / listctrl.cpp
index 52fc578774f518468f1b9c0ca83fe8783fd72716..b6ca0aa425f2cc75b285dbb39d39caf47fd9173b 100644 (file)
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
-#pragma hdrstop
+    #pragma hdrstop
 #endif
 
 #if wxUSE_LISTCTRL
 
-#ifndef WX_PRECOMP
-    #include "wx/app.h"
-    #include "wx/dynarray.h"
-    #include "wx/dcscreen.h"
-    #include "wx/textctrl.h"
-#endif
-
 // under Win32 we always use the native version and also may use the generic
 // one, however some things should be done only if we use only the generic
 // version
-#if defined(__WIN32__) && !defined(__WXUNIVERSAL__)
+#if (defined(__WIN32__) && !defined(__WXUNIVERSAL__)) || defined(__WXMAC__)
     #define HAVE_NATIVE_LISTCTRL
 #endif
 
 // if we have the native control, wx/listctrl.h declares it and not this one
-#ifdef HAVE_NATIVE_LISTCTRL
-    #include "wx/generic/listctrl.h"
-#else // !HAVE_NATIVE_LISTCTRL
-    #include "wx/listctrl.h"
+#include "wx/listctrl.h"
 
+#ifndef HAVE_NATIVE_LISTCTRL
     // if we have a native version, its implementation file does all this
     IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
     IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
     IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxGenericListCtrl)
 #endif // HAVE_NATIVE_LISTCTRL/!HAVE_NATIVE_LISTCTRL
 
+#ifndef WX_PRECOMP
+    #include "wx/dynarray.h"
+    #include "wx/app.h"
+    #include "wx/dcscreen.h"
+    #include "wx/textctrl.h"
+    #include "wx/listbox.h"
+    #include "wx/math.h"
+#endif
+
 #include "wx/selstore.h"
 #include "wx/renderer.h"
-#include "wx/math.h"
 
 #ifdef __WXMAC__
     #include "wx/mac/private.h"
 #define _USE_VISATTR 0
 
 
-// ----------------------------------------------------------------------------
-// events
-// ----------------------------------------------------------------------------
-
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS)
-#if WXWIN_COMPATIBILITY_2_4
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO)
-#endif
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_RIGHT_CLICK)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_DRAGGING)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_END_DRAG)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_FOCUSED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT)
-
 // ----------------------------------------------------------------------------
 // constants
 // ----------------------------------------------------------------------------
@@ -412,7 +382,7 @@ class WXDLLEXPORT wxListHeaderWindow : public wxWindow
 {
 protected:
     wxListMainWindow  *m_owner;
-    wxCursor          *m_currentCursor;
+    const wxCursor    *m_currentCursor;
     wxCursor          *m_resizeCursor;
     bool               m_isDragging;
 
@@ -648,7 +618,7 @@ public:
     void GetImageSize( int index, int &width, int &height ) const;
     int GetTextLength( const wxString &s ) const;
 
-    void SetImageList( wxImageListType *imageList, int which );
+    void SetImageList( wxImageList *imageList, int which );
     void SetItemSpacing( int spacing, bool isSmall = false );
     int GetItemSpacing( bool isSmall = false );
 
@@ -706,7 +676,7 @@ public:
     long FindItem( long start, const wxString& str, bool partial = false );
     long FindItem( long start, wxUIntPtr data);
     long FindItem( const wxPoint& pt );
-    long HitTest( int x, int y, int &flags );
+    long HitTest( int x, int y, int &flags ) const;
     void InsertItem( wxListItem &item );
     void InsertColumn( long col, wxListItem &item );
     int GetItemWidthWithImage(wxListItem * item);
@@ -780,8 +750,8 @@ public:
     bool                 m_dirty;
 
     wxColour            *m_highlightColour;
-    wxImageListType         *m_small_image_list;
-    wxImageListType         *m_normal_image_list;
+    wxImageList         *m_small_image_list;
+    wxImageList         *m_normal_image_list;
     int                  m_small_spacing;
     int                  m_normal_spacing;
     bool                 m_hasFocus;
@@ -960,7 +930,7 @@ bool wxListItemData::IsHit( int x, int y ) const
 {
     wxCHECK_MSG( m_rect, false, _T("can't be called in this mode") );
 
-    return wxRect(GetX(), GetY(), GetWidth(), GetHeight()).Inside(x, y);
+    return wxRect(GetX(), GetY(), GetWidth(), GetHeight()).Contains(x, y);
 }
 
 int wxListItemData::GetX() const
@@ -1697,11 +1667,26 @@ void wxListHeaderWindow::AdjustDC(wxDC& dc)
     int xpix;
     m_owner->GetScrollPixelsPerUnit( &xpix, NULL );
 
-    int x;
-    m_owner->GetViewStart( &x, NULL );
+    int view_start;
+    m_owner->GetViewStart( &view_start, NULL );
+
+
+    int org_x = 0;
+    int org_y = 0;
+    dc.GetDeviceOrigin( &org_x, &org_y );
 
     // account for the horz scrollbar offset
-    dc.SetDeviceOrigin( -x * xpix, 0 );
+#ifdef __WXGTK__
+    if (GetLayoutDirection() == wxLayout_RightToLeft)
+    {
+        // Maybe we just have to check for m_signX
+        // in the DC, but I leave the #ifdef __WXGTK__
+        // for now
+        dc.SetDeviceOrigin( org_x + (view_start * xpix), org_y );
+    }
+    else
+#endif
+        dc.SetDeviceOrigin( org_x - (view_start * xpix), org_y );
 }
 
 void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
@@ -1760,7 +1745,7 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
         static const int MARGIN_BETWEEN_TEXT_AND_ICON = 2;
         int ix = 0, iy = 0;    // init them just to suppress the compiler warnings
         const int image = item.m_image;
-        wxImageListType *imageList;
+        wxImageList *imageList;
         if ( image != -1 )
         {
             imageList = m_owner->m_small_image_list;
@@ -2033,6 +2018,8 @@ wxListTextCtrlWrapper::wxListTextCtrlWrapper(wxListMainWindow *owner,
     m_text->Create(owner, wxID_ANY, m_startValue,
                    wxPoint(rectLabel.x-4,rectLabel.y-4),
                    wxSize(rectLabel.width+11,rectLabel.height+8));
+    m_text->SetFocus();
+
     m_text->PushEventHandler(this);
 }
 
@@ -2045,7 +2032,7 @@ void wxListTextCtrlWrapper::Finish()
         m_text->RemoveEventHandler(this);
         m_owner->FinishEditing(m_text);
 
-        delete this;
+        wxPendingDelete.Append( this );
     }
 }
 
@@ -2087,8 +2074,8 @@ void wxListTextCtrlWrapper::OnChar( wxKeyEvent &event )
             break;
 
         case WXK_ESCAPE:
-            Finish();
             m_owner->OnRenameCancelled( m_itemEdited );
+            Finish();
             break;
 
         default:
@@ -2123,16 +2110,13 @@ void wxListTextCtrlWrapper::OnKillFocus( wxFocusEvent &event )
 {
     if ( !m_finished && !m_aboutToFinish )
     {
-        // We must finish regardless of success, otherwise we'll get
-        // focus problems:
-        Finish();
-
         if ( !AcceptChanges() )
             m_owner->OnRenameCancelled( m_itemEdited );
+
+        Finish();
     }
 
-    // We must let the native text control handle focus, too, otherwise
-    // it could have problems with the cursor (e.g., in wxGTK).
+    // We must let the native text control handle focus
     event.Skip();
 }
 
@@ -2163,8 +2147,8 @@ void wxListMainWindow::Init()
     m_headerWidth =
     m_lineHeight = 0;
 
-    m_small_image_list = (wxImageListType *) NULL;
-    m_normal_image_list = (wxImageListType *) NULL;
+    m_small_image_list = (wxImageList *) NULL;
+    m_normal_image_list = (wxImageList *) NULL;
 
     m_small_spacing = 30;
     m_normal_spacing = 40;
@@ -2381,7 +2365,7 @@ long wxListMainWindow::HitTestLine(size_t line, int x, int y) const
 
     wxListLineData *ld = GetLine(line);
 
-    if ( ld->HasImage() && GetLineIconRect(line).Inside(x, y) )
+    if ( ld->HasImage() && GetLineIconRect(line).Contains(x, y) )
         return wxLIST_HITTEST_ONITEMICON;
 
     // VS: Testing for "ld->HasText() || InReportView()" instead of
@@ -2392,7 +2376,7 @@ long wxListMainWindow::HitTestLine(size_t line, int x, int y) const
         wxRect rect = InReportView() ? GetLineRect(line)
                                      : GetLineLabelRect(line);
 
-        if ( rect.Inside(x, y) )
+        if ( rect.Contains(x, y) )
             return wxLIST_HITTEST_ONITEMLABEL;
     }
 
@@ -2629,9 +2613,9 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
         GetVisibleLinesRange(&visibleFrom, &visibleTo);
 
         wxRect rectLine;
-        wxCoord xOrig, yOrig;
-        CalcUnscrolledPosition(0, 0, &xOrig, &yOrig);
-
+        int xOrig = dc.LogicalToDeviceX( 0 );
+        int yOrig = dc.LogicalToDeviceY( 0 );
+        
         // tell the caller cache to cache the data
         if ( IsVirtual() )
         {
@@ -2647,7 +2631,8 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
         {
             rectLine = GetLineRect(line);
 
-            if ( !IsExposed(rectLine.x - xOrig, rectLine.y - yOrig,
+
+            if ( !IsExposed(rectLine.x + xOrig, rectLine.y + yOrig,
                             rectLine.width, rectLine.height) )
             {
                 // don't redraw unaffected lines to avoid flicker
@@ -2858,6 +2843,7 @@ void wxListMainWindow::OnRenameCancelled(size_t itemEdit)
 
 void wxListMainWindow::OnMouse( wxMouseEvent &event )
 {
+
 #ifdef __WXMAC__
     // On wxMac we can't depend on the EVT_KILL_FOCUS event to properly
     // shutdown the edit control when the mouse is clicked elsewhere on the
@@ -2879,7 +2865,15 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event )
     }
 
     if ( !HasCurrent() || IsEmpty() )
+    {
+        if (event.RightDown())
+        {
+            SendNotify( (size_t)-1, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, event.GetPosition() );
+            // Allow generation of context menu event
+            event.Skip();
+        }
         return;
+    }
 
     if (m_dirty)
         return;
@@ -2949,8 +2943,19 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event )
 
     if ( !hitResult )
     {
-        // outside of any item, reset the selection and bail out
-        HighlightAll(false);
+        // outside of any item
+        if (event.RightDown())
+        {
+            SendNotify( (size_t) -1, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, event.GetPosition() );
+            // Allow generation of context menu event
+            event.Skip();
+        }
+        else
+        {
+            // reset the selection and bail out
+            HighlightAll(false);
+        }
+
         return;
     }
 
@@ -3240,7 +3245,19 @@ void wxListMainWindow::OnChar( wxKeyEvent &event )
         return;
     }
 
-    switch (event.GetKeyCode())
+    // don't use m_linesPerPage directly as it might not be computed yet
+    const int pageSize = GetCountPerPage();
+    wxCHECK_RET( pageSize, _T("should have non zero page size") );
+
+    if (GetLayoutDirection() == wxLayout_RightToLeft)
+    {
+        if (event.GetKeyCode() == WXK_RIGHT)
+            event.m_keyCode = WXK_LEFT;
+        else if (event.GetKeyCode() == WXK_LEFT)
+            event.m_keyCode = WXK_RIGHT;
+    }
+
+    switch ( event.GetKeyCode() )
     {
         case WXK_UP:
             if ( m_current > 0 )
@@ -3264,7 +3281,8 @@ void wxListMainWindow::OnChar( wxKeyEvent &event )
 
         case WXK_PAGEUP:
             {
-                int steps = InReportView() ? m_linesPerPage - 1 : m_current % m_linesPerPage;
+                int steps = InReportView() ? pageSize - 1
+                                           : m_current % pageSize;
 
                 int index = m_current - steps;
                 if (index < 0)
@@ -3277,8 +3295,8 @@ void wxListMainWindow::OnChar( wxKeyEvent &event )
         case WXK_PAGEDOWN:
             {
                 int steps = InReportView()
-                               ? m_linesPerPage - 1
-                               : m_linesPerPage - (m_current % m_linesPerPage) - 1;
+                                ? pageSize - 1
+                                : pageSize - (m_current % pageSize) - 1;
 
                 size_t index = m_current + steps;
                 size_t count = GetItemCount();
@@ -3292,7 +3310,7 @@ void wxListMainWindow::OnChar( wxKeyEvent &event )
         case WXK_LEFT:
             if ( !InReportView() )
             {
-                int index = m_current - m_linesPerPage;
+                int index = m_current - pageSize;
                 if (index < 0)
                     index = 0;
 
@@ -3303,7 +3321,7 @@ void wxListMainWindow::OnChar( wxKeyEvent &event )
         case WXK_RIGHT:
             if ( !InReportView() )
             {
-                size_t index = m_current + m_linesPerPage;
+                size_t index = m_current + pageSize;
 
                 size_t count = GetItemCount();
                 if ( index >= count )
@@ -3435,7 +3453,7 @@ int wxListMainWindow::GetTextLength( const wxString &s ) const
     return lw + AUTOSIZE_COL_MARGIN;
 }
 
-void wxListMainWindow::SetImageList( wxImageListType *imageList, int which )
+void wxListMainWindow::SetImageList( wxImageList *imageList, int which )
 {
     m_dirty = true;
 
@@ -4407,7 +4425,7 @@ long wxListMainWindow::FindItem( const wxPoint& pt )
     return wxNOT_FOUND;
 }
 
-long wxListMainWindow::HitTest( int x, int y, int &flags )
+long wxListMainWindow::HitTest( int x, int y, int &flags ) const
 {
     CalcUnscrolledPosition( x, y, &x, &y );
 
@@ -4670,9 +4688,9 @@ END_EVENT_TABLE()
 
 wxGenericListCtrl::wxGenericListCtrl()
 {
-    m_imageListNormal = (wxImageListType *) NULL;
-    m_imageListSmall = (wxImageListType *) NULL;
-    m_imageListState = (wxImageListType *) NULL;
+    m_imageListNormal = (wxImageList *) NULL;
+    m_imageListSmall = (wxImageList *) NULL;
+    m_imageListState = (wxImageList *) NULL;
 
     m_ownsImageListNormal =
     m_ownsImageListSmall =
@@ -4742,7 +4760,7 @@ bool wxGenericListCtrl::Create(wxWindow *parent,
 {
     m_imageListNormal =
     m_imageListSmall =
-    m_imageListState = (wxImageListType *) NULL;
+    m_imageListState = (wxImageList *) NULL;
     m_ownsImageListNormal =
     m_ownsImageListSmall =
     m_ownsImageListState = false;
@@ -5026,10 +5044,12 @@ wxSize wxGenericListCtrl::GetItemSpacing() const
     return wxSize(spacing, spacing);
 }
 
+#if WXWIN_COMPATIBILITY_2_6
 int wxGenericListCtrl::GetItemSpacing( bool isSmall ) const
 {
     return m_mainWin->GetItemSpacing( isSmall );
 }
+#endif // WXWIN_COMPATIBILITY_2_6
 
 void wxGenericListCtrl::SetItemTextColour( long item, const wxColour &col )
 {
@@ -5106,7 +5126,7 @@ long wxGenericListCtrl::GetNextItem( long item, int geom, int state ) const
     return m_mainWin->GetNextItem( item, geom, state );
 }
 
-wxImageListType *wxGenericListCtrl::GetImageList(int which) const
+wxImageList *wxGenericListCtrl::GetImageList(int which) const
 {
     if (which == wxIMAGE_LIST_NORMAL)
         return m_imageListNormal;
@@ -5115,10 +5135,10 @@ wxImageListType *wxGenericListCtrl::GetImageList(int which) const
     else if (which == wxIMAGE_LIST_STATE)
         return m_imageListState;
 
-    return (wxImageListType *) NULL;
+    return (wxImageList *) NULL;
 }
 
-void wxGenericListCtrl::SetImageList( wxImageListType *imageList, int which )
+void wxGenericListCtrl::SetImageList( wxImageList *imageList, int which )
 {
     if ( which == wxIMAGE_LIST_NORMAL )
     {
@@ -5145,7 +5165,7 @@ void wxGenericListCtrl::SetImageList( wxImageListType *imageList, int which )
     m_mainWin->SetImageList( imageList, which );
 }
 
-void wxGenericListCtrl::AssignImageList(wxImageListType *imageList, int which)
+void wxGenericListCtrl::AssignImageList(wxImageList *imageList, int which)
 {
     SetImageList(imageList, which);
     if ( which == wxIMAGE_LIST_NORMAL )
@@ -5229,7 +5249,8 @@ long wxGenericListCtrl::FindItem( long WXUNUSED(start), const wxPoint& pt,
     return m_mainWin->FindItem( pt );
 }
 
-long wxGenericListCtrl::HitTest( const wxPoint &point, int &flags )
+// TODO: sub item hit testing
+long wxGenericListCtrl::HitTest(const wxPoint& point, int& flags, long *) const
 {
     return m_mainWin->HitTest( (int)point.x, (int)point.y, flags );
 }
@@ -5421,10 +5442,6 @@ bool wxGenericListCtrl::SetFont( const wxFont &font )
     return true;
 }
 
-#if _USE_VISATTR
-#include "wx/listbox.h"
-#endif
-
 // static
 wxVisualAttributes
 wxGenericListCtrl::GetClassDefaultAttributes(wxWindowVariant variant)
@@ -5486,12 +5503,12 @@ bool wxGenericListCtrl::DoPopupMenu( wxMenu *menu, int x, int y )
 
 void wxGenericListCtrl::DoClientToScreen( int *x, int *y ) const
 {
-    return m_mainWin->DoClientToScreen(x, y);
+    m_mainWin->DoClientToScreen(x, y);
 }
 
 void wxGenericListCtrl::DoScreenToClient( int *x, int *y ) const
 {
-    return m_mainWin->DoScreenToClient(x, y);
+    m_mainWin->DoScreenToClient(x, y);
 }
 
 void wxGenericListCtrl::SetFocus()