]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/listctrl.cpp
Initialize the field count in Create(). It was using a garbage value
[wxWidgets.git] / src / generic / listctrl.cpp
index 6421ecff5205a17fb1ea19e4114d842deb01f612..90f95e61f752e5315ec1428b4aa4170df9c6934f 100644 (file)
 #include "wx/generic/imaglist.h"
 
 #ifndef wxUSE_GENERIC_LIST_EXTENSIONS
-#define wxUSE_GENERIC_LIST_EXTENSIONS 0
+#define wxUSE_GENERIC_LIST_EXTENSIONS 1
 #endif
 
+// ============================================================================
+// private classes
+// ============================================================================
+
+//-----------------------------------------------------------------------------
+//  wxListItemData (internal)
+//-----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxListItemData : public wxObject
+{
+public:
+    wxString   m_text;
+    int        m_image;
+    long       m_data;
+    int        m_xpos,m_ypos;
+    int        m_width,m_height;
+
+    wxListItemAttr *m_attr;
+
+public:
+    wxListItemData();
+    ~wxListItemData() { delete m_attr; }
+
+    wxListItemData( const wxListItem &info );
+    void SetItem( const wxListItem &info );
+    void SetText( const wxString &s );
+    void SetImage( int image );
+    void SetData( long data );
+    void SetPosition( int x, int y );
+    void SetSize( int width, int height );
+    bool HasImage() const;
+    bool HasText() const;
+    bool IsHit( int x, int y ) const;
+    void GetText( wxString &s );
+    const wxString& GetText() { return m_text; }
+    int GetX( void ) const;
+    int GetY( void ) const;
+    int GetWidth() const;
+    int GetHeight() const;
+    int GetImage() const;
+    void GetItem( wxListItem &info ) const;
+
+    wxListItemAttr *GetAttributes() const { return m_attr; }
+
+private:
+    DECLARE_DYNAMIC_CLASS(wxListItemData);
+};
+
+//-----------------------------------------------------------------------------
+//  wxListHeaderData (internal)
+//-----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxListHeaderData : public wxObject
+{
+protected:
+    long      m_mask;
+    int       m_image;
+    wxString  m_text;
+    int       m_format;
+    int       m_width;
+    int       m_xpos,m_ypos;
+    int       m_height;
+
+public:
+    wxListHeaderData();
+    wxListHeaderData( const wxListItem &info );
+    void SetItem( const wxListItem &item );
+    void SetPosition( int x, int y );
+    void SetWidth( int w );
+    void SetFormat( int format );
+    void SetHeight( int h );
+    bool HasImage() const;
+    bool HasText() const;
+    bool IsHit( int x, int y ) const;
+    void GetItem( wxListItem &item );
+    void GetText( wxString &s );
+    int GetImage() const;
+    int GetWidth() const;
+    int GetFormat() const;
+    
+private:
+    DECLARE_DYNAMIC_CLASS(wxListHeaderData);
+};
+
+//-----------------------------------------------------------------------------
+//  wxListLineData (internal)
+//-----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxListLineData : public wxObject
+{
+public:
+    wxList              m_items;
+    wxRect              m_bound_all;
+    wxRect              m_bound_label;
+    wxRect              m_bound_icon;
+    wxRect              m_bound_hilight;
+    int                 m_mode;
+    bool                m_hilighted;
+    wxBrush            *m_hilightBrush;
+    int                 m_spacing;
+    wxListMainWindow   *m_owner;
+
+    void DoDraw( wxDC *dc, bool hilight, bool paintBG );
+
+public:
+    wxListLineData() {}
+    wxListLineData( wxListMainWindow *owner, int mode, wxBrush *hilightBrush );
+    void CalculateSize( wxDC *dc, int spacing );
+    void SetPosition( wxDC *dc, int x, int y,  int window_width );
+    void SetColumnPosition( int index, int x );
+    void GetSize( int &width, int &height );
+    void GetExtent( int &x, int &y, int &width, int &height );
+    void GetLabelExtent( int &x, int &y, int &width, int &height );
+    long IsHit( int x, int y );
+    void InitItems( int num );
+    void SetItem( int index, const wxListItem &info );
+    void GetItem( int index, wxListItem &info );
+    void GetText( int index, wxString &s );
+    void SetText( int index, const wxString s );
+    int GetImage( int index );
+    void GetRect( wxRect &rect );
+    void Hilight( bool on );
+    void ReverseHilight();
+    void DrawRubberBand( wxDC *dc, bool on );
+    void Draw( wxDC *dc );
+    bool IsInRect( int x, int y, const wxRect &rect );
+    bool IsHilighted();
+    void AssignRect( wxRect &dest, int x, int y, int width, int height );
+    void AssignRect( wxRect &dest, const wxRect &source );
+    
+private:
+    void SetAttributes(wxDC *dc,
+                       const wxListItemAttr *attr,
+                       const wxColour& colText, const wxFont& font,
+                       bool hilight);
+
+    DECLARE_DYNAMIC_CLASS(wxListLineData);
+};
+
+//-----------------------------------------------------------------------------
+//  wxListHeaderWindow (internal)
+//-----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxListHeaderWindow : public wxWindow
+{
+protected:
+    wxListMainWindow  *m_owner;
+    wxCursor          *m_currentCursor;
+    wxCursor          *m_resizeCursor;
+    bool               m_isDragging;
+    int                m_column;
+    int                m_minX;
+    int                m_currentX;
+
+public:
+    wxListHeaderWindow();
+    ~wxListHeaderWindow();
+    wxListHeaderWindow( wxWindow *win, wxWindowID id, wxListMainWindow *owner,
+      const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize,
+      long style = 0, const wxString &name = "wxlistctrlcolumntitles" );
+    void DoDrawRect( wxDC *dc, int x, int y, int w, int h );
+    void OnPaint( wxPaintEvent &event );
+    void DrawCurrent();
+    void OnMouse( wxMouseEvent &event );
+    void OnSetFocus( wxFocusEvent &event );
+
+private:
+    DECLARE_DYNAMIC_CLASS(wxListHeaderWindow)
+    DECLARE_EVENT_TABLE()
+};
+
+//-----------------------------------------------------------------------------
+// wxListRenameTimer (internal)
+//-----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxListRenameTimer: public wxTimer
+{
+private:
+    wxListMainWindow   *m_owner;
+
+public:
+    wxListRenameTimer( wxListMainWindow *owner );
+    void Notify();
+};
+
+//-----------------------------------------------------------------------------
+//  wxListTextCtrl (internal)
+//-----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxListTextCtrl: public wxTextCtrl
+{
+private:
+    bool               *m_accept;
+    wxString           *m_res;
+    wxListMainWindow   *m_owner;
+    wxString            m_startValue;
+
+public:
+    wxListTextCtrl() {}
+    wxListTextCtrl( wxWindow *parent, const wxWindowID id,
+                    bool *accept, wxString *res, wxListMainWindow *owner,
+                    const wxString &value = "",
+                    const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize,
+                    int style = 0,
+                    const wxValidator& validator = wxDefaultValidator,
+                    const wxString &name = "listctrltextctrl" );
+    void OnChar( wxKeyEvent &event );
+    void OnKillFocus( wxFocusEvent &event );
+
+private:
+    DECLARE_DYNAMIC_CLASS(wxListTextCtrl);
+    DECLARE_EVENT_TABLE()
+};
+
+//-----------------------------------------------------------------------------
+//  wxListMainWindow (internal)
+//-----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxListMainWindow: public wxScrolledWindow
+{
+public:
+    long                 m_mode;
+    wxList               m_lines;
+    wxList               m_columns;
+    wxListLineData      *m_current;
+    wxListLineData      *m_currentEdit;
+    int                  m_visibleLines;
+    wxBrush             *m_hilightBrush;
+    wxColour            *m_hilightColour;
+    int                  m_xScroll,m_yScroll;
+    bool                 m_dirty;
+    wxImageList         *m_small_image_list;
+    wxImageList         *m_normal_image_list;
+    int                  m_small_spacing;
+    int                  m_normal_spacing;
+    bool                 m_hasFocus;
+    bool                 m_usedKeys;
+    bool                 m_lastOnSame;
+    wxTimer             *m_renameTimer;
+    bool                 m_renameAccept;
+    wxString             m_renameRes;
+    bool                 m_isCreated;
+    int                  m_dragCount;
+    wxPoint              m_dragStart;
+
+    // for double click logic
+    wxListLineData      *m_lineLastClicked,
+                        *m_lineBeforeLastClicked;
+
+public:
+    wxListMainWindow();
+    wxListMainWindow( wxWindow *parent, wxWindowID id,
+      const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize,
+      long style = 0, const wxString &name = "listctrlmainwindow" );
+    ~wxListMainWindow();
+    void RefreshLine( wxListLineData *line );
+    void OnPaint( wxPaintEvent &event );
+    void HilightAll( bool on );
+    void SendNotify( wxListLineData *line, wxEventType command );
+    void FocusLine( wxListLineData *line );
+    void UnfocusLine( wxListLineData *line );
+    void SelectLine( wxListLineData *line );
+    void DeselectLine( wxListLineData *line );
+    void DeleteLine( wxListLineData *line );
+
+    void EditLabel( long item );
+    void Edit( long item ) { EditLabel(item); }         // deprecated
+    void OnRenameTimer();
+    void OnRenameAccept();
+
+    void OnMouse( wxMouseEvent &event );
+    void MoveToFocus();
+    void OnArrowChar( wxListLineData *newCurrent, bool shiftDown );
+    void OnChar( wxKeyEvent &event );
+    void OnKeyDown( wxKeyEvent &event );
+    void OnSetFocus( wxFocusEvent &event );
+    void OnKillFocus( wxFocusEvent &event );
+    void OnSize( wxSizeEvent &event );
+    void OnScroll(wxScrollWinEvent& event) ;
+    
+    void DrawImage( int index, wxDC *dc, int x, int y );
+    void GetImageSize( int index, int &width, int &height );
+    int GetIndexOfLine( const wxListLineData *line );
+    int GetTextLength( wxString &s );  // should be const
+
+    void SetImageList( wxImageList *imageList, int which );
+    void SetItemSpacing( int spacing, bool isSmall = FALSE );
+    int GetItemSpacing( bool isSmall = FALSE );
+    void SetColumn( int col, wxListItem &item );
+    void SetColumnWidth( int col, int width );
+    void GetColumn( int col, wxListItem &item );
+    int GetColumnWidth( int vol );
+    int GetColumnCount();
+    int GetCountPerPage();
+    void SetItem( wxListItem &item );
+    void GetItem( wxListItem &item );
+    void SetItemState( long item, long state, long stateMask );
+    int GetItemState( long item, long stateMask );
+    int GetItemCount();
+    void GetItemRect( long index, wxRect &rect );
+    bool GetItemPosition( long item, wxPoint& pos );
+    int GetSelectedItemCount();
+    void SetMode( long mode );
+    long GetMode() const;
+    void CalculatePositions();
+    void RealizeChanges();
+    long GetNextItem( long item, int geometry, int state );
+    void DeleteItem( long index );
+    void DeleteAllItems();
+    void DeleteColumn( int col );
+    void DeleteEverything();
+    void EnsureVisible( long index );
+    long FindItem( long start, const wxString& str, bool partial = FALSE );
+    long FindItem( long start, long data);
+    long HitTest( int x, int y, int &flags );
+    void InsertItem( wxListItem &item );
+//    void AddItem( wxListItem &item );
+    void InsertColumn( long col, wxListItem &item );
+//    void AddColumn( wxListItem &item );
+    void SortItems( wxListCtrlCompare fn, long data );
+
+private:
+    DECLARE_DYNAMIC_CLASS(wxListMainWindow);
+    DECLARE_EVENT_TABLE()
+};
+
+// ============================================================================
+// implementation
+// ============================================================================
+
 //-----------------------------------------------------------------------------
 //  wxListItemData
 //-----------------------------------------------------------------------------
