]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/datavgen.cpp
Replace incorrect uses of wxString::empty() with the intended clear().
[wxWidgets.git] / src / generic / datavgen.cpp
index 99763c1787d0c6f139146bcdda8b678c6e8e119f..716d4b9bf95af43a81b902a23a64c5800e091d15 100644 (file)
@@ -623,6 +623,9 @@ public:
     void ChangeCurrentRow( unsigned int row );
     bool TryAdvanceCurrentColumn(wxDataViewTreeNode *node, bool forward);
 
+    wxDataViewColumn *GetCurrentColumn() const { return m_currentCol; }
+    void ClearCurrentColumn() { m_currentCol = NULL; }
+
     bool IsSingleSel() const { return !GetParent()->HasFlag(wxDV_MULTIPLE); }
     bool IsEmpty() { return GetRowCount() == 0; }
 
@@ -634,7 +637,7 @@ public:
     // the displaying number of the tree are changing along with the
     // expanding/collapsing of the tree nodes
     unsigned int GetLastVisibleRow();
-    unsigned int GetRowCount();
+    unsigned int GetRowCount() const;
 
     const wxDataViewSelection& GetSelections() const { return m_selection; }
     void SetSelections( const wxDataViewSelection & sel )
@@ -703,7 +706,7 @@ public:
     void StartEditing(const wxDataViewItem& item, const wxDataViewColumn* col);
 
 private:
-    int RecalculateCount();
+    int RecalculateCount() const;
 
     // Return false only if the event was vetoed by its handler.
     bool SendExpanderEvent(wxEventType type, const wxDataViewItem& item);
@@ -712,6 +715,10 @@ private:
 
     wxDataViewColumn *FindColumnForEditing(const wxDataViewItem& item, wxDataViewCellMode mode);
 
+    bool IsCellEditableInMode(const wxDataViewItem& item, const wxDataViewColumn *col, wxDataViewCellMode mode) const;
+
+    void DrawCellBackground( wxDataViewRenderer* cell, wxDC& dc, const wxRect& rect );
+
 private:
     wxDataViewCtrl             *m_owner;
     int                         m_lineHeight;
@@ -1021,9 +1028,6 @@ bool wxDataViewToggleRenderer::WXActivateCell(const wxRect& WXUNUSED(cell),
                                               unsigned int col,
                                               const wxMouseEvent *mouseEvent)
 {
-    if ( !model->IsEnabled(item, col) )
-        return false;
-
     if ( mouseEvent )
     {
         // only react to clicks directly on the checkbox, not elsewhere in the same cell:
@@ -1373,7 +1377,14 @@ wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl *parent, wxWindowID i
     m_useCellFocus = false;
     m_currentRow = 0;
 
-    m_lineHeight = wxMax( 17, GetCharHeight() + 4 ); // 17 = mini icon height + 1
+#ifdef __WXMSW__
+    // We would like to use the same line height that Explorer uses. This is
+    // different from standard ListView control since Vista.
+    if ( wxGetWinVersion() >= wxWinVersion_Vista )
+        m_lineHeight = wxMax(16, GetCharHeight()) + 6; // 16 = mini icon height
+    else
+#endif // __WXMSW__
+        m_lineHeight = wxMax(16, GetCharHeight()) + 1; // 16 = mini icon height
 
 #if wxUSE_DRAG_AND_DROP
     m_dragCount = 0;
@@ -1741,6 +1752,37 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
         x_last += col->GetWidth();
     }
 
+    // Draw background of alternate rows specially if required
+    if ( m_owner->HasFlag(wxDV_ROW_LINES) )
+    {
+        wxColour altRowColour = m_owner->m_alternateRowColour;
+        if ( !altRowColour.IsOk() )
+        {
+            // Determine the alternate rows colour automatically from the
+            // background colour.
+            const wxColour bgColour = m_owner->GetBackgroundColour();
+
+            // Depending on the background, alternate row color
+            // will be 3% more dark or 50% brighter.
+            int alpha = bgColour.GetRGB() > 0x808080 ? 97 : 150;
+            altRowColour = bgColour.ChangeLightness(alpha);
+        }
+
+        dc.SetPen(*wxTRANSPARENT_PEN);
+        dc.SetBrush(wxBrush(altRowColour));
+
+        for (unsigned int item = item_start; item < item_last; item++)
+        {
+            if ( item % 2 )
+            {
+                dc.DrawRectangle(x_start,
+                                 GetLineStart(item),
+                                 GetClientSize().GetWidth(),
+                                 GetLineHeight(item));
+            }
+        }
+    }
+
     // Draw horizontal rules if required
     if ( m_owner->HasFlag(wxDV_HORIZ_RULES) )
     {
@@ -1935,6 +1977,11 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
             cell_rect.y = GetLineStart( item );
             cell_rect.height = GetLineHeight( item );
 
+            // draw the background
+            bool selected = m_selection.Index( item ) != wxNOT_FOUND;
+            if ( !selected )
+                DrawCellBackground( cell, dc, cell_rect );
+
             // deal with the expander
             int indent = 0;
             if ((!IsList()) && (col == expander))
@@ -1988,7 +2035,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
                 continue;
 
             int state = 0;
-            if (m_hasFocus && (m_selection.Index(item) != wxNOT_FOUND))
+            if (m_hasFocus && selected)
                 state |= wxDATAVIEW_CELL_SELECTED;
 
             // TODO: it would be much more efficient to create a clipping
@@ -2007,6 +2054,28 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
     }
 }
 
