X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c2efa4b48aa1ff1d15caa6ef6ce23affe01cc946..276f3938c4ae6420a05ad2a7667fdf79261c33d6:/src/generic/datavgen.cpp diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 8cd3e24a25..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(); @@ -545,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 ); @@ -1625,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++) @@ -1816,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; @@ -1852,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; @@ -2194,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; } @@ -2237,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; } @@ -2506,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 ) @@ -2552,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; @@ -3136,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(); @@ -3338,7 +3317,7 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event ) le.SetEventObject(parent); le.SetModel(GetModel()); - if ( parent->GetEventHandler()->ProcessEvent(le) ) + if ( parent->ProcessWindowEvent(le) ) break; // else: fall through to WXK_SPACE handling } @@ -3377,71 +3356,31 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event ) 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: @@ -3451,7 +3390,7 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event ) if (index < 0) index = 0; - OnArrowChar( index, event ); + OnVerticalNavigation( index, event ); } break; @@ -3463,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); @@ -3482,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) @@ -3516,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(); @@ -3523,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 ? @@ -3531,12 +3600,15 @@ 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 itemOffset = 0; - if ((!IsList()) && (GetOwner()->GetExpanderColumn() == col)) + if ((!IsList()) && (expander == col)) { wxDataViewTreeNode * node = GetTreeNodeByRow(current); @@ -3583,8 +3655,6 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) } } - wxDataViewModel *model = GetModel(); - #if wxUSE_DRAG_AND_DROP if (event.Dragging()) { @@ -3606,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; @@ -3644,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))); @@ -3682,7 +3751,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) le.SetEventObject(parent); le.SetModel(GetModel()); - parent->GetEventHandler()->ProcessEvent(le); + parent->ProcessWindowEvent(le); } return; } @@ -3744,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()) { } @@ -4347,6 +4402,7 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column ) bool wxDataViewCtrl::ClearColumns() { + SetExpanderColumn(NULL); m_cols.Clear(); m_colsBestWidths.clear(); OnColumnsCountChanged(); @@ -4371,12 +4427,11 @@ void wxDataViewCtrl::UpdateColWidths() if ( !m_headerArea ) return; - for ( wxVector::const_iterator i = m_colsBestWidths.begin(); - i != m_colsBestWidths.end(); - ++i ) + const unsigned len = m_colsBestWidths.size(); + for ( unsigned i = 0; i < len; i++ ) { - if ( m_colsBestWidths[*i] == 0 ) - m_headerArea->UpdateColumn(*i); + if ( m_colsBestWidths[i] == 0 ) + m_headerArea->UpdateColumn(i); } } @@ -4632,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