From c2e4bc422cea0662602a727a8a56e1457574a71b Mon Sep 17 00:00:00 2001 From: Jorge Moraleda Date: Sun, 12 Apr 2020 23:15:21 -0700 Subject: [PATCH] Make HasValue virtual in wxDataViewModel and have implementations use it. This addresses issue https://trac.wxwidgets.org/ticket/18724 --- include/wx/dataview.h | 2 +- interface/wx/dataview.h | 7 ++- src/generic/datavgen.cpp | 120 ++++++++++++++++++++++----------------- src/gtk/dataview.cpp | 11 +--- 4 files changed, 74 insertions(+), 66 deletions(-) diff --git a/include/wx/dataview.h b/include/wx/dataview.h index 99b620d84d..e796ab46c7 100644 --- a/include/wx/dataview.h +++ b/include/wx/dataview.h @@ -208,7 +208,7 @@ public: // return true if the given item has a value to display in the given // column: this is always true except for container items which by default // only show their label in the first column (but see HasContainerColumns()) - bool HasValue(const wxDataViewItem& item, unsigned col) const + virtual bool HasValue(const wxDataViewItem& item, unsigned col) const { return col == 0 || !IsContainer(item) || HasContainerColumns(item); } diff --git a/interface/wx/dataview.h b/interface/wx/dataview.h index f9decd1a4c..f2857904e0 100644 --- a/interface/wx/dataview.h +++ b/interface/wx/dataview.h @@ -304,14 +304,17 @@ public: All normal items have values in all columns but the container items only show their label in the first column (@a col == 0) by default (but - see HasContainerColumns()). So this function always returns true for + see HasContainerColumns()). So this function by default returns true for the first column while for the other ones it returns true only if the item is not a container or HasContainerColumns() was overridden to return true for it. + Override this method to explicitly specify for which columns a given + item has values. + @since 2.9.1 */ - bool HasValue(const wxDataViewItem& item, unsigned col) const; + virtual bool HasValue(const wxDataViewItem& item, unsigned col) const; /** Override this to indicate of @a item is a container, i.e.\ if diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 7cf49aefa4..ef55a9f8c2 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -2394,15 +2394,17 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) if ( m_useCellFocus && m_currentCol && m_currentColSetByKeyboard ) { - renderColumnFocus = true; - - // If this is container node without columns, render full-row focus: - if ( !IsList() ) + // If this is an item with a single column, render full-row focus: + numColsWithValue = 0; + unsigned int cols = GetOwner()->GetColumnCount(); + for ( unsigned int i = 0; i < cols; i++ ) { - wxDataViewTreeNode *node = GetTreeNodeByRow(item); - if ( node->HasChildren() && !model->HasContainerColumns(node->GetItem()) ) - renderColumnFocus = false; + if ( model->HasValue(item, i) ) + numColsWithValue++; + if ( numColsWithValue > 1 ) + break; } + renderColumnFocus = numColsWithValue<2; } if ( renderColumnFocus ) @@ -2547,11 +2549,8 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) dataitem = node->GetItem(); - // Skip all columns of "container" rows except the expander - // column itself unless HasContainerColumns() overrides this. - if ( col != expander && - model->IsContainer(dataitem) && - !model->HasContainerColumns(dataitem) ) + // Skip al columns that do not have values + if ( !model->HasValue(dataitem, col->GetModelColumn()) ) { cell_rect.y += line_height; continue; @@ -3491,9 +3490,7 @@ int wxDataViewMainWindow::QueryAndCacheLineHeight(unsigned int row, wxDataViewIt if (column->IsHidden()) continue; // skip it! - if ((col != 0) && - model->IsContainer(item) && - !model->HasContainerColumns(item)) + if ( !model->HasValue(item, col) ) continue; // skip it! wxDataViewRenderer *renderer = @@ -4108,8 +4105,7 @@ wxDataViewMainWindow::FindColumnForEditing(const wxDataViewItem& item, wxDataVie // may be directly editable: if ( candidate && GetOwner()->GetExpanderColumn() != candidate && - GetModel()->IsContainer(item) && - !GetModel()->HasContainerColumns(item) ) + !GetModel()->HasValue(item, candidate->GetModelColumn()) ) { candidate = GetOwner()->GetExpanderColumn(); } @@ -4500,8 +4496,13 @@ bool wxDataViewMainWindow::TryAdvanceCurrentColumn(wxDataViewTreeNode *node, wxK if ( node ) { - // navigation shouldn't work in branch nodes without other columns: - if ( node->HasChildren() && !GetModel()->HasContainerColumns(node->GetItem()) ) + // navigation shouldn't work in nodes with fewer than two columns + numColsWithValue = 0; + unsigned int cols = GetOwner()->GetColumnCount(); + for ( unsigned int i = 0; i < cols; i++ ) + if ( GetModel()->HasValue(node->GetItem(), i) ) + numColsWithValue++; + if (numColsWithValue<2) return false; } @@ -4509,7 +4510,13 @@ bool wxDataViewMainWindow::TryAdvanceCurrentColumn(wxDataViewTreeNode *node, wxK { if ( forward ) { - m_currentCol = GetOwner()->GetColumnAt(0); + // find first column with value + unsigned int i = 0; + unsigned int cols = GetOwner()->GetColumnCount(); + for ( ; i < cols; i++ ) + if ( GetModel()->HasValue(node->GetItem(), i) ) + break; + m_currentCol = GetOwner()->GetColumnAt(i); m_currentColSetByKeyboard = true; RefreshRow(m_currentRow); return true; @@ -4521,41 +4528,49 @@ bool wxDataViewMainWindow::TryAdvanceCurrentColumn(wxDataViewTreeNode *node, wxK } } - int idx = GetOwner()->GetColumnIndex(m_currentCol) + (forward ? +1 : -1); - - if ( idx >= (int)GetOwner()->GetColumnCount() ) + int idx = GetOwner()->GetColumnIndex(m_currentCol); + unsigned int cols = GetOwner()->GetColumnCount(); + for ( unsigned int i = 0; i < cols; i++ ) { - if ( !wrapAround ) - return false; + idx += (forward ? +1 : -1); + if ( idx >= (int)GetOwner()->GetColumnCount() ) + { + if ( !wrapAround ) + return false; - if ( GetCurrentRow() < GetRowCount() - 1 ) - { - // go to the first column of the next row: - idx = 0; - OnVerticalNavigation(wxKeyEvent()/*dummy*/, +1); + if ( GetCurrentRow() < GetRowCount() - 1 ) + { + // go to the first column of the next row: + idx = 0; + OnVerticalNavigation(wxKeyEvent()/*dummy*/, +1); + } + else + { + // allow focus change + event.Skip(); + return false; + } } - else + else if ( idx < 0 ) { - // allow focus change - event.Skip(); - return false; - } - } + if ( !wrapAround ) + return false; - if ( idx < 0 && wrapAround ) - { - if ( GetCurrentRow() > 0 ) - { - // go to the last column of the previous row: - idx = (int)GetOwner()->GetColumnCount() - 1; - OnVerticalNavigation(wxKeyEvent()/*dummy*/, -1); - } - else - { - // allow focus change - event.Skip(); - return false; + if ( GetCurrentRow() > 0 ) + { + // go to the last column of the previous row: + idx = col_last-1; + OnVerticalNavigation(wxKeyEvent()/*dummy*/, -1); + } + else + { + // allow focus change + event.Skip(); + return false; + } } + if ( GetModel()->HasValue(node->GetItem(), i) ) + break; } GetOwner()->EnsureVisibleRowCol(m_currentRow, idx); @@ -4767,9 +4782,8 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) } bool ignore_other_columns = - ((expander != col) && - (model->IsContainer(item)) && - (!model->HasContainerColumns(item))); + (expander != col) && + (!model->HasValue(item, col->GetModelColumn())); if (event.LeftDClick()) { @@ -6495,7 +6509,7 @@ wxAccStatus wxDataViewCtrlAccessible::GetDescription(int childId, wxString* desc const unsigned int numCols = dvCtrl->GetColumnCount(); for ( unsigned int col = 0; col < numCols; col++ ) { - if ( model->IsContainer(item) && !model->HasContainerColumns(item) ) + if ( !model->HasValue(item, col) ) continue; // skip it wxDataViewColumn *dvCol = dvCtrl->GetColumnAt(col); diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 17c68517b5..b8ed3c8f3d 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -3146,16 +3146,7 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *WXUNUSED(column), if (!wx_model->IsVirtualListModel()) { - gboolean visible; - if (wx_model->IsContainer( item )) - { - visible = wx_model->HasContainerColumns( item ) || (column == 0); - } - else - { - visible = true; - } - + gboolean visible = wx_model->HasValue(item, column); GValue gvalue = G_VALUE_INIT; g_value_init( &gvalue, G_TYPE_BOOLEAN ); g_value_set_boolean( &gvalue, visible );