]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/listctrl.cpp
Fixed bug [ 754596 ] wxUSE_CONSTRAINTS 0 breaks AutoLayout() with sizers
[wxWidgets.git] / src / generic / listctrl.cpp
index bf85914d4cf7cf0f7ff639e4e2163a7b2f65b3bc..dc42f4b08a74566a506a4533f99721ca75a0565d 100644 (file)
@@ -23,7 +23,7 @@
 // headers
 // ----------------------------------------------------------------------------
 
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
     #pragma implementation "listctrl.h"
     #pragma implementation "listctrlbase.h"
 #endif
     IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxGenericListCtrl)
 #endif // HAVE_NATIVE_LISTCTRL/!HAVE_NATIVE_LISTCTRL
 
-#if defined(__WXGTK__)
-    #include <gtk/gtk.h>
-    #include "wx/gtk/win_gtk.h"
-#endif
+#include "wx/selstore.h"
+
+#include "wx/renderer.h"
 
 // ----------------------------------------------------------------------------
 // events
@@ -104,8 +103,8 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT)
 // constants
 // ----------------------------------------------------------------------------
 
-// the height of the header window (FIXME: should depend on its font!)
-static const int HEADER_HEIGHT = 23;
+// // the height of the header window (FIXME: should depend on its font!)
+// static const int HEADER_HEIGHT = 23;
 
 // the scrollbar units
 static const int SCROLL_UNIT_X = 15;
@@ -118,10 +117,17 @@ static const int LINE_SPACING = 0;
 static const int EXTRA_WIDTH = 3;
 static const int EXTRA_HEIGHT = 4;
 
+// margin between the window and the items
+static const int EXTRA_BORDER_X = 2;
+static const int EXTRA_BORDER_Y = 2;
+
 // offset for the header window
 static const int HEADER_OFFSET_X = 1;
 static const int HEADER_OFFSET_Y = 1;
 
+// margin between rows of icons in [small] icon view
+static const int MARGIN_BETWEEN_ROWS = 6;
+
 // when autosizing the columns, add some slack
 static const int AUTOSIZE_COL_MARGIN = 10;
 
@@ -136,83 +142,6 @@ static const int IMAGE_MARGIN_IN_REPORT_MODE = 5;
 // private classes
 // ============================================================================
 
-// ----------------------------------------------------------------------------
-// wxSelectionStore
-// ----------------------------------------------------------------------------
-
-int CMPFUNC_CONV wxSizeTCmpFn(size_t n1, size_t n2) { return n1 - n2; }
-
-WX_DEFINE_SORTED_EXPORTED_ARRAY_LONG(size_t, wxIndexArray);
-
-// this class is used to store the selected items in the virtual list control
-// (but it is not tied to list control and so can be used with other controls
-// such as wxListBox in wxUniv)
-//
-// the idea is to make it really smart later (i.e. store the selections as an
-// array of ranes + individual items) but, as I don't have time to do it now
-// (this would require writing code to merge/break ranges and much more) keep
-// it simple but define a clean interface to it which allows it to be made
-// smarter later
-class WXDLLEXPORT wxSelectionStore
-{
-public:
-    wxSelectionStore() : m_itemsSel(wxSizeTCmpFn) { Init(); }
-
-    // set the total number of items we handle
-    void SetItemCount(size_t count) { m_count = count; }
-
-    // special case of SetItemCount(0)
-    void Clear() { m_itemsSel.Clear(); m_count = 0; m_defaultState = FALSE; }
-
-    // must be called when a new item is inserted/added
-    void OnItemAdd(size_t item) { wxFAIL_MSG( _T("TODO") ); }
-
-    // must be called when an item is deleted
-    void OnItemDelete(size_t item);
-
-    // select one item, use SelectRange() insted if possible!
-    //
-    // returns true if the items selection really changed
-    bool SelectItem(size_t item, bool select = TRUE);
-
-    // select the range of items
-    //
-    // return true and fill the itemsChanged array with the indices of items
-    // which have changed state if "few" of them did, otherwise return false
-    // (meaning that too many items changed state to bother counting them
-    // individually)
-    bool SelectRange(size_t itemFrom, size_t itemTo,
-                     bool select = TRUE,
-                     wxArrayInt *itemsChanged = NULL);
-
-    // return true if the given item is selected
-    bool IsSelected(size_t item) const;
-
-    // return the total number of selected items
-    size_t GetSelectedCount() const
-    {
-        return m_defaultState ? m_count - m_itemsSel.GetCount()
-                              : m_itemsSel.GetCount();
-    }
-
-private:
-    // (re)init
-    void Init() { m_defaultState = FALSE; }
-
-    // the total number of items we handle
-    size_t m_count;
-
-    // the default state: normally, FALSE (i.e. off) but maybe set to TRUE if
-    // there are more selected items than non selected ones - this allows to
-    // handle selection of all items efficiently
-    bool m_defaultState;
-
-    // the array of items whose selection state is different from default
-    wxIndexArray m_itemsSel;
-
-    DECLARE_NO_COPY_CLASS(wxSelectionStore)
-};
-
 //-----------------------------------------------------------------------------
 //  wxListItemData (internal)
 //-----------------------------------------------------------------------------
@@ -333,7 +262,7 @@ WX_DECLARE_LIST(wxListItemData, wxListItemDataList);
 #include "wx/listimpl.cpp"
 WX_DEFINE_LIST(wxListItemDataList);
 
-class WXDLLEXPORT wxListLineData
+class wxListLineData
 {
 public:
     // the list of subitems: only may have more than one item in report mode
@@ -353,6 +282,18 @@ public:
 
         // the part to be highlighted
         wxRect m_rectHighlight;
+
+        // extend all our rects to be centered inside theo ne of given width
+        void ExtendWidth(wxCoord w)
+        {
+            wxASSERT_MSG( m_rectAll.width <= w,
+                            _T("width can only be increased") );
+
+            m_rectAll.width = w;
+            m_rectLabel.x = m_rectAll.x + (w - m_rectLabel.width)/2;
+            m_rectIcon.x = m_rectAll.x + (w - m_rectIcon.width)/2;
+            m_rectHighlight.x = m_rectAll.x + (w - m_rectHighlight.width)/2;
+        }
     } *m_gi;
 
     // is this item selected? [NB: not used in virtual mode]
@@ -364,7 +305,11 @@ public:
 public:
     wxListLineData(wxListMainWindow *owner);
 
-    ~wxListLineData() { delete m_gi; }
+    ~wxListLineData()
+    {
+        WX_CLEAR_LIST(wxListItemDataList, m_items);
+        delete m_gi;
+    }
 
     // are we in report mode?
     inline bool InReportView() const;
@@ -379,7 +324,7 @@ public:
     void CalculateSize( wxDC *dc, int spacing );
 
     // remember the position this line appears at
-    void SetPosition( int x, int y,  int window_width, int spacing );
+    void SetPosition( int x, int y, int spacing );
 
     // wxListCtrl API
 
@@ -480,7 +425,6 @@ public:
 
     virtual ~wxListHeaderWindow();
 
-    void DoDrawRect( wxDC *dc, int x, int y, int w, int h );
     void DrawCurrent();
     void AdjustDC(wxDC& dc);
 
@@ -551,7 +495,7 @@ WX_DECLARE_LIST(wxListHeaderData, wxListHeaderDataList);
 #include "wx/listimpl.cpp"
 WX_DEFINE_LIST(wxListHeaderDataList);
 
