From 334ff407166bc6635d1bd47d921b4715d7dc7a8b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 15 Dec 2019 19:17:10 +0100 Subject: [PATCH 1/3] Show wxDataViewCheckIconTextRenderer in the sample Instead of using separate check and icon+text columns in the list model page, use the combined check+icon+text column to verify that it works (which is not the case current in the native Mac version). --- samples/dataview/dataview.cpp | 19 +++++++--------- samples/dataview/mymodels.cpp | 42 ++++++++++++++--------------------- samples/dataview/mymodels.h | 10 +++------ 3 files changed, 28 insertions(+), 43 deletions(-) diff --git a/samples/dataview/dataview.cpp b/samples/dataview/dataview.cpp index b879d3e7d8..e7a00ab617 100644 --- a/samples/dataview/dataview.cpp +++ b/samples/dataview/dataview.cpp @@ -833,24 +833,21 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l m_list_model = new MyListModel; m_ctrl[Page_List]->AssociateModel( m_list_model.get() ); - m_ctrl[Page_List]->AppendToggleColumn(L"\u2714", - MyListModel::Col_Toggle, - wxDATAVIEW_CELL_ACTIVATABLE, - wxCOL_WIDTH_AUTOSIZE); + wxDataViewColumn* const colCheckIconText = new wxDataViewColumn + ( + L"\u2714 + icon + text", + new wxDataViewCheckIconTextRenderer(), + MyListModel::Col_ToggleIconText, + wxCOL_WIDTH_AUTOSIZE + ); + m_ctrl[Page_List]->AppendColumn(colCheckIconText); - // the various columns m_ctrl[Page_List]->AppendTextColumn("editable string", MyListModel::Col_EditableText, wxDATAVIEW_CELL_EDITABLE, wxCOL_WIDTH_AUTOSIZE, wxALIGN_NOT, wxDATAVIEW_COL_SORTABLE); - m_ctrl[Page_List]->AppendIconTextColumn("icon", - MyListModel::Col_IconText, - wxDATAVIEW_CELL_EDITABLE, - wxCOL_WIDTH_AUTOSIZE, - wxALIGN_NOT, - wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_SORTABLE); m_ctrl[Page_List]->AppendDateColumn("date", MyListModel::Col_Date); diff --git a/samples/dataview/mymodels.cpp b/samples/dataview/mymodels.cpp index e6ee751299..75f375d817 100644 --- a/samples/dataview/mymodels.cpp +++ b/samples/dataview/mymodels.cpp @@ -437,13 +437,6 @@ void MyListModel::GetValueByRow( wxVariant &variant, { switch ( col ) { - case Col_Toggle: - if (row >= m_toggleColValues.size()) - variant = false; - else - variant = m_toggleColValues[row]; - break; - case Col_EditableText: if (row >= m_textColValues.GetCount()) variant = wxString::Format( "virtual row %d", row ); @@ -451,15 +444,22 @@ void MyListModel::GetValueByRow( wxVariant &variant, variant = m_textColValues[ row ]; break; - case Col_IconText: + case Col_ToggleIconText: { wxString text; + wxCheckBoxState state; if ( row >= m_iconColValues.GetCount() ) + { text = "virtual icon"; + state = wxCHK_UNDETERMINED; + } else + { text = m_iconColValues[row]; + state = m_toggleColValues[row] ? wxCHK_CHECKED : wxCHK_UNCHECKED; + } - variant << wxDataViewIconText(text, m_icon[row % 2]); + variant << wxDataViewCheckIconText(text, m_icon[row % 2], state); } break; @@ -505,9 +505,6 @@ bool MyListModel::GetAttrByRow( unsigned int row, unsigned int col, { switch ( col ) { - case Col_Toggle: - return false; - case Col_EditableText: case Col_Date: if (row < m_toggleColValues.size()) @@ -521,7 +518,7 @@ bool MyListModel::GetAttrByRow( unsigned int row, unsigned int col, } return false; - case Col_IconText: + case Col_ToggleIconText: if ( !(row % 2) ) return false; attr.SetColour(*wxYELLOW); @@ -578,15 +575,8 @@ bool MyListModel::SetValueByRow( const wxVariant &variant, { switch ( col ) { - case Col_Toggle: - if (row >= m_toggleColValues.size()) - return false; - - m_toggleColValues[row] = variant.GetBool(); - return true; - case Col_EditableText: - case Col_IconText: + case Col_ToggleIconText: if (row >= m_textColValues.GetCount()) { // the item is not in the range of the items @@ -600,11 +590,13 @@ bool MyListModel::SetValueByRow( const wxVariant &variant, { m_textColValues[row] = variant.GetString(); } - else // col == Col_IconText + else // col == Col_ToggleIconText { - wxDataViewIconText iconText; - iconText << variant; - m_iconColValues[row] = iconText.GetText(); + wxDataViewCheckIconText checkIconText; + checkIconText << variant; + m_toggleColValues[row] = + checkIconText.GetCheckedState() == wxCHK_CHECKED; + m_iconColValues[row] = checkIconText.GetText(); } return true; diff --git a/samples/dataview/mymodels.h b/samples/dataview/mymodels.h index 3a7f5735da..8cab532f1f 100644 --- a/samples/dataview/mymodels.h +++ b/samples/dataview/mymodels.h @@ -208,9 +208,8 @@ class MyListModel: public wxDataViewVirtualListModel public: enum { - Col_Toggle, + Col_ToggleIconText, Col_EditableText, - Col_IconText, Col_Date, Col_TextWithAttr, Col_Custom, @@ -236,11 +235,8 @@ public: virtual wxString GetColumnType( unsigned int col ) const wxOVERRIDE { - if (col == Col_Toggle) - return "bool"; - - if (col == Col_IconText) - return "wxDataViewIconText"; + if (col == Col_ToggleIconText) + return wxDataViewCheckIconTextRenderer::GetDefaultType(); return "string"; } From 7fa1afafc263089ddeea201e1bf84f7da6bb1c34 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 15 Dec 2019 19:18:07 +0100 Subject: [PATCH 2/3] Re-add support for icons to Mac wxDataViewCheckIconTextRenderer Icons were not supported any longer since the switch to the native implementation in 235e61c311ee1cc3c74a637984ca40b4ed773ae2. Restore them now by using text attachments (thanks to Scott B for the idea). The vertical alignment is still not right, but it's better than nothing. See #17473. --- src/osx/cocoa/dataview.mm | 41 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/osx/cocoa/dataview.mm b/src/osx/cocoa/dataview.mm index 86c6b0468b..6ad23b57a1 100644 --- a/src/osx/cocoa/dataview.mm +++ b/src/osx/cocoa/dataview.mm @@ -3426,7 +3426,46 @@ bool wxDataViewCheckIconTextRenderer::MacRender() break; } [cell setIntValue:nativecbvalue]; - [cell setTitle:wxCFStringRef(checkIconText.GetText()).AsNSString()]; + + const wxCFStringRef textString(checkIconText.GetText()); + + const wxIcon& icon = checkIconText.GetIcon(); + if ( icon.IsOk() ) + { + NSTextAttachmentCell* const attachmentCell = + [[NSTextAttachmentCell alloc] initImageCell: icon.GetNSImage()]; + NSTextAttachment* const attachment = [NSTextAttachment new]; + [attachment setAttachmentCell: attachmentCell]; + + // Note: this string is released by the autorelease pool and must not + // be released manually below. + NSAttributedString* const iconString = + [NSAttributedString attributedStringWithAttachment: attachment]; + + NSAttributedString* const separatorString = + [[NSAttributedString alloc] initWithString: @" "]; + + NSAttributedString* const textAttrString = + [[NSAttributedString alloc] initWithString: textString.AsNSString()]; + + NSMutableAttributedString* const fullString = + [NSMutableAttributedString new]; + [fullString appendAttributedString: iconString]; + [fullString appendAttributedString: separatorString]; + [fullString appendAttributedString: textAttrString]; + + [cell setAttributedTitle: fullString]; + + [fullString release]; + [separatorString release]; + [textAttrString release]; + [attachment release]; + [attachmentCell release]; + } + else + { + [cell setTitle: textString.AsNSString()]; + } return true; } From df6304caa69164eeaa2969c28afd6b33e175bce8 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Mon, 16 Dec 2019 16:28:08 +0100 Subject: [PATCH 3/3] add baselineOffset override to better align icons Cocoa by default aligns the cell on the text baseline, which is not suitable for our needs, solved by subclassing NSTextAttachmentCell --- src/osx/cocoa/dataview.mm | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/osx/cocoa/dataview.mm b/src/osx/cocoa/dataview.mm index 6ad23b57a1..7041b5bcd1 100644 --- a/src/osx/cocoa/dataview.mm +++ b/src/osx/cocoa/dataview.mm @@ -3404,6 +3404,25 @@ void wxDataViewCheckIconTextRenderer::Allow3rdStateForUser(bool allow) m_allow3rdStateForUser = allow; } +@interface wxNSTextAttachmentCellWithBaseline : NSTextAttachmentCell +{ +NSPoint _offset; +} +@end + +@implementation wxNSTextAttachmentCellWithBaseline + +- (void) setCellBaselineOffset:(NSPoint) offset +{ + _offset=offset; +} +- (NSPoint)cellBaselineOffset +{ + return _offset; +} + +@end + bool wxDataViewCheckIconTextRenderer::MacRender() { wxDataViewCheckIconText checkIconText; @@ -3432,8 +3451,8 @@ bool wxDataViewCheckIconTextRenderer::MacRender() const wxIcon& icon = checkIconText.GetIcon(); if ( icon.IsOk() ) { - NSTextAttachmentCell* const attachmentCell = - [[NSTextAttachmentCell alloc] initImageCell: icon.GetNSImage()]; + wxNSTextAttachmentCellWithBaseline* const attachmentCell = + [[wxNSTextAttachmentCellWithBaseline alloc] initImageCell: icon.GetNSImage()]; NSTextAttachment* const attachment = [NSTextAttachment new]; [attachment setAttachmentCell: attachmentCell]; @@ -3450,6 +3469,8 @@ bool wxDataViewCheckIconTextRenderer::MacRender() NSMutableAttributedString* const fullString = [NSMutableAttributedString new]; + [attachmentCell setCellBaselineOffset: NSMakePoint(0.0, -5.0)]; + [fullString appendAttributedString: iconString]; [fullString appendAttributedString: separatorString]; [fullString appendAttributedString: textAttrString];