]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/datavgen.cpp
add support for hiding columns when using native header control in wxGrid; also added...
[wxWidgets.git] / src / generic / datavgen.cpp
index 339d49017455e74b2bee559e9ae129666f239777..21483c4910e6df6750e5285703171c154b4da885 100644 (file)
@@ -67,16 +67,16 @@ static const int EXPANDER_OFFSET = 4;
 static const int EXPANDER_OFFSET = 1;
 #endif
 
-//-----------------------------------------------------------------------------
-// wxDataViewHeaderWindow
-//-----------------------------------------------------------------------------
-
 //Below is the compare stuff
 //For the generic implements, both the leaf nodes and the nodes are sorted for fast search when needed
 static wxDataViewModel * g_model;
 static int g_column = -2;
 static bool g_asending = true;
 
+//-----------------------------------------------------------------------------
+// wxDataViewHeaderWindow
+//-----------------------------------------------------------------------------
+
 class wxDataViewHeaderWindow : public wxHeaderCtrl
 {
 public:
@@ -89,15 +89,120 @@ public:
         { return static_cast<wxDataViewCtrl *>(GetParent()); }
 
 protected:
-    virtual wxHeaderColumnBase& GetColumn(unsigned int idx)
+    // implement/override wxHeaderCtrl functions by forwarding them to the main
+    // control
+    virtual wxHeaderColumn& GetColumn(unsigned int idx)
     {
         return *(GetOwner()->GetColumn(idx));
     }
 
+    virtual bool UpdateColumnWidthToFit(unsigned int idx, int widthTitle)
+    {
+        wxDataViewCtrl * const owner = GetOwner();
+
+        int widthContents = owner->GetBestColumnWidth(idx);
+        owner->GetColumn(idx)->SetWidth(wxMax(widthTitle, widthContents));
+        owner->OnColumnChange(idx);
+
+        return true;
+    }
+
 private:
+    bool SendEvent(wxEventType type, unsigned int n)
+    {
+        wxDataViewCtrl * const owner = GetOwner();
+        wxDataViewEvent event(type, owner->GetId());
+
+        event.SetEventObject(owner);
+        event.SetColumn(n);
+        event.SetDataViewColumn(owner->GetColumn(n));
+        event.SetModel(owner->GetModel());
+
+        // for events created by wxDataViewHeaderWindow the
+        // row / value fields are not valid
+        return owner->GetEventHandler()->ProcessEvent(event);
+    }
+
+    void OnClick(wxHeaderCtrlEvent& event)
+    {
+        const unsigned idx = event.GetColumn();
+
+        if ( SendEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK, idx) )
+            return;
+
+        // default handling for the column click is to sort by this column or
+        // toggle its sort order
+        wxDataViewCtrl * const owner = GetOwner();
+        wxDataViewColumn * const col = owner->GetColumn(idx);
+        if ( !col->IsSortable() )
+        {
+            // no default handling for non-sortable columns
+            event.Skip();
+            return;
+        }
+
+        if ( col->IsSortKey() )
+        {
+            // already using this column for sorting, just change the order
+            col->ToggleSortOrder();
+        }
+        else // not using this column for sorting yet
+        {
+            // first unset the old sort column if any
+            int oldSortKey = owner->GetSortingColumnIndex();
+            if ( oldSortKey != wxNOT_FOUND )
+            {
+                owner->GetColumn(oldSortKey)->UnsetAsSortKey();
+                owner->OnColumnChange(oldSortKey);
+            }
+
+            owner->SetSortingColumnIndex(idx);
+            col->SetAsSortKey();
+        }
+
+        wxDataViewModel * const model = owner->GetModel();
+        if ( model )
+            model->Resort();
+
+        owner->OnColumnChange(idx);
+    }
+
+    void OnRClick(wxHeaderCtrlEvent& event)
+    {
+        if ( !SendEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK,
+                        event.GetColumn()) )
+            event.Skip();
+    }
+
+    void OnEndResize(wxHeaderCtrlEvent& event)
+    {
+        wxDataViewCtrl * const owner = GetOwner();
+
+        const unsigned col = event.GetColumn();
+        owner->GetColumn(col)->SetWidth(event.GetWidth());
+        GetOwner()->OnColumnChange(col);
+    }
+
+    void OnEndReorder(wxHeaderCtrlEvent& event)
+    {
+        wxDataViewCtrl * const owner = GetOwner();
+        owner->ColumnMoved(owner->GetColumn(event.GetColumn()),
+                           event.GetNewOrder());
+    }
+
+    DECLARE_EVENT_TABLE()
     DECLARE_NO_COPY_CLASS(wxDataViewHeaderWindow)
 };
 