@@ -290,15 +620,42 @@ void wxListLineData::CalculateSize( wxDC *dc, int spacing )
         case wxLC_ICON:
         {
             m_bound_all.width = m_spacing;
-            m_bound_all.height = m_spacing+13;
             wxNode *node = m_items.First();
             if (node)
             {
                 wxListItemData *item = (wxListItemData*)node->Data();
                 wxString s = item->GetText();
+                if (s.IsEmpty()) s = wxT("H");
                 wxCoord lw,lh;
                 dc->GetTextExtent( s, &lw, &lh );
+                if (lh < 15) lh = 15;
+                lw += 4;
+                lh += 3;
+                
+                m_bound_all.height = m_spacing+lh;
                 if (lw > m_spacing) m_bound_all.width = lw;
+                m_bound_label.width = lw;
+                m_bound_label.height = lh;
+                
+                if (item->HasImage())
+                {
+                    int w = 0;
+                    int h = 0;
+                    m_owner->GetImageSize( item->GetImage(), w, h );
+                    m_bound_icon.width = w + 8;
+                    m_bound_icon.height = h + 8;
+                }
+                
+                if (!item->HasText())
+                {
+                    m_bound_hilight.width = m_bound_icon.width;
+                    m_bound_hilight.height = m_bound_icon.height;
+                }
+                else
+                {
+                    m_bound_hilight.width = m_bound_label.width;
+                    m_bound_hilight.height = m_bound_label.height;
+                }
             }
             break;
         }
