X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a2d3c415d79ab3a90239b2fcfe9767800e56462d..82614b1a723d277cbf5810bdad8e84eb7d8825ed:/src/generic/datavgen.cpp diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 6b9456a636..f9a43c7075 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -83,6 +83,30 @@ static wxDataViewModel* g_model; static int g_column = -2; static bool g_asending = true; +// ---------------------------------------------------------------------------- +// helper functions +// ---------------------------------------------------------------------------- + +namespace +{ + +// Return the expander column or, if it is not set, the first column and also +// set it as the expander one for the future. +wxDataViewColumn* GetExpanderColumnOrFirstOne(wxDataViewCtrl* dataview) +{ + wxDataViewColumn* expander = dataview->GetExpanderColumn(); + if (!expander) + { + // TODO-RTL: last column for RTL support + expander = dataview->GetColumnAt( 0 ); + dataview->SetExpanderColumn(expander); + } + + return expander; +} + +} // anonymous namespace + //----------------------------------------------------------------------------- // wxDataViewColumn //----------------------------------------------------------------------------- @@ -122,6 +146,30 @@ void wxDataViewColumn::UpdateDisplay() } } +void wxDataViewColumn::SetSortOrder(bool ascending) +{ + if ( !m_owner ) + return; + + // First unset the old sort column if any. + int oldSortKey = m_owner->GetSortingColumnIndex(); + if ( oldSortKey != wxNOT_FOUND ) + { + m_owner->GetColumn(oldSortKey)->UnsetAsSortKey(); + } + + // Now set this one as the new sort column. + const int idx = m_owner->GetColumnIndex(this); + m_owner->SetSortingColumnIndex(idx); + + m_sort = true; + m_sortAscending = ascending; + + // Call this directly instead of using UpdateDisplay() as we already have + // the column index, no need to look it up again. + m_owner->OnColumnChange(idx); +} + //----------------------------------------------------------------------------- // wxDataViewHeaderWindow //----------------------------------------------------------------------------- @@ -169,7 +217,7 @@ private: // for events created by wxDataViewHeaderWindow the // row / value fields are not valid - return owner->GetEventHandler()->ProcessEvent(event); + return owner->ProcessWindowEvent(event); } void OnClick(wxHeaderCtrlEvent& event) @@ -197,16 +245,7 @@ private: } 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(); + col->SetSortOrder(true); } wxDataViewModel * const model = owner->GetModel(); @@ -321,12 +360,13 @@ public: return m_branchData->children; } - void AddChild( wxDataViewTreeNode * node ) + void InsertChild(wxDataViewTreeNode *node, unsigned index) { if ( !m_branchData ) m_branchData = new BranchNodeData; - m_branchData->children.Add( node ); + m_branchData->children.Insert(node, index); + // TODO: insert into sorted array directly in O(log n) instead of resorting in O(n log n) if (g_column >= -1) m_branchData->children.Sort( &wxGenericTreeModelNodeCmp ); @@ -544,8 +584,10 @@ public: wxBitmap CreateItemBitmap( unsigned int row, int &indent ); #endif // wxUSE_DRAG_AND_DROP void OnPaint( wxPaintEvent &event ); - void OnArrowChar(unsigned int newCurrent, const wxKeyEvent& event); void OnChar( wxKeyEvent &event ); + void OnVerticalNavigation(unsigned int newCurrent, const wxKeyEvent& event); + void OnLeftKey(); + void OnRightKey(); void OnMouse( wxMouseEvent &event ); void OnSetFocus( wxFocusEvent &event ); void OnKillFocus( wxFocusEvent &event ); @@ -939,7 +981,7 @@ bool wxDataViewToggleRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state } bool wxDataViewToggleRenderer::WXOnLeftClick(const wxPoint& cursor, - const wxRect& WXUNUSED(cell), + const wxRect& cell, wxDataViewModel *model, const wxDataViewItem& item, unsigned int col) @@ -948,6 +990,14 @@ bool wxDataViewToggleRenderer::WXOnLeftClick(const wxPoint& cursor, if (!wxRect(GetSize()).Contains(cursor)) return false; + return WXOnActivate(cell, model, item, col); +} + +bool wxDataViewToggleRenderer::WXOnActivate(const wxRect& WXUNUSED(cell), + wxDataViewModel *model, + const wxDataViewItem& item, + unsigned int col) +{ if (model->IsEnabled(item, col)) { model->ChangeValue(!m_toggle, item, col); @@ -1616,14 +1666,8 @@ wxBitmap wxDataViewMainWindow::CreateItemBitmap( unsigned int row, int &indent ) wxDataViewModel *model = m_owner->GetModel(); - wxDataViewColumn *expander = GetOwner()->GetExpanderColumn(); - if (!expander) - { - // TODO-RTL: last column for RTL support - expander = GetOwner()->GetColumnAt( 0 ); - GetOwner()->SetExpanderColumn(expander); - } - + wxDataViewColumn * const + expander = GetExpanderColumnOrFirstOne(GetOwner()); int x = 0; for (col = 0; col < cols; col++) @@ -1807,13 +1851,8 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) } #endif // wxUSE_DRAG_AND_DROP - wxDataViewColumn *expander = GetOwner()->GetExpanderColumn(); - if (!expander) - { - // TODO-RTL: last column for RTL support - expander = GetOwner()->GetColumnAt( 0 ); - GetOwner()->SetExpanderColumn(expander); - } + wxDataViewColumn * const + expander = GetExpanderColumnOrFirstOne(GetOwner()); // redraw all cells for all rows which must be repainted and all columns wxRect cell_rect; @@ -1843,7 +1882,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) // Skip all columns of "container" rows except the expander // column itself unless HasContainerColumns() overrides this. - if ( col != GetOwner()->GetExpanderColumn() && + if ( col != expander && model->IsContainer(dataitem) && !model->HasContainerColumns(dataitem) ) continue; @@ -1959,10 +1998,13 @@ public: virtual ~DoJob() { } // The return value control how the tree-walker tranverse the tree - // 0: Job done, stop tranverse and return - // 1: Ignore the current node's subtree and continue - // 2: Job not done, continue - enum { OK = 0 , IGR = 1, CONT = 2 }; + enum + { + DONE, // Job done, stop traversing and return + SKIP_SUBTREE, // Ignore the current node's subtree and continue + CONTINUE // Job not done, continue + }; + virtual int operator() ( wxDataViewTreeNode * node ) = 0; }; @@ -1972,11 +2014,11 @@ bool Walker( wxDataViewTreeNode * node, DoJob & func ) switch( func( node ) ) { - case DoJob::OK: + case DoJob::DONE: return true; - case DoJob::IGR: + case DoJob::SKIP_SUBTREE: return false; - case DoJob::CONT: + case DoJob::CONTINUE: break; } @@ -2013,17 +2055,22 @@ bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem & parent, const wxData if ( !parentNode ) return false; + wxDataViewItemArray siblings; + GetModel()->GetChildren(parent, siblings); + int itemPos = siblings.Index(item, /*fromEnd=*/true); + wxCHECK_MSG( itemPos != wxNOT_FOUND, false, "adding non-existent item?" ); + wxDataViewTreeNode *itemNode = new wxDataViewTreeNode(parentNode, item); itemNode->SetHasChildren(GetModel()->IsContainer(item)); parentNode->SetHasChildren(true); - parentNode->AddChild(itemNode); + parentNode->InsertChild(itemNode, itemPos); parentNode->ChangeSubTreeCount(+1); m_count = -1; } - GetOwner()->UpdateColBestWidths(); + GetOwner()->InvalidateColBestWidths(); UpdateDisplay(); return true; @@ -2158,7 +2205,7 @@ bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent, if( m_currentRow > GetRowCount() ) ChangeCurrentRow(m_count - 1); - GetOwner()->UpdateColBestWidths(); + GetOwner()->InvalidateColBestWidths(); UpdateDisplay(); return true; @@ -2169,7 +2216,7 @@ bool wxDataViewMainWindow::ItemChanged(const wxDataViewItem & item) SortPrepare(); g_model->Resort(); - GetOwner()->UpdateColBestWidths(); + GetOwner()->InvalidateColBestWidths(); // Send event wxWindow *parent = GetParent(); @@ -2177,7 +2224,7 @@ bool wxDataViewMainWindow::ItemChanged(const wxDataViewItem & item) le.SetEventObject(parent); le.SetModel(GetModel()); le.SetItem(item); - parent->GetEventHandler()->ProcessEvent(le); + parent->ProcessWindowEvent(le); return true; } @@ -2210,7 +2257,7 @@ bool wxDataViewMainWindow::ValueChanged( const wxDataViewItem & item, unsigned i SortPrepare(); g_model->Resort(); - GetOwner()->UpdateColBestWidth(view_column); + GetOwner()->InvalidateColBestWidth(view_column); // Send event wxWindow *parent = GetParent(); @@ -2220,7 +2267,7 @@ bool wxDataViewMainWindow::ValueChanged( const wxDataViewItem & item, unsigned i le.SetItem(item); le.SetColumn(view_column); le.SetDataViewColumn(GetOwner()->GetColumn(view_column)); - parent->GetEventHandler()->ProcessEvent(le); + parent->ProcessWindowEvent(le); return true; } @@ -2233,7 +2280,7 @@ bool wxDataViewMainWindow::Cleared() SortPrepare(); BuildTree( GetModel() ); - GetOwner()->UpdateColBestWidths(); + GetOwner()->InvalidateColBestWidths(); UpdateDisplay(); return true; @@ -2489,7 +2536,7 @@ void wxDataViewMainWindow::SendSelectionChangedEvent( const wxDataViewItem& item le.SetModel(GetModel()); le.SetItem( item ); - parent->GetEventHandler()->ProcessEvent(le); + parent->ProcessWindowEvent(le); } void wxDataViewMainWindow::RefreshRow( unsigned int row ) @@ -2535,58 +2582,6 @@ void wxDataViewMainWindow::RefreshRowsAfter( unsigned int firstRow ) Refresh( true, &rect ); } -void wxDataViewMainWindow::OnArrowChar(unsigned int newCurrent, const wxKeyEvent& event) -{ - wxCHECK_RET( newCurrent < GetRowCount(), - wxT("invalid item index in OnArrowChar()") ); - - // if there is no selection, we cannot move it anywhere - if (!HasCurrentRow()) - return; - - unsigned int oldCurrent = m_currentRow; - - // in single selection we just ignore Shift as we can't select several - // items anyhow - if ( event.ShiftDown() && !IsSingleSel() ) - { - RefreshRow( oldCurrent ); - - ChangeCurrentRow( newCurrent ); - - // select all the items between the old and the new one - if ( oldCurrent > newCurrent ) - { - newCurrent = oldCurrent; - oldCurrent = m_currentRow; - } - - SelectRows( oldCurrent, newCurrent, true ); - if (oldCurrent!=newCurrent) - SendSelectionChangedEvent(GetItemByRow(m_selection[0])); - } - else // !shift - { - RefreshRow( oldCurrent ); - - // all previously selected items are unselected unless ctrl is held - if ( !event.ControlDown() ) - SelectAllRows(false); - - ChangeCurrentRow( newCurrent ); - - if ( !event.ControlDown() ) - { - SelectRow( m_currentRow, true ); - SendSelectionChangedEvent(GetItemByRow(m_currentRow)); - } - else - RefreshRow( m_currentRow ); - } - - GetOwner()->EnsureVisible( m_currentRow, -1 ); -} - wxRect wxDataViewMainWindow::GetLineRect( unsigned int row ) const { wxRect rect; @@ -2761,13 +2756,13 @@ public: if( current == static_cast(row)) { ret = node; - return DoJob::OK; + return DoJob::DONE; } if( node->GetSubTreeCount() + current < static_cast(row) ) { current += node->GetSubTreeCount(); - return DoJob::IGR; + return DoJob::SKIP_SUBTREE; } else { @@ -2781,10 +2776,10 @@ public: { const int index = static_cast(row) - current - 1; ret = node->GetChildNodes()[index]; - return DoJob::OK; + return DoJob::DONE; } - return DoJob::CONT; + return DoJob::CONTINUE; } } @@ -3119,7 +3114,8 @@ wxRect wxDataViewMainWindow::GetItemRect( const wxDataViewItem & item, // to get the correct x position where the actual text is int indent = 0; int row = GetRowByItem(item); - if (!IsList() && (column == 0 || GetOwner()->GetExpanderColumn() == column) ) + if (!IsList() && + (column == 0 || GetExpanderColumnOrFirstOne(GetOwner()) == column) ) { wxDataViewTreeNode* node = GetTreeNodeByRow(row); indent = GetOwner()->GetIndent() * node->GetIndentLevel(); @@ -3168,18 +3164,18 @@ public: ret ++; if( node->GetItem() == item ) { - return DoJob::OK; + return DoJob::DONE; } if( node->GetItem() == *m_iter ) { m_iter++; - return DoJob::CONT; + return DoJob::CONTINUE; } else { ret += node->GetSubTreeCount(); - return DoJob::IGR; + return DoJob::SKIP_SUBTREE; } } @@ -3246,7 +3242,7 @@ static void BuildTreeHelper( const wxDataViewModel * model, const wxDataViewIte if( model->IsContainer(children[index]) ) n->SetHasChildren( true ); - node->AddChild(n); + node->InsertChild(n, index); } wxASSERT( node->IsOpen() ); @@ -3309,83 +3305,82 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event ) { case WXK_RETURN: { + // 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 + // is normally done by Space). + + const wxDataViewItem item = GetItemByRow(m_currentRow); + wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, parent->GetId()); - le.SetItem( GetItemByRow(m_currentRow) ); + le.SetItem(item); le.SetEventObject(parent); le.SetModel(GetModel()); - parent->GetEventHandler()->ProcessEvent(le); + if ( parent->ProcessWindowEvent(le) ) + break; + // else: fall through to WXK_SPACE handling + } + + case WXK_SPACE: + { + // Activate the first activatable column if there is any: + wxDataViewColumn *activatableCol = NULL; + + const unsigned cols = GetOwner()->GetColumnCount(); + for ( unsigned i = 0; i < cols; i++ ) + { + wxDataViewColumn *c = GetOwner()->GetColumnAt(i); + if ( c->IsHidden() ) + continue; + if ( c->GetRenderer()->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE ) + { + activatableCol = c; + break; + } + } + + if ( activatableCol ) + { + const wxDataViewItem item = GetItemByRow(m_currentRow); + + const unsigned colIdx = activatableCol->GetModelColumn(); + const wxRect cell_rect = GetOwner()->GetItemRect(item, activatableCol); + + wxDataViewRenderer *cell = activatableCol->GetRenderer(); + cell->PrepareForItem(GetModel(), item, colIdx); + cell->WXOnActivate(cell_rect, GetModel(), item, colIdx); + } } break; case WXK_UP: if ( m_currentRow > 0 ) - OnArrowChar( m_currentRow - 1, event ); + OnVerticalNavigation( m_currentRow - 1, event ); break; case WXK_DOWN: if ( m_currentRow + 1 < GetRowCount() ) - OnArrowChar( m_currentRow + 1, event ); + OnVerticalNavigation( m_currentRow + 1, event ); break; // Add the process for tree expanding/collapsing case WXK_LEFT: - { - if (IsList()) - break; - - wxDataViewTreeNode* node = GetTreeNodeByRow(m_currentRow); - if (!node) - break; - - if (node->HasChildren() && node->IsOpen()) - { - Collapse(m_currentRow); - } - else // if the node is already closed we move the selection to its parent - { - wxDataViewTreeNode *parent_node = node->GetParent(); - - if (parent_node) - { - int parent = GetRowByItem( parent_node->GetItem() ); - if ( parent >= 0 ) - { - unsigned int row = m_currentRow; - SelectRow( row, false); - SelectRow( parent, true ); - ChangeCurrentRow( parent ); - GetOwner()->EnsureVisible( parent, -1 ); - SendSelectionChangedEvent( parent_node->GetItem() ); - } - } - } + OnLeftKey(); break; - } + case WXK_RIGHT: - { - if (!IsExpanded( m_currentRow )) - Expand( m_currentRow ); - else - { - unsigned int row = m_currentRow; - SelectRow( row, false ); - SelectRow( row + 1, true ); - ChangeCurrentRow( row + 1 ); - GetOwner()->EnsureVisible( row + 1, -1 ); - SendSelectionChangedEvent( GetItemByRow(row+1) ); - } + OnRightKey(); break; - } + case WXK_END: { if (!IsEmpty()) - OnArrowChar( GetRowCount() - 1, event ); + OnVerticalNavigation( GetRowCount() - 1, event ); break; } case WXK_HOME: if (!IsEmpty()) - OnArrowChar( 0, event ); + OnVerticalNavigation( 0, event ); break; case WXK_PAGEUP: @@ -3395,7 +3390,7 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event ) if (index < 0) index = 0; - OnArrowChar( index, event ); + OnVerticalNavigation( index, event ); } break; @@ -3407,13 +3402,13 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event ) if ( index >= count ) index = count - 1; - OnArrowChar( index, event ); + OnVerticalNavigation( index, event ); } break; case WXK_F2: { - if(m_selection.size() == 1) + if( !m_selection.empty() ) { // TODO: we need to revise that when we have a concept for a 'current column' GetOwner()->StartEditor(GetItemByRow(m_selection[0]), 0); @@ -3426,6 +3421,106 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event ) } } +void wxDataViewMainWindow::OnVerticalNavigation(unsigned int newCurrent, const wxKeyEvent& event) +{ + wxCHECK_RET( newCurrent < GetRowCount(), + wxT("invalid item index in OnVerticalNavigation()") ); + + // if there is no selection, we cannot move it anywhere + if (!HasCurrentRow()) + return; + + unsigned int oldCurrent = m_currentRow; + + // in single selection we just ignore Shift as we can't select several + // items anyhow + if ( event.ShiftDown() && !IsSingleSel() ) + { + RefreshRow( oldCurrent ); + + ChangeCurrentRow( newCurrent ); + + // select all the items between the old and the new one + if ( oldCurrent > newCurrent ) + { + newCurrent = oldCurrent; + oldCurrent = m_currentRow; + } + + SelectRows( oldCurrent, newCurrent, true ); + if (oldCurrent!=newCurrent) + SendSelectionChangedEvent(GetItemByRow(m_selection[0])); + } + else // !shift + { + RefreshRow( oldCurrent ); + + // all previously selected items are unselected unless ctrl is held + if ( !event.ControlDown() ) + SelectAllRows(false); + + ChangeCurrentRow( newCurrent ); + + if ( !event.ControlDown() ) + { + SelectRow( m_currentRow, true ); + SendSelectionChangedEvent(GetItemByRow(m_currentRow)); + } + else + RefreshRow( m_currentRow ); + } + + GetOwner()->EnsureVisible( m_currentRow, -1 ); +} + +void wxDataViewMainWindow::OnLeftKey() +{ + if (IsList()) + return; + + wxDataViewTreeNode* node = GetTreeNodeByRow(m_currentRow); + if (!node) + return; + + if (node->HasChildren() && node->IsOpen()) + { + Collapse(m_currentRow); + } + else // if the node is already closed we move the selection to its parent + { + wxDataViewTreeNode *parent_node = node->GetParent(); + + if (parent_node) + { + int parent = GetRowByItem( parent_node->GetItem() ); + if ( parent >= 0 ) + { + unsigned int row = m_currentRow; + SelectRow( row, false); + SelectRow( parent, true ); + ChangeCurrentRow( parent ); + GetOwner()->EnsureVisible( parent, -1 ); + SendSelectionChangedEvent( parent_node->GetItem() ); + } + } + } +} + +void wxDataViewMainWindow::OnRightKey() +{ + if (!IsExpanded( m_currentRow )) + Expand( m_currentRow ); + else + { + unsigned int row = m_currentRow; + SelectRow( row, false ); + SelectRow( row + 1, true ); + ChangeCurrentRow( row + 1 ); + GetOwner()->EnsureVisible( row + 1, -1 ); + SendSelectionChangedEvent( GetItemByRow(row+1) ); + } +} + void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) { if (event.GetEventType() == wxEVT_MOUSEWHEEL) @@ -3460,6 +3555,37 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) } xpos += c->GetWidth(); } + + wxDataViewModel* const model = GetModel(); + + const unsigned int current = GetLineAt( y ); + const wxDataViewItem item = GetItemByRow(current); + + // Handle right clicking here, before everything else as context menu + // events should be sent even when we click outside of any item, unlike all + // the other ones. + if (event.RightUp()) + { + wxWindow *parent = GetParent(); + wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, parent->GetId()); + le.SetEventObject(parent); + le.SetModel(model); + + if ( item.IsOk() && col ) + { + le.SetItem( item ); + le.SetColumn( col->GetModelColumn() ); + le.SetDataViewColumn( col ); + + wxVariant value; + model->GetValue( value, item, col->GetModelColumn() ); + le.SetValue(value); + } + + parent->ProcessWindowEvent(le); + return; + } + if (!col) { event.Skip(); @@ -3467,7 +3593,6 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) } wxDataViewRenderer *cell = col->GetRenderer(); - unsigned int current = GetLineAt( y ); if ((current >= GetRowCount()) || (x > GetEndOfLastCol())) { // Unselect all if below the last row ? @@ -3475,27 +3600,29 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) return; } + wxDataViewColumn* const + expander = GetExpanderColumnOrFirstOne(GetOwner()); + // Test whether the mouse is hovering over the expander (a.k.a tree "+" // button) and also determine the offset of the real cell start, skipping // the indentation and the expander itself. bool hoverOverExpander = false; - int expanderOffset = 0; - if ((!IsList()) && (GetOwner()->GetExpanderColumn() == col)) + int itemOffset = 0; + if ((!IsList()) && (expander == col)) { wxDataViewTreeNode * node = GetTreeNodeByRow(current); - if( node!=NULL && node->HasChildren() ) - { - int indent = node->GetIndentLevel(); - indent = GetOwner()->GetIndent()*indent; + int indent = node->GetIndentLevel(); + itemOffset = GetOwner()->GetIndent()*indent; + + if ( node->HasChildren() ) + { // we make the rectangle we are looking in a bit bigger than the actual // visual expander so the user can hit that little thing reliably - wxRect rect( xpos + indent, + wxRect rect(itemOffset, GetLineStart( current ) + (GetLineHeight(current) - m_lineHeight)/2, m_lineHeight, m_lineHeight); - expanderOffset = indent + m_lineHeight; - if( rect.Contains(x, y) ) { // So the mouse is over the expander @@ -3513,6 +3640,10 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) m_underMouse = node; } } + + // Account for the expander as well, even if this item doesn't have it, + // its parent does so it still counts for the offset. + itemOffset += m_lineHeight; } if (!hoverOverExpander) { @@ -3524,8 +3655,6 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) } } - wxDataViewModel *model = GetModel(); - #if wxUSE_DRAG_AND_DROP if (event.Dragging()) { @@ -3547,12 +3676,12 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) m_owner->CalcUnscrolledPosition( m_dragStart.x, m_dragStart.y, &m_dragStart.x, &m_dragStart.y ); unsigned int drag_item_row = GetLineAt( m_dragStart.y ); - wxDataViewItem item = GetItemByRow( drag_item_row ); + wxDataViewItem itemDragged = GetItemByRow( drag_item_row ); // Notify cell about drag wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG, m_owner->GetId() ); event.SetEventObject( m_owner ); - event.SetItem( item ); + event.SetItem( itemDragged ); event.SetModel( model ); if (!m_owner->HandleWindowEvent( event )) return; @@ -3585,9 +3714,8 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) m_lastOnSame = false; } - wxDataViewItem item = GetItemByRow(current); bool ignore_other_columns = - ((GetOwner()->GetExpanderColumn() != col) && + ((expander != col) && (model->IsContainer(item)) && (!model->HasContainerColumns(item))); @@ -3600,6 +3728,8 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) } else if ( current == m_lineLastClicked ) { + bool activated = false; + if ((!ignore_other_columns) && (cell->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE)) { const unsigned colIdx = col->GetModelColumn(); @@ -3608,9 +3738,10 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) wxRect cell_rect( xpos, GetLineStart( current ), col->GetWidth(), GetLineHeight( current ) ); - cell->WXOnActivate( cell_rect, model, item, colIdx ); + activated = cell->WXOnActivate( cell_rect, model, item, colIdx ); } - else + + if ( !activated ) { wxWindow *parent = GetParent(); wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, parent->GetId()); @@ -3620,7 +3751,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) le.SetEventObject(parent); le.SetModel(GetModel()); - parent->GetEventHandler()->ProcessEvent(le); + parent->ProcessWindowEvent(le); } return; } @@ -3682,20 +3813,6 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) SendSelectionChangedEvent(GetItemByRow( m_currentRow ) ); } } - else if (event.RightUp()) - { - wxVariant value; - model->GetValue( value, item, col->GetModelColumn() ); - wxWindow *parent = GetParent(); - wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, parent->GetId()); - le.SetItem( item ); - le.SetColumn( col->GetModelColumn() ); - le.SetDataViewColumn( col ); - le.SetEventObject(parent); - le.SetModel(GetModel()); - le.SetValue(value); - parent->GetEventHandler()->ProcessEvent(le); - } else if (event.MiddleDown()) { } @@ -3784,9 +3901,9 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) // notify cell about click cell->PrepareForItem(model, item, col->GetModelColumn()); - wxRect cell_rect( xpos + expanderOffset, + wxRect cell_rect( xpos + itemOffset, GetLineStart( current ), - col->GetWidth() - expanderOffset, + col->GetWidth() - itemOffset, GetLineHeight( current ) ); // Report position relative to the cell's custom area, i.e. @@ -3880,6 +3997,8 @@ void wxDataViewCtrl::Init() m_sortingColumnIdx = wxNOT_FOUND; m_headerArea = NULL; + + m_colsDirty = false; } bool wxDataViewCtrl::Create(wxWindow *parent, @@ -4283,33 +4402,50 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column ) bool wxDataViewCtrl::ClearColumns() { + SetExpanderColumn(NULL); m_cols.Clear(); m_colsBestWidths.clear(); OnColumnsCountChanged(); return true; } -void wxDataViewCtrl::UpdateColBestWidth(int idx) +void wxDataViewCtrl::InvalidateColBestWidth(int idx) { m_colsBestWidths[idx] = 0; - - if ( m_headerArea ) - m_headerArea->UpdateColumn(idx); + m_colsDirty = true; } -void wxDataViewCtrl::UpdateColBestWidths() +void wxDataViewCtrl::InvalidateColBestWidths() { m_colsBestWidths.clear(); m_colsBestWidths.resize(m_cols.size()); + m_colsDirty = true; +} - if ( m_headerArea ) +void wxDataViewCtrl::UpdateColWidths() +{ + if ( !m_headerArea ) + return; + + const unsigned len = m_colsBestWidths.size(); + for ( unsigned i = 0; i < len; i++ ) { - const unsigned cols = m_headerArea->GetColumnCount(); - for ( unsigned i = 0; i < cols; i++ ) + if ( m_colsBestWidths[i] == 0 ) m_headerArea->UpdateColumn(i); } } +void wxDataViewCtrl::OnInternalIdle() +{ + wxDataViewCtrlBase::OnInternalIdle(); + + if ( m_colsDirty ) + { + m_colsDirty = false; + UpdateColWidths(); + } +} + int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const { #if 1 @@ -4551,10 +4687,12 @@ void wxDataViewCtrl::StartEditor( const wxDataViewItem & item, unsigned int colu if (!col) return; - wxRect itemRect = GetItemRect(item, col); wxDataViewRenderer* renderer = col->GetRenderer(); - if (renderer->GetMode() == wxDATAVIEW_CELL_EDITABLE) - renderer->StartEditing(item, itemRect); + if (renderer->GetMode() != wxDATAVIEW_CELL_EDITABLE) + return; + + const wxRect itemRect = GetItemRect(item, col); + renderer->StartEditing(item, itemRect); } #endif // !wxUSE_GENERICDATAVIEWCTRL