-class WXDLLEXPORT wxListMainWindow : public wxScrolledWindow
+class wxListMainWindow : public wxScrolledWindow
 {
 public:
     wxListMainWindow();
@@ -652,6 +596,7 @@ public:
 
     void OnRenameTimer();
     bool OnRenameAccept(size_t itemEdit, const wxString& value);
+    void OnRenameCancelled(size_t itemEdit);
 
     void OnMouse( wxMouseEvent &event );
 
@@ -690,6 +635,7 @@ public:
     void SetItemState( long item, long state, long stateMask );
     int GetItemState( long item, long stateMask ) const;
     void GetItemRect( long index, wxRect &rect ) const;
+    wxRect GetViewRect() const;
     bool GetItemPosition( long item, wxPoint& pos ) const;
     int GetSelectedItemCount() const;
 
@@ -797,8 +743,6 @@ public:
     bool                 m_dirty;
 
     wxColour            *m_highlightColour;
-    int                  m_xScroll,
-                         m_yScroll;
     wxImageListType         *m_small_image_list;
     wxImageListType         *m_normal_image_list;
     int                  m_small_spacing;
@@ -826,9 +770,6 @@ protected:
     // common part of all ctors
     void Init();
 
-    // intiialize m_[xy]Scroll
-    void InitScrolling();
-
     // get the line data for the given index
     wxListLineData *GetLine(size_t n) const
     {
@@ -903,183 +844,6 @@ private:
 // implementation
 // ============================================================================
 
-// ----------------------------------------------------------------------------
-// wxSelectionStore
-// ----------------------------------------------------------------------------
-
-bool wxSelectionStore::IsSelected(size_t item) const
-{
-    bool isSel = m_itemsSel.Index(item) != wxNOT_FOUND;
-
-    // if the default state is to be selected, being in m_itemsSel means that
-    // the item is not selected, so we have to inverse the logic
-    return m_defaultState ? !isSel : isSel;
-}
-
-bool wxSelectionStore::SelectItem(size_t item, bool select)
-{
-    // search for the item ourselves as like this we get the index where to
-    // insert it later if needed, so we do only one search in the array instead
-    // of two (adding item to a sorted array requires a search)
-    size_t index = m_itemsSel.IndexForInsert(item);
-    bool isSel = index < m_itemsSel.GetCount() && m_itemsSel[index] == item;
-
-    if ( select != m_defaultState )
-    {
-        if ( !isSel )
-        {
-            m_itemsSel.AddAt(item, index);
-
-            return TRUE;
-        }
-    }
-    else // reset to default state
-    {
-        if ( isSel )
-        {
-            m_itemsSel.RemoveAt(index);
-            return TRUE;
-        }
-    }
-
-    return FALSE;
-}
-
-bool wxSelectionStore::SelectRange(size_t itemFrom, size_t itemTo,
-                                   bool select,
-                                   wxArrayInt *itemsChanged)
-{
-    // 100 is hardcoded but it shouldn't matter much: the important thing is
-    // that we don't refresh everything when really few (e.g. 1 or 2) items
-    // change state
-    static const size_t MANY_ITEMS = 100;
-
-    wxASSERT_MSG( itemFrom <= itemTo, _T("should be in order") );
-
-    // are we going to have more [un]selected items than the other ones?
-    if ( itemTo - itemFrom > m_count/2 )
-    {
-        if ( select != m_defaultState )
-        {
-            // the default state now becomes the same as 'select'
-            m_defaultState = select;
-
-            // so all the old selections (which had state select) shouldn't be
-            // selected any more, but all the other ones should
-            wxIndexArray selOld = m_itemsSel;
-            m_itemsSel.Empty();
-
-            // TODO: it should be possible to optimize the searches a bit
-            //       knowing the possible range
-
-            size_t item;
-            for ( item = 0; item < itemFrom; item++ )
-            {
-                if ( selOld.Index(item) == wxNOT_FOUND )
-                    m_itemsSel.Add(item);
-            }
-
-            for ( item = itemTo + 1; item < m_count; item++ )
-            {
-                if ( selOld.Index(item) == wxNOT_FOUND )
-                    m_itemsSel.Add(item);
-            }
-
-            // many items (> half) changed state
-            itemsChanged = NULL;
-        }
-        else // select == m_defaultState
-        {
-            // get the inclusive range of items between itemFrom and itemTo
-            size_t count = m_itemsSel.GetCount(),
-                   start = m_itemsSel.IndexForInsert(itemFrom),
-                   end = m_itemsSel.IndexForInsert(itemTo);
-
-            if ( start == count || m_itemsSel[start] < itemFrom )
-            {
-                start++;
-            }
-
-            if ( end == count || m_itemsSel[end] > itemTo )
-            {
-                end--;
-            }
-
-            if ( start <= end )
-            {
-                // delete all of them (from end to avoid changing indices)
-                for ( int i = end; i >= (int)start; i-- )
-                {
-                    if ( itemsChanged )
-                    {
-                        if ( itemsChanged->GetCount() > MANY_ITEMS )
-                        {
-                            // stop counting (see comment below)
-                            itemsChanged = NULL;
-                        }
-                        else
-                        {
-                            itemsChanged->Add(m_itemsSel[i]);
-                        }
-                    }
-
-                    m_itemsSel.RemoveAt(i);
-                }
-            }
-        }
-    }
-    else // "few" items change state
-    {
-        if ( itemsChanged )
-        {
-            itemsChanged->Empty();
-        }
-
-        // just add the items to the selection
-        for ( size_t item = itemFrom; item <= itemTo; item++ )
-        {
-            if ( SelectItem(item, select) && itemsChanged )
-            {
-                itemsChanged->Add(item);
-
-                if ( itemsChanged->GetCount() > MANY_ITEMS )
-                {
-                    // stop counting them, we'll just eat gobs of memory
-                    // for nothing at all - faster to refresh everything in
-                    // this case
-                    itemsChanged = NULL;
-                }
-            }
-        }
-    }
-
-    // we set it to NULL if there are many items changing state
-    return itemsChanged != NULL;
-}
-
-void wxSelectionStore::OnItemDelete(size_t item)
-{
-    size_t count = m_itemsSel.GetCount(),
-           i = m_itemsSel.IndexForInsert(item);
-
-    if ( i < count && m_itemsSel[i] == item )
-    {
-        // this item itself was in m_itemsSel, remove it from there
-        m_itemsSel.RemoveAt(i);
-
-        count--;
-    }
-
-    // and adjust the index of all which follow it
-    while ( i < count )
-    {
-        // all following elements must be greater than the one we deleted
-        wxASSERT_MSG( m_itemsSel[i] > item, _T("logic error") );
-
-        m_itemsSel[i++]--;
-    }
-}
-
 //-----------------------------------------------------------------------------
 //  wxListItemData
 //-----------------------------------------------------------------------------
@@ -1341,7 +1105,6 @@ inline bool wxListLineData::IsVirtual() const
 wxListLineData::wxListLineData( wxListMainWindow *owner )
 {
     m_owner = owner;
-    m_items.DeleteContents( TRUE );
 
     if ( InReportView() )
     {
@@ -1359,101 +1122,98 @@ wxListLineData::wxListLineData( wxListMainWindow *owner )
 
 void wxListLineData::CalculateSize( wxDC *dc, int spacing )
 {
-    wxListItemDataList::Node *node = m_items.GetFirst();
+    wxListItemDataList::compatibility_iterator node = m_items.GetFirst();
     wxCHECK_RET( node, _T("no subitems at all??") );
 
     wxListItemData *item = node->GetData();
 
+    wxString s;
+    wxCoord lw, lh;
+
     switch ( GetMode() )
     {
         case wxLC_ICON:
         case wxLC_SMALL_ICON:
-            {
-                m_gi->m_rectAll.width = spacing;
-
-                wxString s = item->GetText();
-
-                wxCoord lw, lh;
-                if ( s.empty() )
-                {
-                    lh =
-                    m_gi->m_rectLabel.width =
-                    m_gi->m_rectLabel.height = 0;
-                }
-                else // has label
-                {
-                    dc->GetTextExtent( s, &lw, &lh );
-                    if (lh < SCROLL_UNIT_Y)
-                        lh = SCROLL_UNIT_Y;
-                    lw += EXTRA_WIDTH;
-                    lh += EXTRA_HEIGHT;
-
-                    m_gi->m_rectAll.height = spacing + lh;
-                    if (lw > spacing)
-                        m_gi->m_rectAll.width = lw;
-
-                    m_gi->m_rectLabel.width = lw;
-                    m_gi->m_rectLabel.height = lh;
-                }
+            m_gi->m_rectAll.width = spacing;
 
-                if (item->HasImage())
-                {
-                    int w, h;
-                    m_owner->GetImageSize( item->GetImage(), w, h );
-                    m_gi->m_rectIcon.width = w + 8;
-                    m_gi->m_rectIcon.height = h + 8;
-
-                    if ( m_gi->m_rectIcon.width > m_gi->m_rectAll.width )
-                        m_gi->m_rectAll.width = m_gi->m_rectIcon.width;
-                    if ( m_gi->m_rectIcon.height + lh > m_gi->m_rectAll.height - 4 )
-                        m_gi->m_rectAll.height = m_gi->m_rectIcon.height + lh + 4;
-                }
+            s = item->GetText();
 
-                if ( item->HasText() )
-                {
-                    m_gi->m_rectHighlight.width = m_gi->m_rectLabel.width;
-                    m_gi->m_rectHighlight.height = m_gi->m_rectLabel.height;
-                }
-                else // no text, highlight the icon
-                {
-                    m_gi->m_rectHighlight.width = m_gi->m_rectIcon.width;
-                    m_gi->m_rectHighlight.height = m_gi->m_rectIcon.height;
-                }
+            if ( s.empty() )
+            {
+                lh =
+                m_gi->m_rectLabel.width =
+                m_gi->m_rectLabel.height = 0;
             }
-            break;
-
-        case wxLC_LIST:
+            else // has label
             {
-                wxString s = item->GetTextForMeasuring();
-
-                wxCoord lw,lh;
                 dc->GetTextExtent( s, &lw, &lh );
                 if (lh < SCROLL_UNIT_Y)
                     lh = SCROLL_UNIT_Y;
                 lw += EXTRA_WIDTH;
                 lh += EXTRA_HEIGHT;
 
+                m_gi->m_rectAll.height = spacing + lh;
+                if (lw > spacing)
+                    m_gi->m_rectAll.width = lw;
+
                 m_gi->m_rectLabel.width = lw;
                 m_gi->m_rectLabel.height = lh;
+            }
 
-                m_gi->m_rectAll.width = lw;
-                m_gi->m_rectAll.height = lh;
+            if (item->HasImage())
+            {
+                int w, h;
+                m_owner->GetImageSize( item->GetImage(), w, h );
+                m_gi->m_rectIcon.width = w + 8;
+                m_gi->m_rectIcon.height = h + 8;
+
+                if ( m_gi->m_rectIcon.width > m_gi->m_rectAll.width )
+                    m_gi->m_rectAll.width = m_gi->m_rectIcon.width;
+                if ( m_gi->m_rectIcon.height + lh > m_gi->m_rectAll.height - 4 )
+                    m_gi->m_rectAll.height = m_gi->m_rectIcon.height + lh + 4;
+            }
 
-                if (item->HasImage())
-                {
-                    int w, h;
-                    m_owner->GetImageSize( item->GetImage(), w, h );
-                    m_gi->m_rectIcon.width = w;
-                    m_gi->m_rectIcon.height = h;
-
-                    m_gi->m_rectAll.width += 4 + w;
-                    if (h > m_gi->m_rectAll.height)
-                        m_gi->m_rectAll.height = h;
-                }
+            if ( item->HasText() )
+            {
+                m_gi->m_rectHighlight.width = m_gi->m_rectLabel.width;
+                m_gi->m_rectHighlight.height = m_gi->m_rectLabel.height;
+            }
+            else // no text, highlight the icon
+            {
+                m_gi->m_rectHighlight.width = m_gi->m_rectIcon.width;
+                m_gi->m_rectHighlight.height = m_gi->m_rectIcon.height;
+            }
+            break;
+
+        case wxLC_LIST:
+            s = item->GetTextForMeasuring();
+
+            dc->GetTextExtent( s, &lw, &lh );
+            if (lh < SCROLL_UNIT_Y)
+                lh = SCROLL_UNIT_Y;
+            lw += EXTRA_WIDTH;
+            lh += EXTRA_HEIGHT;
+
+            m_gi->m_rectLabel.width = lw;
+            m_gi->m_rectLabel.height = lh;
+
+            m_gi->m_rectAll.width = lw;
+            m_gi->m_rectAll.height = lh;
 
-                m_gi->m_rectHighlight.width = m_gi->m_rectAll.width;
-                m_gi->m_rectHighlight.height = m_gi->m_rectAll.height;
+            if (item->HasImage())
+            {
+                int w, h;
+                m_owner->GetImageSize( item->GetImage(), w, h );
+                m_gi->m_rectIcon.width = w;
+                m_gi->m_rectIcon.height = h;
+
+                m_gi->m_rectAll.width += 4 + w;
+                if (h > m_gi->m_rectAll.height)
+                    m_gi->m_rectAll.height = h;
             }
+
+            m_gi->m_rectHighlight.width = m_gi->m_rectAll.width;
+            m_gi->m_rectHighlight.height = m_gi->m_rectAll.height;
             break;
 
         case wxLC_REPORT:
@@ -1465,11 +1225,9 @@ void wxListLineData::CalculateSize( wxDC *dc, int spacing )
     }
 }
 
-void wxListLineData::SetPosition( int x, int y,
-                                  int window_width,
-                                  int spacing )
+void wxListLineData::SetPosition( int x, int y, int spacing )
 {
-    wxListItemDataList::Node *node = m_items.GetFirst();
+    wxListItemDataList::compatibility_iterator node = m_items.GetFirst();
     wxCHECK_RET( node, _T("no subitems at all??") );
 
     wxListItemData *item = node->GetData();
@@ -1542,7 +1300,7 @@ void wxListLineData::InitItems( int num )
 
 void wxListLineData::SetItem( int index, const wxListItem &info )
 {
-    wxListItemDataList::Node *node = m_items.Item( index );
+    wxListItemDataList::compatibility_iterator node = m_items.Item( index );
     wxCHECK_RET( node, _T("invalid column index in SetItem") );
 
     wxListItemData *item = node->GetData();
@@ -1551,7 +1309,7 @@ void wxListLineData::SetItem( int index, const wxListItem &info )
 
 void wxListLineData::GetItem( int index, wxListItem &info )
 {
-    wxListItemDataList::Node *node = m_items.Item( index );
+    wxListItemDataList::compatibility_iterator node = m_items.Item( index );
     if (node)
     {
         wxListItemData *item = node->GetData();
@@ -1563,7 +1321,7 @@ wxString wxListLineData::GetText(int index) const
 {
     wxString s;
 
-    wxListItemDataList::Node *node = m_items.Item( index );
+    wxListItemDataList::compatibility_iterator node = m_items.Item( index );
     if (node)
     {
         wxListItemData *item = node->GetData();
@@ -1575,7 +1333,7 @@ wxString wxListLineData::GetText(int index) const
 
 void wxListLineData::SetText( int index, const wxString s )
 {
-    wxListItemDataList::Node *node = m_items.Item( index );
+    wxListItemDataList::compatibility_iterator node = m_items.Item( index );
     if (node)
     {
         wxListItemData *item = node->GetData();
@@ -1585,7 +1343,7 @@ void wxListLineData::SetText( int index, const wxString s )
 
 void wxListLineData::SetImage( int index, int image )
 {
-    wxListItemDataList::Node *node = m_items.Item( index );
+    wxListItemDataList::compatibility_iterator node = m_items.Item( index );
     wxCHECK_RET( node, _T("invalid column index in SetImage()") );
 
     wxListItemData *item = node->GetData();
@@ -1594,7 +1352,7 @@ void wxListLineData::SetImage( int index, int image )
 
 int wxListLineData::GetImage( int index ) const
 {
-    wxListItemDataList::Node *node = m_items.Item( index );
+    wxListItemDataList::compatibility_iterator node = m_items.Item( index );
     wxCHECK_MSG( node, -1, _T("invalid column index in GetImage()") );
 
     wxListItemData *item = node->GetData();
@@ -1603,7 +1361,7 @@ int wxListLineData::GetImage( int index ) const
 
 wxListItemAttr *wxListLineData::GetAttr() const
 {
-    wxListItemDataList::Node *node = m_items.GetFirst();
+    wxListItemDataList::compatibility_iterator node = m_items.GetFirst();
     wxCHECK_MSG( node, NULL, _T("invalid column index in GetAttr()") );
 
     wxListItemData *item = node->GetData();
@@ -1612,7 +1370,7 @@ wxListItemAttr *wxListLineData::GetAttr() const
 
 void wxListLineData::SetAttr(wxListItemAttr *attr)
 {
-    wxListItemDataList::Node *node = m_items.GetFirst();
+    wxListItemDataList::compatibility_iterator node = m_items.GetFirst();
     wxCHECK_RET( node, _T("invalid column index in SetAttr()") );
 
     wxListItemData *item = node->GetData();
@@ -1685,7 +1443,7 @@ bool wxListLineData::SetAttributes(wxDC *dc,
 
 void wxListLineData::Draw( wxDC *dc )
 {
-    wxListItemDataList::Node *node = m_items.GetFirst();
+    wxListItemDataList::compatibility_iterator node = m_items.GetFirst();
     wxCHECK_RET( node, _T("no subitems at all??") );
 
     bool highlighted = IsHighlighted();
@@ -1697,20 +1455,31 @@ void wxListLineData::Draw( wxDC *dc )
         dc->DrawRectangle( m_gi->m_rectHighlight );
     }
 
+    // just for debugging to better see where the items are
+#if 0
+    dc->SetPen(*wxRED_PEN);
+    dc->SetBrush(*wxTRANSPARENT_BRUSH);
+    dc->DrawRectangle( m_gi->m_rectAll );
+    dc->SetPen(*wxGREEN_PEN);
+    dc->DrawRectangle( m_gi->m_rectIcon );
+#endif // 0
+
     wxListItemData *item = node->GetData();
     if (item->HasImage())
     {
-        wxRect rectIcon = m_gi->m_rectIcon;
-        m_owner->DrawImage( item->GetImage(), dc,
-                            rectIcon.x, rectIcon.y );
+        // centre the image inside our rectangle, this looks nicer when items
+        // ae aligned in a row
+        const wxRect& rectIcon = m_gi->m_rectIcon;
+
+        m_owner->DrawImage(item->GetImage(), dc, rectIcon.x, rectIcon.y);
     }
 
     if (item->HasText())
     {
-        wxRect rectLabel = m_gi->m_rectLabel;
+        const wxRect& rectLabel = m_gi->m_rectLabel;
 
         wxDCClipper clipper(*dc, rectLabel);
-        dc->DrawText( item->GetText(), rectLabel.x, rectLabel.y );
+        dc->DrawText(item->GetText(), rectLabel.x, rectLabel.y);
     }
 }
 
@@ -1732,7 +1501,7 @@ void wxListLineData::DrawInReportMode( wxDC *dc,
             y = rect.y + (LINE_SPACING + EXTRA_HEIGHT) / 2;
 
     size_t col = 0;
-    for ( wxListItemDataList::Node *node = m_items.GetFirst();
+    for ( wxListItemDataList::compatibility_iterator node = m_items.GetFirst();
           node;
           node = node->GetNext(), col++ )
     {
@@ -1905,66 +1674,6 @@ wxListHeaderWindow::~wxListHeaderWindow()
 #include "wx/univ/theme.h"
 #endif
 
-void wxListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h )
-{
-#if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
-    GtkStateType state = m_parent->IsEnabled() ? GTK_STATE_NORMAL
-                                               : GTK_STATE_INSENSITIVE;
-
-    x = dc->XLOG2DEV( x );
-
-    gtk_paint_box (m_wxwindow->style, GTK_PIZZA(m_wxwindow)->bin_window,
-                   state, GTK_SHADOW_OUT,
-                   (GdkRectangle*) NULL, m_wxwindow,
-                   (char *)"button", // const_cast
-                   x-1, y-1, w+2, h+2);
-#elif defined(__WXUNIVERSAL__)
-    wxTheme *theme = wxTheme::Get();
-    wxRenderer *renderer = theme->GetRenderer();
-    renderer->DrawBorder( *dc, wxBORDER_RAISED, wxRect(x,y,w,h), 0 );
-#elif defined(__WXMAC__)
-    const int m_corner = 1;
-
-    dc->SetBrush( *wxTRANSPARENT_BRUSH );
-
-    dc->SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNSHADOW ) , 1 , wxSOLID ) );
-    dc->DrawLine( x+w-m_corner+1, y, x+w, y+h );  // right (outer)
-    dc->DrawRectangle( x, y+h, w+1, 1 );          // bottom (outer)
-
-    wxPen pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID );
-
-    dc->SetPen( pen );
-    dc->DrawLine( x+w-m_corner, y, x+w-1, y+h );  // right (inner)
-    dc->DrawRectangle( x+1, y+h-1, w-2, 1 );      // bottom (inner)
-
-    dc->SetPen( *wxWHITE_PEN );
-    dc->DrawRectangle( x, y, w-m_corner+1, 1 );   // top (outer)
-    dc->DrawRectangle( x, y, 1, h );              // left (outer)
-    dc->DrawLine( x, y+h-1, x+1, y+h-1 );
-    dc->DrawLine( x+w-1, y, x+w-1, y+1 );
-#else // !GTK, !Mac
-    const int m_corner = 1;
-
-    dc->SetBrush( *wxTRANSPARENT_BRUSH );
-
-    dc->SetPen( *wxBLACK_PEN );
-    dc->DrawLine( x+w-m_corner+1, y, x+w, y+h );  // right (outer)
-    dc->DrawRectangle( x, y+h, w+1, 1 );          // bottom (outer)
-
-    wxPen pen( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID );
-
-    dc->SetPen( pen );
-    dc->DrawLine( x+w-m_corner, y, x+w-1, y+h );  // right (inner)
-    dc->DrawRectangle( x+1, y+h-1, w-2, 1 );      // bottom (inner)
-
-    dc->SetPen( *wxWHITE_PEN );
-    dc->DrawRectangle( x, y, w-m_corner+1, 1 );   // top (outer)
-    dc->DrawRectangle( x, y, 1, h );              // left (outer)
-    dc->DrawLine( x, y+h-1, x+1, y+h-1 );
-    dc->DrawLine( x+w-1, y, x+w-1, y+1 );
-#endif
-}
-
 // shift the DC origin to match the position of the main window horz
 // scrollbar: this allows us to always use logical coords
 void wxListHeaderWindow::AdjustDC(wxDC& dc)
@@ -1981,11 +1690,7 @@ void wxListHeaderWindow::AdjustDC(wxDC& dc)
 
 void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
 {
-#if defined(__WXGTK__)
-    wxClientDC dc( this );
-#else
     wxPaintDC dc( this );
-#endif
 
     PrepareDC( dc );
     AdjustDC( dc );
@@ -2020,9 +1725,14 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
         // inside the column rect
         int cw = wCol - 2;
 
-        dc.SetPen( *wxWHITE_PEN );
-
-        DoDrawRect( &dc, x, HEADER_OFFSET_Y, cw, h-2 );
+        wxRendererNative::Get().DrawHeaderButton
+                                (
+                                    this,
+                                    dc,
+                                    wxRect(x, HEADER_OFFSET_Y, cw, h - 2),
+                                    m_parent->IsEnabled() ? 0
+                                                          : wxCONTROL_DISABLED
+                                );
 
         // see if we have enough space for the column label
 
@@ -2357,6 +2067,7 @@ void wxListTextCtrl::OnChar( wxKeyEvent &event )
 
         case WXK_ESCAPE:
             Finish();
+            m_owner->OnRenameCancelled( m_itemEdited );
             break;
 
         default:
@@ -2391,9 +2102,11 @@ void wxListTextCtrl::OnKillFocus( wxFocusEvent &event )
 {
     if ( !m_finished )
     {
-        (void)AcceptChanges();
-
+        // We must finish regardless of success, otherwise we'll get focus problems
         Finish();
+
+        if ( !AcceptChanges() )
+            m_owner->OnRenameCancelled( m_itemEdited );
     }
 
     event.Skip();
@@ -2417,7 +2130,6 @@ END_EVENT_TABLE()
 
 void wxListMainWindow::Init()
 {
-    m_columns.DeleteContents( TRUE );
     m_dirty = TRUE;
     m_countVirt = 0;
     m_lineFrom =
@@ -2447,29 +2159,12 @@ void wxListMainWindow::Init()
     m_freezeCount = 0;
 }
 
-void wxListMainWindow::InitScrolling()
-{
-    if ( HasFlag(wxLC_REPORT) )
-    {
-        m_xScroll = SCROLL_UNIT_X;
-        m_yScroll = SCROLL_UNIT_Y;
-    }
-    else
-    {
-        m_xScroll = SCROLL_UNIT_Y;
-        m_yScroll = 0;
-    }
-}
-
 wxListMainWindow::wxListMainWindow()
 {
     Init();
 
     m_highlightBrush =
     m_highlightUnfocusedBrush = (wxBrush *) NULL;
-
-    m_xScroll =
-    m_yScroll = 0;
 }
 
 wxListMainWindow::wxListMainWindow( wxWindow *parent,
@@ -2504,8 +2199,7 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent,
     wxSize sz = size;
     sz.y = 25;
 
-    InitScrolling();
-    SetScrollbars( m_xScroll, m_yScroll, 0, 0, 0, 0 );
+    SetScrollbars( SCROLL_UNIT_X, SCROLL_UNIT_Y, 0, 0, 0, 0 );
 
     SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX ) );
 }
@@ -2513,6 +2207,7 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent,
 wxListMainWindow::~wxListMainWindow()
 {
     DoDeleteAllItems();
+    WX_CLEAR_LIST(wxListHeaderDataList, m_columns);
 
     delete m_highlightBrush;
     delete m_highlightUnfocusedBrush;
@@ -3139,6 +2834,41 @@ bool wxListMainWindow::OnRenameAccept(size_t itemEdit, const wxString& value)
                 le.IsAllowed();
 }
 
+#ifdef __VMS__ // Ignore unreacheable code
+# pragma message disable initnotreach
+#endif
+
+void wxListMainWindow::OnRenameCancelled(size_t WXUNUSED(itemEdit))
+{
+    // wxMSW seems not to notify the program about
+    // cancelled label edits.
+    return;
+
+  #if 0
+    // above unconditional return cause warning about not reachable code
+
+    // let owner know that the edit was cancelled
+    wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetParent()->GetId() );
+
+    // These only exist for wxTreeCtrl, which should probably be changed
+    // le.m_editCancelled = TRUE;
+    // le.m_label = wxEmptyString;
+
+    le.SetEventObject( GetParent() );
+    le.m_itemIndex = itemEdit;
+
+    wxListLineData *data = GetLine(itemEdit);
+    wxCHECK_RET( data, _T("invalid index in OnRenameCancelled()") );
+
+    data->GetItem( 0, le.m_item );
+
+    GetEventHandler()->ProcessEvent( le );
+  #endif
+}
+#ifdef __VMS__
+# pragma message enable initnotreach
+#endif
+
 void wxListMainWindow::OnMouse( wxMouseEvent &event )
 {
     event.SetEventObject( GetParent() );
@@ -3324,8 +3054,8 @@ void wxListMainWindow::MoveToItem(size_t item)
     int client_w, client_h;
     GetClientSize( &client_w, &client_h );
 
-    int view_x = m_xScroll*GetScrollPos( wxHORIZONTAL );
-    int view_y = m_yScroll*GetScrollPos( wxVERTICAL );
+    int view_x = SCROLL_UNIT_X*GetScrollPos( wxHORIZONTAL );
+    int view_y = SCROLL_UNIT_Y*GetScrollPos( wxVERTICAL );
 
     if ( HasFlag(wxLC_REPORT) )
     {
@@ -3334,16 +3064,16 @@ void wxListMainWindow::MoveToItem(size_t item)
         ResetVisibleLinesRange();
 
         if (rect.y < view_y )
-            Scroll( -1, rect.y/m_yScroll );
+            Scroll( -1, rect.y/SCROLL_UNIT_Y );
         if (rect.y+rect.height+5 > view_y+client_h)
-            Scroll( -1, (rect.y+rect.height-client_h+SCROLL_UNIT_Y)/m_yScroll );
+            Scroll( -1, (rect.y+rect.height-client_h+SCROLL_UNIT_Y)/SCROLL_UNIT_Y );
     }
     else // !report
     {
         if (rect.x-view_x < 5)
-            Scroll( (rect.x-5)/m_xScroll, -1 );
+            Scroll( (rect.x-5)/SCROLL_UNIT_X, -1 );
         if (rect.x+rect.width-5 > view_x+client_w)
-            Scroll( (rect.x+rect.width-client_w+SCROLL_UNIT_X)/m_xScroll, -1 );
+            Scroll( (rect.x+rect.width-client_w+SCROLL_UNIT_X)/SCROLL_UNIT_X, -1 );
     }
 }
 
@@ -3730,7 +3460,7 @@ int wxListMainWindow::GetItemSpacing( bool isSmall )
 
 void wxListMainWindow::SetColumn( int col, wxListItem &item )
 {
-    wxListHeaderDataList::Node *node = m_columns.Item( col );
+    wxListHeaderDataList::compatibility_iterator node = m_columns.Item( col );
 
     wxCHECK_RET( node, _T("invalid column index in SetColumn") );
 
@@ -3763,7 +3493,7 @@ void wxListMainWindow::SetColumnWidth( int col, int width )
     if ( headerWin )
         headerWin->m_dirty = TRUE;
 
-    wxListHeaderDataList::Node *node = m_columns.Item( col );
+    wxListHeaderDataList::compatibility_iterator node = m_columns.Item( col );
     wxCHECK_RET( node, _T("no column?") );
 
     wxListHeaderData *column = node->GetData();
@@ -3791,7 +3521,7 @@ void wxListMainWindow::SetColumnWidth( int col, int width )
             for ( size_t i = 0; i < count; i++ )
             {
                 wxListLineData *line = GetLine(i);
-                wxListItemDataList::Node *n = line->m_items.Item( col );
+                wxListItemDataList::compatibility_iterator n = line->m_items.Item( col );
 
                 wxCHECK_RET( n, _T("no subitem?") );
 
@@ -3844,7 +3574,7 @@ int wxListMainWindow::GetHeaderWidth() const
 
 void wxListMainWindow::GetColumn( int col, wxListItem &item ) const
 {
-    wxListHeaderDataList::Node *node = m_columns.Item( col );
+    wxListHeaderDataList::compatibility_iterator node = m_columns.Item( col );
     wxCHECK_RET( node, _T("invalid column index in GetColumn") );
 
     wxListHeaderData *column = node->GetData();
@@ -3853,7 +3583,7 @@ void wxListMainWindow::GetColumn( int col, wxListItem &item ) const
 
 int wxListMainWindow::GetColumnWidth( int col ) const
 {
-    wxListHeaderDataList::Node *node = m_columns.Item( col );
+    wxListHeaderDataList::compatibility_iterator node = m_columns.Item( col );
     wxCHECK_MSG( node, 0, _T("invalid column index") );
 
     wxListHeaderData *column = node->GetData();
@@ -4050,11 +3780,58 @@ int wxListMainWindow::GetSelectedItemCount() const
 // item position/size
 // ----------------------------------------------------------------------------
 
+wxRect wxListMainWindow::GetViewRect() const
+{
+    wxASSERT_MSG( !HasFlag(wxLC_REPORT | wxLC_LIST),
+                    _T("wxListCtrl::GetViewRect() only works in icon mode") );
+
+    // we need to find the longest/tallest label
+    wxCoord xMax = 0,
+            yMax = 0;
+    const int count = GetItemCount();
+    if ( count )
+    {
+        for ( int i = 0; i < count; i++ )
+        {
+            wxRect r;
+            GetItemRect(i, r);
+
+            wxCoord x = r.GetRight(),
+                    y = r.GetBottom();
+
+            if ( x > xMax )
+                xMax = x;
+            if ( y > yMax )
+                yMax = y;
+        }
+    }
+
+    // some fudge needed to make it look prettier
+    xMax += 2*EXTRA_BORDER_X;
+    yMax += 2*EXTRA_BORDER_Y;
+
+    // account for the scrollbars if necessary
+    const wxSize sizeAll = GetClientSize();
+    if ( xMax > sizeAll.x )
+        yMax += wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y);
+    if ( yMax > sizeAll.y )
+        xMax += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
+
+    return wxRect(0, 0, xMax, yMax);
+}
+
 void wxListMainWindow::GetItemRect( long index, wxRect &rect ) const
 {
     wxCHECK_RET( index >= 0 && (size_t)index < GetItemCount(),
                  _T("invalid index in GetItemRect") );
 
+    // ensure that we're laid out, otherwise we could return nonsense
+    if ( m_dirty )
+    {
+        wxConstCast(this, wxListMainWindow)->
+            RecalculatePositions(TRUE /* no refresh */);
+    }
+
     rect = GetLineRect((size_t)index);
 
     CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y);
@@ -4080,6 +3857,8 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
     wxClientDC dc( this );
     dc.SetFont( GetFont() );
 
+    const size_t count = GetItemCount();
+
     int iconSpacing;
     if ( HasFlag(wxLC_ICON) )
         iconSpacing = m_normal_spacing;
@@ -4110,104 +3889,170 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
 
     if ( HasFlag(wxLC_REPORT) )
     {
-        // all lines have the same height
+        // all lines have the same height and we scroll one line per step
         int lineHeight = GetLineHeight();
 
-        // scroll one line per step
-        m_yScroll = lineHeight;
-
-        size_t lineCount = GetItemCount();
-        int entireHeight = lineCount*lineHeight + LINE_SPACING;
+        int entireHeight = count*lineHeight + LINE_SPACING;
 
         m_linesPerPage = clientHeight / lineHeight;
 
         ResetVisibleLinesRange();
 
-        SetScrollbars( m_xScroll, m_yScroll,
-                       GetHeaderWidth() / m_xScroll,
-                       (entireHeight + m_yScroll - 1)/m_yScroll,
+        SetScrollbars( SCROLL_UNIT_X, lineHeight,
+                       GetHeaderWidth() / SCROLL_UNIT_X,
+                       (entireHeight + lineHeight - 1) / lineHeight,
                        GetScrollPos(wxHORIZONTAL),
                        GetScrollPos(wxVERTICAL),
                        TRUE );
     }
     else // !report
     {
-        // at first we try without any scrollbar. if the items don't
-        // fit into the window, we recalculate after subtracting an
-        // approximated 15 pt for the horizontal scrollbar
-
-        int entireWidth = 0;
-
-        for (int tries = 0; tries < 2; tries++)
+        // we have 3 different layout strategies: either layout all items
+        // horizontally/vertically (wxLC_ALIGN_XXX styles explicitly given) or
+        // to arrange them in top to bottom, left to right (don't ask me why
+        // not the other way round...) order
+        if ( HasFlag(wxLC_ALIGN_LEFT | wxLC_ALIGN_TOP) )
         {
-            // We start with 4 for the border around all items
-            entireWidth = 4;
+            int x = EXTRA_BORDER_X;
+            int y = EXTRA_BORDER_Y;
 
-            if (tries == 1)
-            {
-                // Now we have decided that the items do not fit into the
-                // client area. Unfortunately, wxWindows sometimes thinks
-                // that it does fit and therefore NO horizontal scrollbar
-                // is inserted. This looks ugly, so we fudge here and make
-                // the calculated width bigger than was actually has been
-                // calculated. This ensures that wxScrolledWindows puts
-                // a scrollbar at the bottom of its client area.
-                entireWidth += SCROLL_UNIT_X;
-            }
+            wxCoord widthMax = 0;
 
-            // Start at 2,2 so the text does not touch the border
-            int x = 2;
-            int y = 2;
-            int maxWidth = 0;
-            m_linesPerPage = 0;
-            int currentlyVisibleLines = 0;
-
-            size_t count = GetItemCount();
-            for (size_t i = 0; i < count; i++)
+            size_t i;
+            for ( i = 0; i < count; i++ )
             {
-                currentlyVisibleLines++;
                 wxListLineData *line = GetLine(i);
                 line->CalculateSize( &dc, iconSpacing );
-                line->SetPosition( x, y, clientWidth, iconSpacing );  // Why clientWidth? (FIXME)
+                line->SetPosition( x, y, iconSpacing );
 
                 wxSize sizeLine = GetLineSize(i);
 
-                if ( maxWidth < sizeLine.x )
-                    maxWidth = sizeLine.x;
+                if ( HasFlag(wxLC_ALIGN_TOP) )
+                {
+                    if ( sizeLine.x > widthMax )
+                        widthMax = sizeLine.x;
 
-                y += sizeLine.y;
-                if (currentlyVisibleLines > m_linesPerPage)
-                    m_linesPerPage = currentlyVisibleLines;
+                    y += sizeLine.y;
+                }
+                else // wxLC_ALIGN_LEFT
+                {
+                    x += sizeLine.x + MARGIN_BETWEEN_ROWS;
+                }
+            }
 
-                // Assume that the size of the next one is the same... (FIXME)
-                if ( y + sizeLine.y >= clientHeight )
+            if ( HasFlag(wxLC_ALIGN_TOP) )
+            {
+                // traverse the items again and tweak their sizes so that they are
+                // all the same in a row
+                for ( i = 0; i < count; i++ )
                 {
-                    currentlyVisibleLines = 0;
-                    y = 2;
-                    x += maxWidth+6;
-                    entireWidth += maxWidth+6;
-                    maxWidth = 0;
+                    wxListLineData *line = GetLine(i);
+                    line->m_gi->ExtendWidth(widthMax);
                 }
+            }
+
+
+            SetScrollbars
+            (
+                SCROLL_UNIT_X,
+                SCROLL_UNIT_Y,
+                (x + SCROLL_UNIT_X) / SCROLL_UNIT_X,
+                (y + SCROLL_UNIT_Y) / SCROLL_UNIT_Y,
+                GetScrollPos( wxHORIZONTAL ),
+                GetScrollPos( wxVERTICAL ),
+                TRUE
+            );
+        }
+        else // "flowed" arrangement, the most complicated case
+        {
+            // at first we try without any scrollbars, if the items don't fit into
+            // the window, we recalculate after subtracting the space taken by the
+            // scrollbar
 
-                // We have reached the last item.
-                if ( i == count - 1 )
-                    entireWidth += maxWidth;
+            int entireWidth = 0;
+            #if 0
+            // entireHeight is not used so no need to define it
+            int entireHeight = 0;
+            #endif
 
-                if ( (tries == 0) && (entireWidth+SCROLL_UNIT_X > clientWidth) )
+            for (int tries = 0; tries < 2; tries++)
+            {
+                entireWidth = 2*EXTRA_BORDER_X;
+                #if 0
+                // entireHeight is not used so no need to define it
+                entireHeight = 2*EXTRA_BORDER_Y;
+                #endif
+
+                if (tries == 1)
                 {
-                    clientHeight -= 15; // We guess the scrollbar height. (FIXME)
-                    m_linesPerPage = 0;
-                    currentlyVisibleLines = 0;
-                    break;
+                    // Now we have decided that the items do not fit into the
+                    // client area, so we need a scrollbar
+                    entireWidth += SCROLL_UNIT_X;
                 }
 
-                if ( i == count - 1 )
-                    tries = 1;  // Everything fits, no second try required.
+                int x = EXTRA_BORDER_X;
+                int y = EXTRA_BORDER_Y;
+                int maxWidthInThisRow = 0;
+
+                m_linesPerPage = 0;
+                int currentlyVisibleLines = 0;
+
+                for (size_t i = 0; i < count; i++)
+                {
+                    currentlyVisibleLines++;
+                    wxListLineData *line = GetLine(i);
+                    line->CalculateSize( &dc, iconSpacing );
+                    line->SetPosition( x, y, iconSpacing );
+
+                    wxSize sizeLine = GetLineSize(i);
+
+                    if ( maxWidthInThisRow < sizeLine.x )
+                        maxWidthInThisRow = sizeLine.x;
+
+                    y += sizeLine.y;
+                    if (currentlyVisibleLines > m_linesPerPage)
+                        m_linesPerPage = currentlyVisibleLines;
+
+                    if ( y + sizeLine.y >= clientHeight )
+                    {
+                        currentlyVisibleLines = 0;
+                        y = EXTRA_BORDER_Y;
+                        maxWidthInThisRow += MARGIN_BETWEEN_ROWS;
+                        x += maxWidthInThisRow;
+                        entireWidth += maxWidthInThisRow;
+                        maxWidthInThisRow = 0;
+                    }
+
+                    // We have reached the last item.
+                    if ( i == count - 1 )
+                        entireWidth += maxWidthInThisRow;
+
+                    if ( (tries == 0) &&
+                            (entireWidth + SCROLL_UNIT_X > clientWidth) )
+                    {
+                        clientHeight -= wxSystemSettings::
+                                            GetMetric(wxSYS_HSCROLL_Y);
+                        m_linesPerPage = 0;
+                        currentlyVisibleLines = 0;
+                        break;
+                    }
+
+                    if ( i == count - 1 )
+                        tries = 1;  // Everything fits, no second try required.
+                }
             }
-        }
 
-        int scroll_pos = GetScrollPos( wxHORIZONTAL );
-        SetScrollbars( m_xScroll, m_yScroll, (entireWidth+SCROLL_UNIT_X) / m_xScroll, 0, scroll_pos, 0, TRUE );
+            SetScrollbars
+            (
+                SCROLL_UNIT_X,
+                SCROLL_UNIT_Y,
+                (entireWidth + SCROLL_UNIT_X) / SCROLL_UNIT_X,
+                0,
+                GetScrollPos( wxHORIZONTAL ),
+                0,
+                TRUE
+            );
+        }
     }
 
     if ( !noRefresh )
@@ -4330,12 +4175,25 @@ void wxListMainWindow::DeleteItem( long lindex )
 
 void wxListMainWindow::DeleteColumn( int col )
 {
-    wxListHeaderDataList::Node *node = m_columns.Item( col );
+    wxListHeaderDataList::compatibility_iterator node = m_columns.Item( col );
 
     wxCHECK_RET( node, wxT("invalid column index in DeleteColumn()") );
 
     m_dirty = TRUE;
-    m_columns.DeleteNode( node );
+    delete node->GetData();
+    m_columns.Erase( node );
+
+    if ( !IsVirtual() )
+    {
+        // update all the items
+        for ( size_t i = 0; i < m_lines.GetCount(); i++ )
+        {
+            wxListLineData * const line = GetLine(i);
+            wxListItemDataList::compatibility_iterator n = line->m_items.Item( col );
+            delete n->GetData();
+            line->m_items.Erase(n);
+        }
+    }
 
     // invalidate it as it has to be recalculated
     m_headerWidth = 0;
@@ -4384,7 +4242,7 @@ void wxListMainWindow::DeleteAllItems()
 
 void wxListMainWindow::DeleteEverything()
 {
-    m_columns.Clear();
+    WX_CLEAR_LIST(wxListHeaderDataList, m_columns);
 
     DeleteAllItems();
 }
@@ -4492,18 +4350,39 @@ void wxListMainWindow::InsertItem( wxListItem &item )
 
     m_dirty = TRUE;
 
+    #if 0
+    // this is unused variable
     int mode = 0;
+    #endif
     if ( HasFlag(wxLC_REPORT) )
     {
+        #if 0
+        // this is unused variable
         mode = wxLC_REPORT;
+        #endif
         ResetVisibleLinesRange();
     }
     else if ( HasFlag(wxLC_LIST) )
+        #if 0
+        // this is unused variable
         mode = wxLC_LIST;
+        #else
+        {}
+        #endif
     else if ( HasFlag(wxLC_ICON) )
+        #if 0
+        // this is unused variable
         mode = wxLC_ICON;
+        #else
+        {}
+        #endif
     else if ( HasFlag(wxLC_SMALL_ICON) )
+        #if 0
+        // this is unused variable
         mode = wxLC_ICON;  // no typo
+        #else
+        {}
+        #endif
     else
     {
         wxFAIL_MSG( _T("unknown mode") );
@@ -4516,6 +4395,17 @@ void wxListMainWindow::InsertItem( wxListItem &item )
     m_lines.Insert( line, id );
 
     m_dirty = TRUE;
+
+    // If an item is selected at or below the point of insertion, we need to
+    // increment the member variables because the current row's index has gone
+    // up by one
+    if ( HasCurrent() && m_current >= id )
+    {
+        m_current++;
+    }
+
+    SendNotify(id, wxEVT_COMMAND_LIST_INSERT_ITEM);
+
     RefreshLines(id, GetItemCount() - 1);
 }
 
@@ -4526,10 +4416,12 @@ void wxListMainWindow::InsertColumn( long col, wxListItem &item )
     {
         if (item.m_width == wxLIST_AUTOSIZE_USEHEADER)
             item.m_width = GetTextLength( item.m_text );
+
         wxListHeaderData *column = new wxListHeaderData( item );
-        if ((col >= 0) && (col < (int)m_columns.GetCount()))
+        bool insert = (col >= 0) && ((size_t)col < m_columns.GetCount());
+        if ( insert )
         {
-            wxListHeaderDataList::Node *node = m_columns.Item( col );
+            wxListHeaderDataList::compatibility_iterator node = m_columns.Item( col );
             m_columns.Insert( node, column );
         }
         else
@@ -4537,6 +4429,20 @@ void wxListMainWindow::InsertColumn( long col, wxListItem &item )
             m_columns.Append( column );
         }
 
+        if ( !IsVirtual() )
+        {
+            // update all the items
+            for ( size_t i = 0; i < m_lines.GetCount(); i++ )
+            {
+                wxListLineData * const line = GetLine(i);
+                wxListItemData * const data = new wxListItemData(this);
+                if ( insert )
+                    line->m_items.Insert(col, data);
+                else
+                    line->m_items.Append(data);
+            }
+        }
+
         // invalidate it as it has to be recalculated
         m_headerWidth = 0;
     }
@@ -4653,7 +4559,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxGenericListCtrl, wxControl)
 
 BEGIN_EVENT_TABLE(wxGenericListCtrl,wxControl)
   EVT_SIZE(wxGenericListCtrl::OnSize)
-  EVT_IDLE(wxGenericListCtrl::OnIdle)
 END_EVENT_TABLE()
 
 wxGenericListCtrl::wxGenericListCtrl()
@@ -4668,6 +4573,7 @@ wxGenericListCtrl::wxGenericListCtrl()
 
     m_mainWin = (wxListMainWindow*) NULL;
     m_headerWin = (wxListHeaderWindow*) NULL;
+    m_headerHeight = 0;
 }
 
 wxGenericListCtrl::~wxGenericListCtrl()
@@ -4680,15 +4586,38 @@ wxGenericListCtrl::~wxGenericListCtrl()
         delete m_imageListState;
 }
 
+void wxGenericListCtrl::CalculateAndSetHeaderHeight()
+{
+    if ( m_headerWin )
+    {
+        // we use 'g' to get the descent, too
+        int w, h, d;
+        m_headerWin->GetTextExtent(wxT("Hg"), &w, &h, &d);
+        h += d + 2 * HEADER_OFFSET_Y + EXTRA_HEIGHT;
+
+        // only update if there is not enough space
+        if ( h > m_headerHeight )
+        {
+            m_headerHeight = h;
+
+            m_headerWin->SetSize(m_headerWin->GetSize().x, m_headerHeight);
+
+            if ( HasFlag(wxLC_REPORT) && !HasFlag(wxLC_NO_HEADER) )
+                ResizeReportView(TRUE);
+        }
+    }
+}
+
 void wxGenericListCtrl::CreateHeaderWindow()
 {
     m_headerWin = new wxListHeaderWindow
                       (
                         this, -1, m_mainWin,
                         wxPoint(0, 0),
-                        wxSize(GetClientSize().x, HEADER_HEIGHT),
+                        wxSize(GetClientSize().x, m_headerHeight),
                         wxTAB_TRAVERSAL
                       );
+    CalculateAndSetHeaderHeight();
 }
 
 bool wxGenericListCtrl::Create(wxWindow *parent,
@@ -4911,11 +4840,16 @@ bool wxGenericListCtrl::SetItemData( long item, long data )
     return TRUE;
 }
 
+wxRect wxGenericListCtrl::GetViewRect() const
+{
+    return m_mainWin->GetViewRect();
+}
+
 bool wxGenericListCtrl::GetItemRect( long item, wxRect &rect,  int WXUNUSED(code) ) const
 {
     m_mainWin->GetItemRect( item, rect );
     if ( m_mainWin->HasHeader() )
-        rect.y += HEADER_HEIGHT + 1;
+        rect.y += m_headerHeight + 1;
     return TRUE;
 }
 
@@ -4945,6 +4879,13 @@ void wxGenericListCtrl::SetItemSpacing( int spacing, bool isSmall )
     m_mainWin->SetItemSpacing( spacing, isSmall );
 }
 
+wxSize wxGenericListCtrl::GetItemSpacing() const
+{
+    const int spacing = m_mainWin->GetItemSpacing(HasFlag(wxLC_SMALL_ICON));
+
+    return wxSize(spacing, spacing);
+}
+
 int wxGenericListCtrl::GetItemSpacing( bool isSmall ) const
 {
     return m_mainWin->GetItemSpacing( isSmall );
@@ -5179,7 +5120,7 @@ long wxGenericListCtrl::InsertColumn( long col, wxListItem &item )
 
     // if we hadn't had header before and have it now we need to relayout the
     // window
-    if ( GetColumnCount() == 1 )
+    if ( GetColumnCount() == 1 && m_mainWin->HasHeader() )
     {
         ResizeReportView(TRUE /* have header */);
     }
@@ -5247,8 +5188,8 @@ void wxGenericListCtrl::ResizeReportView(bool showHeader)
 
     if ( showHeader )
     {
-        m_headerWin->SetSize( 0, 0, cw, HEADER_HEIGHT );
-        m_mainWin->SetSize( 0, HEADER_HEIGHT + 1, cw, ch - HEADER_HEIGHT - 1 );
+        m_headerWin->SetSize( 0, 0, cw, m_headerHeight );
+        m_mainWin->SetSize( 0, m_headerHeight + 1, cw, ch - m_headerHeight - 1 );
     }
     else // no header window
     {
@@ -5256,9 +5197,9 @@ void wxGenericListCtrl::ResizeReportView(bool showHeader)
     }
 }
 
-void wxGenericListCtrl::OnIdle( wxIdleEvent & event )
+void wxGenericListCtrl::OnInternalIdle()
 {
-    event.Skip();
+    wxWindow::OnInternalIdle();
 
     // do it only if needed
     if ( !m_mainWin->m_dirty )
@@ -5315,8 +5256,11 @@ bool wxGenericListCtrl::SetFont( const wxFont &font )
     if (m_headerWin)
     {
         m_headerWin->SetFont( font );
+        CalculateAndSetHeaderHeight();
     }
 
+    Refresh();
+
     return TRUE;
 }
 
@@ -5417,6 +5361,57 @@ void wxGenericListCtrl::RefreshItems(long itemFrom, long itemTo)
     m_mainWin->RefreshLines(itemFrom, itemTo);
 }
 
+/*
+ * Generic wxListCtrl is more or less a container for two other
+ * windows which drawings are done upon. These are namely
+ * 'm_headerWin' and 'm_mainWin'.
+ * Here we override 'virtual wxWindow::Refresh()' to mimic the
+ * behaviour wxListCtrl has under wxMSW.
+ */
+void wxGenericListCtrl::Refresh(bool eraseBackground, const wxRect *rect)
+{
+    if (!rect)
+    {
+        // The easy case, no rectangle specified.
+        if (m_headerWin)
+            m_headerWin->Refresh(eraseBackground);
+
+        if (m_mainWin)
+            m_mainWin->Refresh(eraseBackground);
+    }
+    else
+    {
+        // Refresh the header window
+        if (m_headerWin)
+        {
+            wxRect rectHeader = m_headerWin->GetRect();
+            rectHeader.Intersect(*rect);
+            if (rectHeader.GetWidth() && rectHeader.GetHeight())
+            {
+                int x, y;
+                m_headerWin->GetPosition(&x, &y);
+                rectHeader.Offset(-x, -y);
+                m_headerWin->Refresh(eraseBackground, &rectHeader);
+            }
+
+        }
+
+        // Refresh the main window
+        if (m_mainWin)
+        {
+            wxRect rectMain = m_mainWin->GetRect();
+            rectMain.Intersect(*rect);
+            if (rectMain.GetWidth() && rectMain.GetHeight())
+            {
+                int x, y;
+                m_mainWin->GetPosition(&x, &y);
+                rectMain.Offset(-x, -y);
+                m_mainWin->Refresh(eraseBackground, &rectMain);
+            }
+        }
+    }
+}
+
 void wxGenericListCtrl::Freeze()
 {
     m_mainWin->Freeze();