@@ -308,24 +665,34 @@ void wxListLineData::CalculateSize( wxDC *dc, int spacing )
             if (node)
             {
                 wxListItemData *item = (wxListItemData*)node->Data();
+                
                 wxString s = item->GetText();
+                if (s.IsEmpty()) s = wxT("H");
                 wxCoord lw,lh;
                 dc->GetTextExtent( s, &lw, &lh );
+                if (lh < 15) lh = 15;
+                lw += 4;
+                lh += 3;
+                m_bound_label.width = lw;
+                m_bound_label.height = lh;
+                
                 m_bound_all.width = lw;
                 m_bound_all.height = lh;
+                
                 if (item->HasImage())
                 {
-#ifdef __WIN16__
                     int w = 0;
                     int h = 0;
-#else
-                    wxCoord w = 0;
-                    wxCoord h = 0;
-#endif
                     m_owner->GetImageSize( item->GetImage(), w, h );
+                    m_bound_icon.width = w;
+                    m_bound_icon.height = h;
+                    
                     m_bound_all.width += 4 + w;
                     if (h > m_bound_all.height) m_bound_all.height = h;
                 }
+                
+                m_bound_hilight.width = m_bound_all.width;
+                m_bound_hilight.height = m_bound_all.height;
             }
             break;
         }