+BEGIN_EVENT_TABLE(wxDataViewHeaderWindow, wxHeaderCtrl)
+    EVT_HEADER_CLICK(wxID_ANY, wxDataViewHeaderWindow::OnClick)
+    EVT_HEADER_RIGHT_CLICK(wxID_ANY, wxDataViewHeaderWindow::OnRClick)
+
+    EVT_HEADER_END_RESIZE(wxID_ANY, wxDataViewHeaderWindow::OnEndResize)
+
+    EVT_HEADER_END_REORDER(wxID_ANY, wxDataViewHeaderWindow::OnEndReorder)
+END_EVENT_TABLE()
+
 //-----------------------------------------------------------------------------
 // wxDataViewRenameTimer
 //-----------------------------------------------------------------------------
@@ -1130,7 +1235,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
     unsigned int x_start;
     for (x_start = 0; col_start < cols; col_start++)
     {
-        wxDataViewColumn *col = GetOwner()->GetColumn(col_start);
+        wxDataViewColumn *col = GetOwner()->GetColumnAt(col_start);
         if (col->IsHidden())
             continue;      // skip it!
 
@@ -1145,7 +1250,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
     unsigned int x_last = x_start;
     for (; col_last < cols; col_last++)
     {
-        wxDataViewColumn *col = GetOwner()->GetColumn(col_last);
+        wxDataViewColumn *col = GetOwner()->GetColumnAt(col_last);
         if (col->IsHidden())
             continue;      // skip it!
 
@@ -1177,7 +1282,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
         int x = x_start;
         for (unsigned int i = col_start; i < col_last; i++)
         {
-            wxDataViewColumn *col = GetOwner()->GetColumn(i);
+            wxDataViewColumn *col = GetOwner()->GetColumnAt(i);
             if (col->IsHidden())
                 continue;       // skip it
 
@@ -1218,8 +1323,8 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
     wxDataViewColumn *expander = GetOwner()->GetExpanderColumn();
     if (!expander)
     {
-        // TODO: last column for RTL support
-        expander = GetOwner()->GetColumn( 0 );
+        // TODO-RTL: last column for RTL support
+        expander = GetOwner()->GetColumnAt( 0 );
         GetOwner()->SetExpanderColumn(expander);
     }
 
@@ -1229,7 +1334,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
     for (unsigned int i = col_start; i < col_last; i++)
     {
 
-        wxDataViewColumn *col = GetOwner()->GetColumn( i );
+        wxDataViewColumn *col = GetOwner()->GetColumnAt( i );
         wxDataViewRenderer *cell = col->GetRenderer();
         cell_rect.width = col->GetWidth();
 
@@ -1379,7 +1484,7 @@ void wxDataViewMainWindow::OnRenameTimer()
     unsigned int i;
     for (i = 0; i < cols; i++)
     {
-        wxDataViewColumn *c = GetOwner()->GetColumn( i );
+        wxDataViewColumn *c = GetOwner()->GetColumnAt( i );
         if (c->IsHidden())
             continue;      // skip it!
 
@@ -1690,7 +1795,7 @@ void wxDataViewMainWindow::ScrollTo( int rows, int column )
         m_owner->CalcUnscrolledPosition( rect.x, rect.y, &xx, &yy );
         for (x_start = 0; colnum < column; colnum++)
         {
-            wxDataViewColumn *col = GetOwner()->GetColumn(colnum);
+            wxDataViewColumn *col = GetOwner()->GetColumnAt(colnum);
             if (col->IsHidden())
                 continue;      // skip it!
 
@@ -1725,7 +1830,7 @@ int wxDataViewMainWindow::GetEndOfLastCol() const
     for (i = 0; i < GetOwner()->GetColumnCount(); i++)
     {
         const wxDataViewColumn *c =
-            const_cast<wxDataViewCtrl*>(GetOwner())->GetColumn( i );
+            const_cast<wxDataViewCtrl*>(GetOwner())->GetColumnAt( i );
 
         if (!c->IsHidden())
             width += c->GetWidth();
@@ -2452,7 +2557,7 @@ void wxDataViewMainWindow::HitTest( const wxPoint & point, wxDataViewItem & item
     m_owner->CalcUnscrolledPosition( point.x, point.y, &x, &y );
     for (unsigned x_start = 0; colnum < cols; colnum++)
     {
-        col = GetOwner()->GetColumn(colnum);
+        col = GetOwner()->GetColumnAt(colnum);
         if (col->IsHidden())
             continue;      // skip it!
 
@@ -2476,9 +2581,9 @@ wxRect wxDataViewMainWindow::GetItemRect( const wxDataViewItem & item, const wxD
     wxDataViewColumn *col = NULL;
     for( int i = 0, cols = GetOwner()->GetColumnCount(); i < cols; i ++ )
     {
-       col = GetOwner()->GetColumn( i );
+       col = GetOwner()->GetColumnAt( i );
        x += col->GetWidth();
-       if( GetOwner()->GetColumn(i+1) == column )
+       if( GetOwner()->GetColumnAt(i+1) == column )
            break;
     }
     int w = col->GetWidth();
@@ -2767,7 +2872,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
     unsigned int i;
     for (i = 0; i < cols; i++)
     {
-        wxDataViewColumn *c = GetOwner()->GetColumn( i );
+        wxDataViewColumn *c = GetOwner()->GetColumnAt( i );
         if (c->IsHidden())
             continue;      // skip it!
 
@@ -3128,7 +3233,8 @@ void wxDataViewCtrl::Init()
     m_notifier = NULL;
 
     // No sorting column at start
-    m_sortingColumn = NULL;
+    m_sortingColumnIdx = wxNOT_FOUND;
+
     m_headerArea = NULL;
 }
 
@@ -3241,7 +3347,7 @@ bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col )
         return false;
 
     m_cols.Append( col );
-    OnColumnChange();
+    OnColumnsCountChanged();
     return true;
 }
 
@@ -3251,7 +3357,7 @@ bool wxDataViewCtrl::PrependColumn( wxDataViewColumn *col )
         return false;
 
     m_cols.Insert( col );
-    OnColumnChange();
+    OnColumnsCountChanged();
     return true;
 }
 
@@ -3261,11 +3367,19 @@ bool wxDataViewCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *col )
         return false;
 
     m_cols.Insert( pos, col );
-    OnColumnChange();
+    OnColumnsCountChanged();
     return true;
 }
 
-void wxDataViewCtrl::OnColumnChange()
+void wxDataViewCtrl::OnColumnChange(unsigned int idx)
+{
+    if ( m_headerArea )
+        m_headerArea->UpdateColumn(idx);
+
+    m_clientArea->UpdateDisplay();
+}
+
+void wxDataViewCtrl::OnColumnsCountChanged()
 {
     if (m_headerArea)
         m_headerArea->SetColumnCount(GetColumnCount());
@@ -3288,32 +3402,39 @@ unsigned int wxDataViewCtrl::GetColumnCount() const
     return m_cols.GetCount();
 }
 
-wxDataViewColumn* wxDataViewCtrl::GetColumn( unsigned int pos ) const
+wxDataViewColumn* wxDataViewCtrl::GetColumn( unsigned int idx ) const
 {
-    wxDataViewColumnList::const_iterator iter;
-    unsigned int i = 0;
-    for (iter = m_cols.begin(); iter!=m_cols.end(); iter++)
-    {
-        if (i == pos)
-            return *iter;
+    return m_cols[idx];
+}
 
-        if ((*iter)->IsHidden())
-            continue;
-        i ++;
-    }
-    return NULL;
+wxDataViewColumn *wxDataViewCtrl::GetColumnAt(unsigned int pos) const
+{
+    // columns can't be reordered if there is no header window which allows
+    // to do this
+    const unsigned idx = m_headerArea ? m_headerArea->GetColumnsOrder()[pos]
+                                      : pos;
+
+    return GetColumn(idx);
 }
 
-void wxDataViewCtrl::ColumnMoved( wxDataViewColumn* col, unsigned int new_pos )
+int wxDataViewCtrl::GetColumnIndex(const wxDataViewColumn *column) const
 {
-    if (new_pos > m_cols.GetCount()) return;
+    const unsigned count = m_cols.size();
+    for ( unsigned n = 0; n < count; n++ )
+    {
+        if ( m_cols[n] == column )
+            return n;
+    }
 
-    // Exchange position
-    m_cols.DeleteContents(false);
-    m_cols.DeleteObject( col );
-    m_cols.Insert( new_pos, col );
-    m_cols.DeleteContents(true);
+    return wxNOT_FOUND;
+}
 
+void wxDataViewCtrl::ColumnMoved(wxDataViewColumn * WXUNUSED(col),
+                                 unsigned int WXUNUSED(new_pos))
+{
+    // do _not_ reorder m_cols elements here, they should always be in the
+    // order in which columns were added, we only display the columns in
+    // different order
     m_clientArea->UpdateDisplay();
 }
 
@@ -3324,7 +3445,7 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column )
         return false;
 
     m_cols.Erase(ret);
-    OnColumnChange();
+    OnColumnsCountChanged();
 
     return true;
 }
@@ -3332,23 +3453,24 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column )
 bool wxDataViewCtrl::ClearColumns()
 {
     m_cols.Clear();
-    OnColumnChange();
+    OnColumnsCountChanged();
     return true;
 }
 
 int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const
 {
-    int ret = 0, dead = 0;
-    int len = GetColumnCount();
-    for (int i=0; i<len; i++)
+    int ret = 0,
+        dummy = 0;
+    unsigned int len = GetColumnCount();
+    for ( unsigned int i = 0; i < len; i++ )
     {
-        wxDataViewColumn * col = GetColumn(i);
+        wxDataViewColumn * col = GetColumnAt(i);
         if (col->IsHidden())
             continue;
         ret += col->GetWidth();
         if (column==col)
         {
-            CalcScrolledPosition( ret, dead, &ret, &dead );
+            CalcScrolledPosition( ret, dummy, &ret, &dummy );
             break;
         }
     }
@@ -3357,7 +3479,8 @@ int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const
 
 wxDataViewColumn *wxDataViewCtrl::GetSortingColumn() const
 {
-    return NULL;
+    return m_sortingColumnIdx == wxNOT_FOUND ? NULL
+                                             : GetColumn(m_sortingColumnIdx);
 }
 
 //Selection code with wxDataViewItem as parameters
@@ -3523,17 +3646,7 @@ void wxDataViewCtrl::EnsureVisible( const wxDataViewItem & item, const wxDataVie
         if( column == NULL )
             EnsureVisible(row, -1);
         else
-        {
-            int col = 0;
-            int len = GetColumnCount();
-            for( int i = 0; i < len; i ++ )
-                if( GetColumn(i) == column )
-                {
-                    col = i;
-                    break;
-                }
-            EnsureVisible( row, col );
-        }
+            EnsureVisible( row, GetColumnIndex(column) );
     }
 
 }