]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/listctrl.cpp
floating pane size now restores after perspective restore
[wxWidgets.git] / src / generic / listctrl.cpp
index 952596d171056f39d8d1a9a3fea83d843c1baa11..3bda4a220f1c71f0d6adf35f144f68318c8c221f 100644 (file)
@@ -39,6 +39,7 @@
     #include "wx/timer.h"
     #include "wx/settings.h"
     #include "wx/dynarray.h"
+    #include "wx/dcclient.h"
     #include "wx/dcscreen.h"
     #include "wx/math.h"
 #endif
@@ -70,7 +71,11 @@ static const int SCROLL_UNIT_X = 15;
 static const int LINE_SPACING = 0;
 
 // extra margins around the text label
+#ifdef __WXGTK__
+static const int EXTRA_WIDTH = 6;
+#else
 static const int EXTRA_WIDTH = 4;
+#endif
 static const int EXTRA_HEIGHT = 4;
 
 // margin between the window and the items
@@ -120,7 +125,7 @@ WX_DEFINE_ARRAY_PTR(wxColWidthInfo *, ColWidthArray);
 //  wxListItemData (internal)
 //-----------------------------------------------------------------------------
 
-class WXDLLEXPORT wxListItemData
+class wxListItemData
 {
 public:
     wxListItemData(wxListMainWindow *owner);
@@ -190,7 +195,7 @@ protected:
 //  wxListHeaderData (internal)
 //-----------------------------------------------------------------------------
 
-class WXDLLEXPORT wxListHeaderData : public wxObject
+class wxListHeaderData : public wxObject
 {
 public:
     wxListHeaderData();
@@ -198,6 +203,7 @@ public:
     void SetItem( const wxListItem &item );
     void SetPosition( int x, int y );
     void SetWidth( int w );
+    void SetState( int state );
     void SetFormat( int format );
     void SetHeight( int h );
     bool HasImage() const;
@@ -212,6 +218,7 @@ public:
     int GetImage() const;
     int GetWidth() const;
     int GetFormat() const;
+    int GetState() const;
 
 protected:
     long      m_mask;
@@ -222,6 +229,7 @@ protected:
     int       m_xpos,
               m_ypos;
     int       m_height;
+    int       m_state;
 
 private:
     void Init();
@@ -371,7 +379,7 @@ WX_DEFINE_OBJARRAY(wxListLineDataArray)
 //  wxListHeaderWindow (internal)
 //-----------------------------------------------------------------------------
 
-class WXDLLEXPORT wxListHeaderWindow : public wxWindow
+class wxListHeaderWindow : public wxWindow
 {
 protected:
     wxListMainWindow  *m_owner;
@@ -428,7 +436,7 @@ private:
 // wxListRenameTimer (internal)
 //-----------------------------------------------------------------------------
 
-class WXDLLEXPORT wxListRenameTimer: public wxTimer
+class wxListRenameTimer: public wxTimer
 {
 private:
     wxListMainWindow *m_owner;
@@ -442,7 +450,7 @@ public:
 // wxListTextCtrlWrapper: wraps a wxTextCtrl to make it work for inline editing
 //-----------------------------------------------------------------------------
 
-class WXDLLEXPORT wxListTextCtrlWrapper : public wxEvtHandler
+class wxListTextCtrlWrapper : public wxEvtHandler
 {
 public:
     // NB: text must be a valid object but not Create()d yet
@@ -686,7 +694,7 @@ public:
 
     // send out a wxListEvent
     void SendNotify( size_t line,
-                     wxEventType command,
+                     wxEventType command, 
                      const wxPoint& point = wxDefaultPosition );
 
     // override base class virtual to reset m_lineHeight when the font changes
@@ -719,6 +727,11 @@ public:
     {
         return m_hasFocus ? m_highlightBrush : m_highlightUnfocusedBrush;
     }
+    
+    bool HasFocus() const
+    {
+        return m_hasFocus;
+    }
 
 //protected:
     // the array of all line objects for a non virtual list control (for the
@@ -887,7 +900,7 @@ void wxListItemData::SetItem( const wxListItem &info )
     if ( info.HasAttributes() )
     {
         if ( m_attr )
-            *m_attr = *info.GetAttributes();
+            m_attr->AssignFrom(*info.GetAttributes());
         else
             m_attr = new wxListItemAttr(*info.GetAttributes());
     }
@@ -992,6 +1005,7 @@ void wxListHeaderData::Init()
     m_xpos = 0;
     m_ypos = 0;
     m_height = 0;
+    m_state = 0;
 }
 
 wxListHeaderData::wxListHeaderData()
@@ -1021,6 +1035,9 @@ void wxListHeaderData::SetItem( const wxListItem &item )
 
     if ( m_mask & wxLIST_MASK_WIDTH )
         SetWidth(item.m_width);
+        
+    if ( m_mask & wxLIST_MASK_STATE )
+        SetState(item.m_state);
 }
 
 void wxListHeaderData::SetPosition( int x, int y )
@@ -1039,6 +1056,11 @@ void wxListHeaderData::SetWidth( int w )
     m_width = w < 0 ? WIDTH_COL_DEFAULT : w;
 }
 
+void wxListHeaderData::SetState( int flag )
+{
+    m_state = flag;
+}
+
 void wxListHeaderData::SetFormat( int format )
 {
     m_format = format;
@@ -1061,6 +1083,7 @@ void wxListHeaderData::GetItem( wxListItem& item )
     item.m_image = m_image;
     item.m_format = m_format;
     item.m_width = m_width;
+    item.m_state = m_state;
 }
 
 int wxListHeaderData::GetImage() const
@@ -1078,6 +1101,11 @@ int wxListHeaderData::GetFormat() const
     return m_format;
 }
 
+int wxListHeaderData::GetState() const
+{
+    return m_state;
+}
+
 //-----------------------------------------------------------------------------
 //  wxListLineData
 //-----------------------------------------------------------------------------
@@ -1237,9 +1265,9 @@ void wxListLineData::SetPosition( int x, int y, int spacing )
             if ( item->HasText() )
             {
                 if (m_gi->m_rectAll.width > spacing)
-                    m_gi->m_rectLabel.x = m_gi->m_rectAll.x + 2;
+                    m_gi->m_rectLabel.x = m_gi->m_rectAll.x + (EXTRA_WIDTH/2);
                 else
-                    m_gi->m_rectLabel.x = m_gi->m_rectAll.x + 2 + (spacing / 2) - (m_gi->m_rectLabel.width / 2);
+                    m_gi->m_rectLabel.x = m_gi->m_rectAll.x + (EXTRA_WIDTH/2) + (spacing / 2) - (m_gi->m_rectLabel.width / 2);
                 m_gi->m_rectLabel.y = m_gi->m_rectAll.y + m_gi->m_rectAll.height + 2 - m_gi->m_rectLabel.height;
                 m_gi->m_rectHighlight.x = m_gi->m_rectLabel.x - 2;
                 m_gi->m_rectHighlight.y = m_gi->m_rectLabel.y - 2;
@@ -1263,11 +1291,11 @@ void wxListLineData::SetPosition( int x, int y, int spacing )
             {
                 m_gi->m_rectIcon.x = m_gi->m_rectAll.x + 2;
                 m_gi->m_rectIcon.y = m_gi->m_rectAll.y + 2;
-                m_gi->m_rectLabel.x = m_gi->m_rectAll.x + 6 + m_gi->m_rectIcon.width;
+                m_gi->m_rectLabel.x = m_gi->m_rectAll.x + 4 + (EXTRA_WIDTH/2) + m_gi->m_rectIcon.width;
             }
             else
             {
-                m_gi->m_rectLabel.x = m_gi->m_rectAll.x + 2;
+                m_gi->m_rectLabel.x = m_gi->m_rectAll.x + (EXTRA_WIDTH/2);
             }
             break;
 
@@ -1379,7 +1407,16 @@ bool wxListLineData::SetAttributes(wxDC *dc,
     // arithmetics on wxColour, unfortunately)
     wxColour colText;
     if ( highlighted )
+#ifdef __WXMAC__
+    {
+        if (m_owner->HasFocus())
+            colText = *wxWHITE;
+        else
+            colText = *wxBLACK;
+    }
+#else
         colText = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
+#endif
     else if ( attr && attr->HasTextColour() )
         colText = attr->GetTextColour();
     else
@@ -1423,7 +1460,26 @@ void wxListLineData::Draw( wxDC *dc )
     wxListItemAttr *attr = GetAttr();
 
     if ( SetAttributes(dc, attr, highlighted) )
+#if ( !defined(__WXGTK20__) && !defined(__WXMAC__) )
+    {
         dc->DrawRectangle( m_gi->m_rectHighlight );
+    }
+#else
+    {
+        if (highlighted)
+        {
+            int flags = wxCONTROL_SELECTED;
+            if (m_owner->HasFocus())
+                flags |= wxCONTROL_FOCUSED;
+            wxRendererNative::Get().DrawItemSelectionRect( m_owner, *dc, m_gi->m_rectHighlight, flags );
+            
+        }
+        else
+        {
+            dc->DrawRectangle( m_gi->m_rectHighlight );
+        }
+    }
+#endif
 
     // just for debugging to better see where the items are
 #if 0
@@ -1463,10 +1519,34 @@ void wxListLineData::DrawInReportMode( wxDC *dc,
     //       GetAttr() and move these lines into the loop below
     wxListItemAttr *attr = GetAttr();
     if ( SetAttributes(dc, attr, highlighted) )
+#if ( !defined(__WXGTK20__) && !defined(__WXMAC__) )
+    {
         dc->DrawRectangle( rectHL );
+    }
+#else
+    {
+        if (highlighted)
+        {
+            int flags = wxCONTROL_SELECTED;
+            if (m_owner->HasFocus())
+                flags |= wxCONTROL_FOCUSED;
+            wxRendererNative::Get().DrawItemSelectionRect( m_owner, *dc, rectHL, flags );
+        }
+        else
+        {
+            dc->DrawRectangle( rectHL );
+        }
+    }
+#endif
 
     wxCoord x = rect.x + HEADER_OFFSET_X,
             yMid = rect.y + rect.height/2;
+#ifdef __WXGTK__
+    // This probably needs to be done
+    // on all platforms as the icons
+    // otherwise nearly touch the border
+    x += 2;
+#endif
 
     size_t col = 0;
     for ( wxListItemDataList::compatibility_iterator node = m_items.GetFirst();
@@ -1717,13 +1797,26 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
         int ch = h - 2;
 #endif
 
+        int flags = 0;
+        if (!m_parent->IsEnabled())
+            flags |= wxCONTROL_DISABLED;
+
+// NB: The code below is not really Mac-specific, but since we are close 
+// to 2.8 release and I don't have time to test on other platforms, I
+// defined this only for wxMac. If this behavior is desired on
+// other platforms, please go ahead and revise or remove the #ifdef.
+#ifdef __WXMAC__
+        if ( !m_owner->IsVirtual() && (item.m_mask & wxLIST_MASK_STATE) && 
+                (item.m_state & wxLIST_STATE_SELECTED) )
+            flags |= wxCONTROL_SELECTED;
+#endif
+
         wxRendererNative::Get().DrawHeaderButton
                                 (
                                     this,
                                     dc,
                                     wxRect(x, HEADER_OFFSET_Y, cw, ch),
-                                    m_parent->IsEnabled() ? 0
-                                                          : (int)wxCONTROL_DISABLED
+                                    flags
                                 );
 
         // see if we have enough space for the column label
@@ -1919,6 +2012,22 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event )
             }
             else // click on a column
             {
+                // record the selected state of the columns
+                if (event.LeftDown())
+                {
+                    for (int i=0; i < m_owner->GetColumnCount(); i++)
+                    {
+                        wxListItem colItem;
+                        m_owner->GetColumn(i, colItem);
+                        long state = colItem.GetState(); 
+                        if (i == m_column)
+                            colItem.SetState(state | wxLIST_STATE_SELECTED);
+                        else
+                            colItem.SetState(state & ~wxLIST_STATE_SELECTED);
+                        m_owner->SetColumn(i, colItem);
+                    }
+                }
+                
                 SendListEvent( event.LeftDown()
                                     ? wxEVT_COMMAND_LIST_COL_CLICK
                                     : wxEVT_COMMAND_LIST_COL_RIGHT_CLICK,
@@ -2182,22 +2291,22 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent,
     Init();
 
     m_highlightBrush = new wxBrush
-                           (
+                         (
                             wxSystemSettings::GetColour
                             (
                                 wxSYS_COLOUR_HIGHLIGHT
                             ),
                             wxSOLID
-                           );
-
+                         );
+                         
     m_highlightUnfocusedBrush = new wxBrush
-                                    (
-                                       wxSystemSettings::GetColour
-                                       (
-                                           wxSYS_COLOUR_BTNSHADOW
-                                       ),
-                                       wxSOLID
-                                    );
+                              (
+                                 wxSystemSettings::GetColour
+                                 (
+                                     wxSYS_COLOUR_BTNSHADOW
+                                 ),
+                                 wxSOLID
+                              );
 
     SetScrollbars( 0, 0, 0, 0, 0, 0 );
 
@@ -2698,9 +2807,15 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
     {
         if ( m_hasFocus )
         {
+            wxRect rect( GetLineHighlightRect( m_current ) );
+#ifndef __WXGTK20__
             dc.SetPen( *wxBLACK_PEN );
             dc.SetBrush( *wxTRANSPARENT_BRUSH );
-            dc.DrawRectangle( GetLineHighlightRect( m_current ) );
+            dc.DrawRectangle( rect );
+#else
+            wxRendererNative::Get().DrawItemSelectionRect( this, dc, rect, wxCONTROL_CURRENT|wxCONTROL_FOCUSED );
+            
+#endif
         }
     }
 #endif
@@ -2731,6 +2846,7 @@ void wxListMainWindow::SendNotify( size_t line,
 {
     wxListEvent le( command, GetParent()->GetId() );
     le.SetEventObject( GetParent() );
+    
     le.m_itemIndex = line;
 
     // set only for events which have position
@@ -2741,7 +2857,7 @@ void wxListMainWindow::SendNotify( size_t line,
     // program has it anyhow and if we did it would result in accessing all
     // the lines, even those which are not visible now and this is precisely
     // what we're trying to avoid
-    if ( !IsVirtual() && (command != wxEVT_COMMAND_LIST_DELETE_ITEM) )
+    if ( !IsVirtual() )
     {
         if ( line != (size_t)-1 )
         {
@@ -3945,6 +4061,8 @@ bool wxListMainWindow::GetItemPosition(long item, wxPoint& pos) const
 
 void wxListMainWindow::RecalculatePositions(bool noRefresh)
 {
+    const int lineHeight = GetLineHeight();
+
     wxClientDC dc( this );
     dc.SetFont( GetFont() );
 
@@ -3978,8 +4096,6 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
         clientHeight;
     GetSize( &clientWidth, &clientHeight );
 
-    const int lineHeight = GetLineHeight();
-
     if ( InReportView() )
     {
         // all lines have the same height and we scroll one line per step
@@ -4221,11 +4337,11 @@ void wxListMainWindow::DeleteItem( long lindex )
         if ( m_current != index || m_current == count - 1 )
             m_current--;
     }
-
     if ( InReportView() )
     {
-    //  mark the Column Max Width cache as dirty if the items in the line
-    //  we're deleting contain the Max Column Width
+        //  mark the Column Max Width cache as dirty if the items in the line
+        //  we're deleting contain the Max Column Width
         wxListLineData * const line = GetLine(index);
         wxListItemDataList::compatibility_iterator n;
         wxListItemData *itemData;
@@ -4247,6 +4363,8 @@ void wxListMainWindow::DeleteItem( long lindex )
         ResetVisibleLinesRange();
     }
 
+    SendNotify( index, wxEVT_COMMAND_LIST_DELETE_ITEM, wxDefaultPosition );
+
     if ( IsVirtual() )
     {
         m_countVirt--;
@@ -4260,8 +4378,6 @@ void wxListMainWindow::DeleteItem( long lindex )
     // we need to refresh the (vert) scrollbar as the number of items changed
     m_dirty = true;
 
-    SendNotify( index, wxEVT_COMMAND_LIST_DELETE_ITEM );
-
     RefreshAfter(index);
 }
 
@@ -4805,7 +4921,7 @@ bool wxGenericListCtrl::Create(wxWindow *parent,
             m_headerWin->Show( false );
     }
 
-    SetBestSize(size);
+    SetInitialSize(size);
 
     return true;
 }