@@ -337,11 +704,14 @@ void wxListLineData::CalculateSize( wxDC *dc, int spacing )
             while (node)
             {
                 wxListItemData *item = (wxListItemData*)node->Data();
-                wxString s;
-                item->GetText( s );
-                if (s.IsNull()) s = "H";
+                wxString s = item->GetText();
+                if (s.IsEmpty()) s = wxT("H");
                 wxCoord lw,lh;
                 dc->GetTextExtent( s, &lw, &lh );
+                if (lh < 15) lh = 15;
+                lw += 4;
+                lh += 3;
+                
                 item->SetSize( item->GetWidth(), lh );
                 m_bound_all.width += lw;
                 m_bound_all.height = lh;
@@ -360,63 +730,38 @@ void wxListLineData::SetPosition( wxDC *dc, int x, int y, int window_width )
     {
         case wxLC_ICON:
         {
-            AssignRect( m_bound_icon, 0, 0, 0, 0 );
-            AssignRect( m_bound_label, 0, 0, 0, 0 );
-            AssignRect( m_bound_hilight, m_bound_all );
             wxNode *node = m_items.First();
             if (node)
             {
                 wxListItemData *item = (wxListItemData*)node->Data();
                 if (item->HasImage())
                 {
-                    wxListItemData *item = (wxListItemData*)node->Data();
-                    int w = 0;
-                    int h = 0;
-                    m_owner->GetImageSize( item->GetImage(), w, h );
-                    m_bound_icon.x = m_bound_all.x + (m_spacing/2) - (w/2);
-                    m_bound_icon.y = m_bound_all.y + m_spacing - h - 5;
-                    m_bound_icon.width = w;
-                    m_bound_icon.height = h;
-                    if (!item->HasText())
-                    {
-                        AssignRect( m_bound_hilight, m_bound_icon );
-                        m_bound_hilight.x -= 5;
-                        m_bound_hilight.y -= 5;
-                        m_bound_hilight.width += 9;
-                        m_bound_hilight.height += 9;
-                    }
+                    m_bound_icon.x = m_bound_all.x + 4 + (m_spacing/2) - (m_bound_icon.width/2);
+                    m_bound_icon.y = m_bound_all.y + 4;
                 }
                 if (item->HasText())
                 {
-                    wxString s;
-                    item->GetText( s );
-                    wxCoord lw,lh;
-                    dc->GetTextExtent( s, &lw, &lh );
                     if (m_bound_all.width > m_spacing)
-                        m_bound_label.x = m_bound_all.x;
+                        m_bound_label.x = m_bound_all.x + 2;
                     else
-                        m_bound_label.x = m_bound_all.x +  (m_spacing/2) - lw/2;
-                    m_bound_label.y = m_bound_all.y + m_bound_all.height - lh;
-                    m_bound_label.width = lw;
-                    m_bound_label.height = lh;
-                    AssignRect( m_bound_hilight, m_bound_label );
-                    m_bound_hilight.x -= 2;
-                    m_bound_hilight.y -= 2;
-                    m_bound_hilight.width += 4;
-                    m_bound_hilight.height += 4;
+                        m_bound_label.x = m_bound_all.x + 2 + (m_spacing/2) - (m_bound_label.width/2);
+                    m_bound_label.y = m_bound_all.y + m_bound_all.height + 2 - m_bound_label.height;
+                    m_bound_hilight.x = m_bound_label.x - 2;
+                    m_bound_hilight.y = m_bound_label.y - 2;
+                }
+                else
+                {
+                    m_bound_hilight.x = m_bound_icon.x - 4;
+                    m_bound_hilight.y = m_bound_icon.y - 4;
                 }
             }
             break;
         }
         case wxLC_LIST:
         {
-            AssignRect( m_bound_label, m_bound_all );
-            m_bound_all.x -= 2;
-            m_bound_all.y -= 2;
-            m_bound_all.width += 4;
-            m_bound_all.height += 3;
-            AssignRect( m_bound_hilight, m_bound_all );
-            AssignRect( m_bound_icon, 0, 0, 0, 0 );
+            m_bound_hilight.x = m_bound_all.x;
+            m_bound_hilight.y = m_bound_all.y;
+            m_bound_label.y = m_bound_all.y + 2;
             wxNode *node = m_items.First();
             if (node)
             {
@@ -425,49 +770,31 @@ void wxListLineData::SetPosition( wxDC *dc, int x, int y, int window_width )
                 {
                     m_bound_icon.x = m_bound_all.x + 2;
                     m_bound_icon.y = m_bound_all.y + 2;
-                    int w;
-                    int h;
-                    m_owner->GetImageSize( item->GetImage(), w, h );
-                    m_bound_icon.width = w;
-                    m_bound_icon.height = h;
-                    m_bound_label.x += 4 + w;
-                    m_bound_label.width -= 4 + w;
+                    m_bound_label.x = m_bound_all.x + 6 + m_bound_icon.width;
+                }
+                else
+                {
+                    m_bound_label.x = m_bound_all.x + 2;
                 }
             }
             break;
         }
         case wxLC_REPORT:
         {
-            wxCoord lw,lh;
-            dc->GetTextExtent( "H", &lw, &lh );
             m_bound_all.x = 0;
-            m_bound_all.y -= 0;
-            m_bound_all.height = lh+3;
             m_bound_all.width = window_width;
             AssignRect( m_bound_hilight, m_bound_all );
-            AssignRect( m_bound_label, m_bound_all );
-            AssignRect( m_bound_icon, 0, 0, 0, 0 );
+            m_bound_label.x = m_bound_all.x + 2;
+            m_bound_label.y = m_bound_all.y + 2;
             wxNode *node = m_items.First();
             if (node)
             {
                 wxListItemData *item = (wxListItemData*)node->Data();
-                wxString s;
-                item->GetText( s );
-                if (s.IsEmpty()) s = wxT("H");
-                wxCoord lw,lh;
-                dc->GetTextExtent( s, &lw, &lh );
-                m_bound_label.width = lw;
-                m_bound_label.height = lh;
                 if (item->HasImage())
                 {
                     m_bound_icon.x = m_bound_all.x + 2;
                     m_bound_icon.y = m_bound_all.y + 2;
-                    int w;
-                    int h;
-                    m_owner->GetImageSize( item->GetImage(), w, h );
-                    m_bound_icon.width = w;
-                    m_bound_icon.height = h;
-                    m_bound_label.x += 4 + w;
+                    m_bound_label.x += 4 + m_bound_icon.width;
                 }
             }
             break;
@@ -618,15 +945,14 @@ void wxListLineData::SetAttributes(wxDC *dc,
 
 void wxListLineData::DoDraw( wxDC *dc, bool hilight, bool paintBG )
 {
-    wxCoord dev_x = dc->LogicalToDeviceX( m_bound_all.x-2 );
-    wxCoord dev_y = dc->LogicalToDeviceY( m_bound_all.y-2 );
-    wxCoord dev_w = dc->LogicalToDeviceXRel( m_bound_all.width+4 );
-    wxCoord dev_h = dc->LogicalToDeviceYRel( m_bound_all.height+4 );
+    int dev_x = 0;
+    int dev_y = 0;
+    m_owner->CalcScrolledPosition( m_bound_all.x, m_bound_all.y, &dev_x, &dev_y );
+    wxCoord dev_w = m_bound_all.width;
+    wxCoord dev_h = m_bound_all.height;
 
     if (!m_owner->IsExposed( dev_x, dev_y, dev_w, dev_h ))
-    {
         return;
-    }
 
     wxWindow *listctrl = m_owner->GetParent();
 
@@ -677,7 +1003,6 @@ void wxListLineData::DoDraw( wxDC *dc, bool hilight, bool paintBG )
         while (node)
         {
             wxListItemData *item = (wxListItemData*)node->Data();
-            dc->SetClippingRegion( item->GetX(), item->GetY(), item->GetWidth()-3, item->GetHeight() );
             int x = item->GetX();
             if (item->HasImage())
             {
@@ -686,9 +1011,10 @@ void wxListLineData::DoDraw( wxDC *dc, bool hilight, bool paintBG )
                 m_owner->GetImageSize( item->GetImage(), x, y );
                 x += item->GetX() + 5;
             }
+            dc->SetClippingRegion( item->GetX(), item->GetY(), item->GetWidth()-3, item->GetHeight() );
             if (item->HasText())
             {
-                dc->DrawText( item->GetText(), x, item->GetY() );
+                dc->DrawText( item->GetText(), x, item->GetY()+1 );
             }
             dc->DestroyClippingRegion();
             node = node->Next();
@@ -952,11 +1278,11 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event )
     m_minX = 0;
     bool hit_border = FALSE;
     int xpos = 0;
-    for (int j = 0; j < m_owner->GetColumnCount()-1; j++)
+    for (int j = 0; j < m_owner->GetColumnCount(); j++)
     {
         xpos += m_owner->GetColumnWidth( j );
         m_column = j;
-        if ((abs(x-xpos) < 3) && (y < 22))
+        if ((abs(x-xpos) < 3) && (y < 22) && (m_column < m_owner->GetColumnCount()-1))
         {
             hit_border = TRUE;
             break;
@@ -1060,24 +1386,33 @@ void wxListTextCtrl::OnChar( wxKeyEvent &event )
     {
         (*m_accept) = TRUE;
         (*m_res) = GetValue();
-        m_owner->SetFocus();
+        
+        if (!wxPendingDelete.Member(this))
+            wxPendingDelete.Append(this);
+
+        if ((*m_accept) && ((*m_res) != m_startValue))
+            m_owner->OnRenameAccept();
+            
         return;
     }
     if (event.m_keyCode == WXK_ESCAPE)
     {
         (*m_accept) = FALSE;
         (*m_res) = "";
-        m_owner->SetFocus();
+        
+        if (!wxPendingDelete.Member(this))
+            wxPendingDelete.Append(this);
+            
         return;
     }
+    
     event.Skip();
 }
 
 void wxListTextCtrl::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
 {
-    if (wxPendingDelete.Member(this)) return;
-
-    wxPendingDelete.Append(this);
+    if (!wxPendingDelete.Member(this))
+        wxPendingDelete.Append(this);
 
     if ((*m_accept) && ((*m_res) != m_startValue))
         m_owner->OnRenameAccept();
@@ -1097,7 +1432,7 @@ BEGIN_EVENT_TABLE(wxListMainWindow,wxScrolledWindow)
   EVT_KEY_DOWN       (wxListMainWindow::OnKeyDown)
   EVT_SET_FOCUS      (wxListMainWindow::OnSetFocus)
   EVT_KILL_FOCUS     (wxListMainWindow::OnKillFocus)
-  EVT_SCROLLWIN                 (wxListMainWindow::OnScroll)
+  EVT_SCROLLWIN      (wxListMainWindow::OnScroll)
 END_EVENT_TABLE()
 
 wxListMainWindow::wxListMainWindow()
@@ -1121,6 +1456,9 @@ wxListMainWindow::wxListMainWindow()
     m_renameTimer = new wxListRenameTimer( this );
     m_isCreated = FALSE;
     m_dragCount = 0;
+
+    m_lineLastClicked =
+    m_lineBeforeLastClicked = (wxListLineData *)NULL;
 }
 
 wxListMainWindow::wxListMainWindow( wxWindow *parent, wxWindowID id,
@@ -1166,7 +1504,7 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent, wxWindowID id,
     m_renameTimer = new wxListRenameTimer( this );
     m_renameAccept = FALSE;
 
-    SetBackgroundColour( *wxWHITE );
+    SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX ) );
 }
 
 wxListMainWindow::~wxListMainWindow()
@@ -1182,22 +1520,16 @@ void wxListMainWindow::RefreshLine( wxListLineData *line )
 {
     if (m_dirty) return;
 
+    if (!line) return;
+    
     int x = 0;
     int y = 0;
     int w = 0;
     int h = 0;
-    if (line)
-    {
-        wxClientDC dc(this);
-        PrepareDC( dc );
-        line->GetExtent( x, y, w, h );
-        wxRect rect(
-          dc.LogicalToDeviceX(x-3),
-          dc.LogicalToDeviceY(y-3),
-          dc.LogicalToDeviceXRel(w+6),
-          dc.LogicalToDeviceXRel(h+6) );
-        Refresh( TRUE, &rect );
-    }
+    line->GetExtent( x, y, w, h );
+    CalcScrolledPosition( x, y, &x, &y );
+    wxRect rect( x, y, w, h );
+    Refresh( TRUE, &rect );
 }
 
 void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
@@ -1420,15 +1752,26 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event )
 
     if (!line) return;
 
+    bool forceClick = FALSE;
     if (event.ButtonDClick())
     {
-        m_usedKeys = FALSE;
-        m_lastOnSame = FALSE;
         m_renameTimer->Stop();
+        m_lastOnSame = FALSE;
 
-        SendNotify( line, wxEVT_COMMAND_LIST_ITEM_ACTIVATED );
+        if ( line == m_lineBeforeLastClicked )
+        {
+            m_usedKeys = FALSE;
+
+            SendNotify( line, wxEVT_COMMAND_LIST_ITEM_ACTIVATED );
 
-       return;
+            return;
+        }
+        else
+        {
+            // the first click was on another item, so don't interpret this as
+            // a double click, but as a simple click instead
+            forceClick = TRUE;
+        }
     }
 
     if (event.LeftUp() && m_lastOnSame)
@@ -1456,8 +1799,11 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event )
         return;
     }
 
-    if (event.LeftDown())
+    if ( event.LeftDown() || forceClick )
     {
+        m_lineBeforeLastClicked = m_lineLastClicked;
+        m_lineLastClicked = line;
+
         m_usedKeys = FALSE;
         wxListLineData *oldCurrent = m_current;
         if (m_mode & wxLC_SINGLE_SEL)
@@ -1529,7 +1875,10 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event )
             UnfocusLine( oldCurrent );
             FocusLine( m_current );
         }