+
+void wxDataViewMainWindow::DrawCellBackground( wxDataViewRenderer* cell, wxDC& dc, const wxRect& rect )
+{
+    wxRect rectBg( rect );
+
+    // don't overlap the horizontal rules
+    if ( m_owner->HasFlag(wxDV_HORIZ_RULES) )
+    {
+        rectBg.x++;
+        rectBg.width--;
+    }
+
+    // don't overlap the vertical rules
+    if ( m_owner->HasFlag(wxDV_VERT_RULES) )
+    {
+        rectBg.y++;
+        rectBg.height--;
+    }
+
+    cell->RenderBackground(&dc, rectBg);
+}
+
 void wxDataViewMainWindow::OnRenameTimer()
 {
     // We have to call this here because changes may just have
@@ -2028,7 +2097,7 @@ wxDataViewMainWindow::StartEditing(const wxDataViewItem& item,
                                    const wxDataViewColumn* col)
 {
     wxDataViewRenderer* renderer = col->GetRenderer();
-    if (renderer->GetMode() != wxDATAVIEW_CELL_EDITABLE)
+    if ( !IsCellEditableInMode(item, col, wxDATAVIEW_CELL_EDITABLE) )
         return;
 
     const wxRect itemRect = GetItemRect(item, col);
@@ -2507,12 +2576,14 @@ unsigned int wxDataViewMainWindow::GetLastVisibleRow()
     return wxMin( GetRowCount()-1, row );
 }
 
-unsigned int wxDataViewMainWindow::GetRowCount()
+unsigned int wxDataViewMainWindow::GetRowCount() const
 {
     if ( m_count == -1 )
     {
-        m_count = RecalculateCount();
-        UpdateDisplay();
+        wxDataViewMainWindow* const
+            self = const_cast<wxDataViewMainWindow*>(this);
+        self->m_count = RecalculateCount();
+        self->UpdateDisplay();
     }
     return m_count;
 }
@@ -2899,15 +2970,20 @@ wxDataViewTreeNode * wxDataViewMainWindow::GetTreeNodeByRow(unsigned int row) co
 
 wxDataViewItem wxDataViewMainWindow::GetItemByRow(unsigned int row) const
 {
+    wxDataViewItem item;
     if (IsVirtualList())
     {
-        return wxDataViewItem( wxUIntToPtr(row+1) );
+        if ( row < GetRowCount() )
+            item = wxDataViewItem(wxUIntToPtr(row+1));
     }
     else
     {
         wxDataViewTreeNode *node = GetTreeNodeByRow(row);
-        return node ? node->GetItem() : wxDataViewItem();
+        if ( node )
+            item = node->GetItem();
     }
+
+    return item;
 }
 
 bool
@@ -3228,7 +3304,7 @@ wxRect wxDataViewMainWindow::GetItemRect( const wxDataViewItem & item,
     return itemRect;
 }
 
-int wxDataViewMainWindow::RecalculateCount()
+int wxDataViewMainWindow::RecalculateCount() const
 {
     if (IsVirtualList())
     {
@@ -3384,7 +3460,7 @@ wxDataViewMainWindow::FindColumnForEditing(const wxDataViewItem& item, wxDataVie
     wxDataViewColumn *candidate = m_currentCol;
 
     if ( candidate &&
-         candidate->GetRenderer()->GetMode() != mode &&
+         !IsCellEditableInMode(item, candidate, mode) &&
          !m_currentColSetByKeyboard )
     {
         // If current column was set by mouse to something not editable (in
@@ -3408,7 +3484,7 @@ wxDataViewMainWindow::FindColumnForEditing(const wxDataViewItem& item, wxDataVie
             if ( c->IsHidden() )
                 continue;
 
-            if ( c->GetRenderer()->GetMode() == mode )
+            if ( IsCellEditableInMode(item, c, mode) )
             {
                 candidate = c;
                 break;
@@ -3429,12 +3505,25 @@ wxDataViewMainWindow::FindColumnForEditing(const wxDataViewItem& item, wxDataVie
     if ( !candidate )
        return NULL;
 
-   if ( candidate->GetRenderer()->GetMode() != mode )
+   if ( !IsCellEditableInMode(item, candidate, mode) )
        return NULL;
 
    return candidate;
 }
 
+bool wxDataViewMainWindow::IsCellEditableInMode(const wxDataViewItem& item,
+                                                const wxDataViewColumn *col,
+                                                wxDataViewCellMode mode) const
+{
+    if ( col->GetRenderer()->GetMode() != mode )
+        return false;
+
+    if ( !GetModel()->IsEnabled(item, col->GetModelColumn()) )
+        return false;
+
+    return true;
+}
+
 void wxDataViewMainWindow::OnCharHook(wxKeyEvent& event)
 {
     if ( m_editorCtrl )
@@ -3483,6 +3572,12 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
     switch ( event.GetKeyCode() )
     {
         case WXK_RETURN:
+            if ( event.HasModifiers() )
+            {
+                event.Skip();
+                break;
+            }
+            else
             {
                 // Enter activates the item, i.e. sends wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED to
                 // it. Only if that event is not handled do we activate column renderer (which
@@ -3502,6 +3597,12 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
             }
 
         case WXK_SPACE:
+            if ( event.HasModifiers() )
+            {
+                event.Skip();
+                break;
+            }
+            else
             {
                 // Space toggles activatable items or -- if not activatable --
                 // starts inline editing (this is normally done using F2 on
@@ -3531,6 +3632,12 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
             }
 
         case WXK_F2:
+            if ( event.HasModifiers() )
+            {
+                event.Skip();
+                break;
+            }
+            else
             {
                 if( !m_selection.empty() )
                 {
@@ -3552,7 +3659,7 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
                     wxDataViewColumn *editableCol = FindColumnForEditing(item, wxDATAVIEW_CELL_EDITABLE);
 
                     if ( editableCol )
-                        GetOwner()->StartEditor(item, GetOwner()->GetColumnIndex(editableCol));
+                        GetOwner()->EditItem(item, editableCol);
                 }
             }
             break;
@@ -4033,7 +4140,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
         if (m_lastOnSame && !ignore_other_columns)
         {
             if ((col == m_currentCol) && (current == m_currentRow) &&
-                (cell->GetMode() & wxDATAVIEW_CELL_EDITABLE) )
+                IsCellEditableInMode(item, col, wxDATAVIEW_CELL_EDITABLE) )
             {
                 m_renameTimer->Start( 100, true );
             }
@@ -4152,7 +4259,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
                         (current == oldCurrentRow)) && oldWasSelected;
 
         // Call ActivateCell() after everything else as under GTK+
-        if (cell->GetMode() & wxDATAVIEW_CELL_ACTIVATABLE)
+        if ( IsCellEditableInMode(item, col, wxDATAVIEW_CELL_ACTIVATABLE) )
         {
             // notify cell about click
             cell->PrepareForItem(model, item, col->GetModelColumn());
@@ -4600,13 +4707,7 @@ unsigned int wxDataViewCtrl::GetBestColumnWidth(int idx) const
                                   m_clientArea->GetRowHeight());
 
     if ( m_headerArea )
-    {
-        int header_width = m_headerArea->GetTextExtent(column->GetTitle()).x;
-        // Labels on native MSW header are indented on both sides
-        header_width +=
-            wxRendererNative::Get().GetHeaderButtonMargin(m_headerArea);
-        calculator.UpdateWithWidth(header_width);
-    }
+        calculator.UpdateWithWidth(m_headerArea->GetColumnTitleWidth(*column));
 
     // The code below deserves some explanation. For very large controls, we
     // simply can't afford to calculate sizes for all items, it takes too
@@ -4701,6 +4802,10 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column )
 
     m_colsBestWidths.erase(m_colsBestWidths.begin() + GetColumnIndex(column));
     m_cols.Erase(ret);
+
+    if ( m_clientArea->GetCurrentColumn() == column )
+        m_clientArea->ClearCurrentColumn();
+
     OnColumnsCountChanged();
 
     return true;
@@ -4711,7 +4816,11 @@ bool wxDataViewCtrl::ClearColumns()
     SetExpanderColumn(NULL);
     m_cols.Clear();
     m_colsBestWidths.clear();
+
+    m_clientArea->ClearCurrentColumn();
+
     OnColumnsCountChanged();
+
     return true;
 }
 
@@ -4754,7 +4863,6 @@ void wxDataViewCtrl::OnInternalIdle()
 
 int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const
 {
-#if 1
     unsigned int len = GetColumnCount();
     for ( unsigned int i = 0; i < len; i++ )
     {
@@ -4764,25 +4872,6 @@ int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const
     }
 
     return wxNOT_FOUND;
-#else
-    // This returns the position in pixels which is not what we want.
-    int ret = 0,
-        dummy = 0;
-    unsigned int len = GetColumnCount();
-    for ( unsigned int i = 0; i < len; i++ )
-    {
-        wxDataViewColumn * col = GetColumnAt(i);
-        if (col->IsHidden())
-            continue;
-        ret += col->GetWidth();
-        if (column==col)
-        {
-            CalcScrolledPosition( ret, dummy, &ret, &dummy );
-            break;
-        }
-    }
-    return ret;
-#endif
 }
 
 wxDataViewColumn *wxDataViewCtrl::GetSortingColumn() const
@@ -4809,6 +4898,11 @@ void wxDataViewCtrl::DoSetCurrentItem(const wxDataViewItem& item)
     }
 }
 
+wxDataViewColumn *wxDataViewCtrl::GetCurrentColumn() const
+{
+    return m_clientArea->GetCurrentColumn();
+}
+
 int wxDataViewCtrl::GetSelectedItemsCount() const
 {
     return m_clientArea->GetSelections().size();
@@ -4897,6 +4991,11 @@ bool wxDataViewCtrl::IsSelected( const wxDataViewItem & item ) const
     return false;
 }
 
+void wxDataViewCtrl::SetAlternateRowColour(const wxColour& colour)
+{
+    m_alternateRowColour = colour;
+}
+
 void wxDataViewCtrl::SelectAll()
 {
     m_clientArea->SelectAllRows(true);
@@ -4987,13 +5086,12 @@ bool wxDataViewCtrl::IsExpanded( const wxDataViewItem & item ) const
     return false;
 }
 
-void wxDataViewCtrl::StartEditor( const wxDataViewItem & item, unsigned int column )
+void wxDataViewCtrl::EditItem(const wxDataViewItem& item, const wxDataViewColumn *column)
 {
-    wxDataViewColumn* col = GetColumn( column );
-    if (!col)
-        return;
+    wxCHECK_RET( item.IsOk(), "invalid item" );
+    wxCHECK_RET( column, "no column provided" );
 
-    m_clientArea->StartEditing(item, col);
+    m_clientArea->StartEditing(item, column);
 }
 
 #endif // !wxUSE_GENERICDATAVIEWCTRL