-        m_lastOnSame = (m_current == oldCurrent);
+
+        // forceClick is only set if the previous click was on another item
+        m_lastOnSame = !forceClick && (m_current == oldCurrent);
+
         return;
     }
 }
@@ -1624,6 +1973,7 @@ void wxListMainWindow::OnChar( wxKeyEvent &event )
     if (event.KeyCode() == WXK_TAB)
     {
         wxNavigationKeyEvent nevent;
+        nevent.SetWindowChange( event.ControlDown() );
         nevent.SetDirection( !event.ShiftDown() );
         nevent.SetEventObject( GetParent()->GetParent() );
         nevent.SetCurrentFocus( m_parent );
@@ -1722,8 +2072,19 @@ void wxListMainWindow::OnChar( wxKeyEvent &event )
         }
         case WXK_SPACE:
         {
-            m_current->ReverseHilight();
-            RefreshLine( m_current );
+            if (m_mode & wxLC_SINGLE_SEL)
+            {
+                wxListEvent le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, GetParent()->GetId() );
+                le.SetEventObject( GetParent() );
+                le.m_itemIndex = GetIndexOfLine( m_current );
+                m_current->GetItem( 0, le.m_item );
+                GetParent()->GetEventHandler()->ProcessEvent( le );
+            }
+            else
+            {
+                m_current->ReverseHilight();
+                RefreshLine( m_current );
+            }
             break;
         }
         case WXK_INSERT:
@@ -1793,6 +2154,7 @@ void wxListMainWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
   We don't even allow the wxScrolledWindow::AdjustScrollbars() call
 
 */
+    m_dirty = TRUE;
 }
 
 void wxListMainWindow::DrawImage( int index, wxDC *dc, int x, int y )
@@ -2219,7 +2581,7 @@ void wxListMainWindow::CalculatePositions()
     line->CalculateSize( &dc, iconSpacing );
     int dummy = 0;
     line->GetSize( dummy, lineSpacing );
-    lineSpacing += 4;
+    lineSpacing += 1;
 
     int clientWidth = 0;
     int clientHeight = 0;
@@ -2276,8 +2638,8 @@ void wxListMainWindow::CalculatePositions()
         for (int tries = 0; tries < 2; tries++)
         {
             entireWidth = 0;
-            int x = 5;  // painting is done at x-2
-            int y = 5;  // painting is done at y-2
+            int x = 2;
+            int y = 2;
             int maxWidth = 0;
             m_visibleLines = 0;
             int m_currentVisibleLines = 0;
@@ -2296,7 +2658,7 @@ void wxListMainWindow::CalculatePositions()
                 if (y+lineSpacing-6 >= clientHeight) // -6 for earlier "line breaking"
                 {
                     m_currentVisibleLines = 0;
-                    y = 5;
+                    y = 2;
                     x += maxWidth+6;
                     entireWidth += maxWidth+6;
                     maxWidth = 0;
@@ -2734,7 +3096,7 @@ bool wxListCtrl::Create(wxWindow *parent,
         m_headerWin = (wxListHeaderWindow *) NULL;
     }
 
-    SetBackgroundColour( *wxWHITE );
+    SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX ) );
 
     return ret;
 }
@@ -3253,3 +3615,44 @@ bool wxListCtrl::SetFont( const wxFont &font )
     return TRUE;
 }
 
+#if wxUSE_DRAG_AND_DROP
+
+void wxListCtrl::SetDropTarget( wxDropTarget *dropTarget )
+{
+    m_mainWin->SetDropTarget( dropTarget );
+}
+
+wxDropTarget *wxListCtrl::GetDropTarget() const
+{
+    return m_mainWin->GetDropTarget();
+}
+
+#endif // wxUSE_DRAG_AND_DROP
+
+bool wxListCtrl::SetCursor( const wxCursor &cursor )
+{
+    return m_mainWin ? m_mainWin->wxWindow::SetCursor(cursor) : FALSE;
+}
+
+wxColour wxListCtrl::GetBackgroundColour() const
+{
+    return m_mainWin ? m_mainWin->GetBackgroundColour() : wxColour();
+}
+
+wxColour wxListCtrl::GetForegroundColour() const
+{
+    return m_mainWin ? m_mainWin->GetForegroundColour() : wxColour();
+}
+
+bool wxListCtrl::DoPopupMenu( wxMenu *menu, int x, int y )
+{
+    return m_mainWin->PopupMenu( menu, x, y );
+}
+
+void wxListCtrl::SetFocus()
+{
+    /* The test in window.cpp fails as we are a composite
+       window, so it checks against "this", but not m_mainWin. */
+    if ( FindFocus() != this )
+        m_mainWin->SetFocus();
+}