From 47794945b5c834ca29a34ca0e27afec6c907a062 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Sat, 6 Feb 2016 17:09:36 +0100 Subject: [PATCH 1/6] Fixed compiling with MSVC. --- src/generic/listctrl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index 5551dc0627..3b48b76c36 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -46,7 +46,7 @@ #endif #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) - #define "wx/msw/wrapwin.h" + #include "wx/msw/wrapwin.h" #endif // NOTE: If using the wxListBox visual attributes works everywhere then this can @@ -4589,7 +4589,7 @@ void wxGenericListCtrl::CreateOrDestroyHeaderWindowAsNeeded() ), wxTAB_TRAVERSAL ); - + #if defined( __WXMAC__ ) static wxFont font( wxOSX_SYSTEM_FONT_SMALL ); m_headerWin->SetFont( font ); From 415292c61457a86791881061fa0425b9f6be9961 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Sat, 6 Feb 2016 17:12:56 +0100 Subject: [PATCH 2/6] Implemented logic. --- include/wx/generic/listctrl.h | 5 ++ include/wx/generic/private/listctrl.h | 12 +++++ src/generic/listctrl.cpp | 68 +++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) diff --git a/include/wx/generic/listctrl.h b/include/wx/generic/listctrl.h index 454ce5b378..d706cb813e 100644 --- a/include/wx/generic/listctrl.h +++ b/include/wx/generic/listctrl.h @@ -101,6 +101,11 @@ public: void SetTextColour(const wxColour& col); long GetTopItem() const; + virtual bool HasCheckboxes() const wxOVERRIDE; + virtual bool EnableCheckboxes(bool enable = true) wxOVERRIDE; + virtual bool IsItemChecked(long item) const wxOVERRIDE; + virtual void CheckItem(long item, bool check) wxOVERRIDE; + void SetSingleStyle( long style, bool add = true ) ; void SetWindowStyleFlag( long style ) wxOVERRIDE; void RecreateWindow() {} diff --git a/include/wx/generic/private/listctrl.h b/include/wx/generic/private/listctrl.h index 72f1727765..7c13269955 100644 --- a/include/wx/generic/private/listctrl.h +++ b/include/wx/generic/private/listctrl.h @@ -200,6 +200,8 @@ public: // is this item selected? [NB: not used in virtual mode] bool m_highlighted; + bool m_checked; + // back pointer to the list ctrl wxListMainWindow *m_owner; @@ -249,6 +251,9 @@ public: void SetImage( int index, int image ); int GetImage( int index ) const; + void Check(bool check) {m_checked = check; } + bool IsChecked() { return m_checked; } + bool HasImage() const { return GetImage() != -1; } bool HasText() const { return !GetText(0).empty(); } @@ -636,6 +641,11 @@ public: bool GetItemPosition( long item, wxPoint& pos ) const; int GetSelectedItemCount() const; + bool HasCheckboxes() const; + bool EnableCheckboxes(bool enable = true); + bool IsItemChecked(long item) const; + void CheckItem(long item, bool check); + wxString GetItemText(long item, int col = 0) const { wxListItem info; @@ -779,6 +789,8 @@ protected: m_lineBeforeLastClicked, m_lineSelectSingleOnUp; + bool m_hasCheckboxes; + protected: wxWindow *GetMainWindowOfCompositeControl() wxOVERRIDE { return GetParent(); } diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index 3b48b76c36..93efcf2723 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -410,6 +410,7 @@ wxListLineData::wxListLineData( wxListMainWindow *owner ) m_gi = new GeometryInfo; m_highlighted = false; + m_checked = false; InitItems( GetMode() == wxLC_REPORT ? m_owner->GetColumnCount() : 1 ); } @@ -1588,6 +1589,8 @@ void wxListMainWindow::Init() m_lineLastClicked = m_lineSelectSingleOnUp = m_lineBeforeLastClicked = (size_t)-1; + + m_hasCheckboxes = false; } wxListMainWindow::wxListMainWindow() @@ -3673,6 +3676,41 @@ bool wxListMainWindow::GetItemPosition(long item, wxPoint& pos) const return true; } +// ---------------------------------------------------------------------------- +// checkboxes +// ---------------------------------------------------------------------------- + + +bool wxListMainWindow::HasCheckboxes() const +{ + return m_hasCheckboxes; +} + +bool wxListMainWindow::EnableCheckboxes(bool enable) +{ + m_hasCheckboxes = enable; + Refresh(); + + return true; +} + +void wxListMainWindow::CheckItem(long item, bool state) +{ + wxListLineData *line = GetLine((size_t)item); + line->Check(state); + + RefreshLine(item); + + SendNotify(item, state ? wxEVT_LIST_ITEM_CHECKED + : wxEVT_LIST_ITEM_UNCHECKED); +} + +bool wxListMainWindow::IsItemChecked(long item) const +{ + wxListLineData *line = GetLine((size_t)item); + return line->IsChecked(); +} + // ---------------------------------------------------------------------------- // geometry calculation // ---------------------------------------------------------------------------- @@ -4691,6 +4729,36 @@ void wxGenericListCtrl::OnScroll(wxScrollWinEvent& event) event.Skip(); } +bool wxGenericListCtrl::HasCheckboxes() const +{ + if (!InReportView()) + return false; + + return m_mainWin->HasCheckboxes(); +} + +bool wxGenericListCtrl::EnableCheckboxes(bool enable) +{ + if (!InReportView()) + return false; + + return m_mainWin->EnableCheckboxes(enable); +} + +void wxGenericListCtrl::CheckItem(long item, bool state) +{ + if (InReportView()) + m_mainWin->CheckItem(item, state); +} + +bool wxGenericListCtrl::IsItemChecked(long item) const +{ + if (!InReportView()) + return false; + + return m_mainWin->IsItemChecked(item); +} + void wxGenericListCtrl::SetSingleStyle( long style, bool add ) { wxASSERT_MSG( !(style & wxLC_VIRTUAL), From 3b89a3c7c5f98c2f0d25265eb5062db6e0cdd471 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Sat, 6 Feb 2016 17:19:15 +0100 Subject: [PATCH 3/6] Implemented drawing checkboxes. --- src/generic/listctrl.cpp | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index 93efcf2723..0ee4531998 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -102,6 +102,8 @@ static const int IMAGE_MARGIN_IN_REPORT_MODE = 5; // the space between the image and the text in the report mode in header static const int HEADER_IMAGE_MARGIN_IN_REPORT_MODE = 2; +// space after a checkbox +static const int MARGIN_AFTER_CHECKBOX = 5; // ---------------------------------------------------------------------------- @@ -795,6 +797,19 @@ void wxListLineData::DrawInReportMode( wxDC *dc, x += 2; #endif + if (m_owner->HasCheckboxes()) { + wxSize cbSize = wxRendererNative::Get().GetCheckBoxSize(m_owner); + int yOffset = (rect.height - cbSize.GetHeight()) / 2; + wxRect rr(x, rect.y + yOffset, cbSize.GetWidth(), cbSize.GetHeight()); + + int flags = 0; + if (m_checked) + flags |= wxCONTROL_CHECKED; + wxRendererNative::Get().DrawCheckBox(m_owner, *dc, rr, flags); + + x += cbSize.GetWidth() + MARGIN_AFTER_CHECKBOX; + } + size_t col = 0; for ( wxListItemDataList::compatibility_iterator node = m_items.GetFirst(); node; @@ -803,6 +818,8 @@ void wxListLineData::DrawInReportMode( wxDC *dc, wxListItemData *item = node->GetData(); int width = m_owner->GetColumnWidth(col); + if (col == 0 && m_owner->HasCheckboxes()) + width -= x; int xOld = x; x += width; @@ -3680,7 +3697,6 @@ bool wxListMainWindow::GetItemPosition(long item, wxPoint& pos) const // checkboxes // ---------------------------------------------------------------------------- - bool wxListMainWindow::HasCheckboxes() const { return m_hasCheckboxes; @@ -3688,7 +3704,19 @@ bool wxListMainWindow::HasCheckboxes() const bool wxListMainWindow::EnableCheckboxes(bool enable) { + bool changed = enable != m_hasCheckboxes; m_hasCheckboxes = enable; + + if (changed) { + int cbWidth = wxRendererNative::Get().GetCheckBoxSize(this).GetWidth() + MARGIN_AFTER_CHECKBOX; + if (m_hasCheckboxes) + SetColumnWidth(0, GetColumnWidth(0) + cbWidth); + else + SetColumnWidth(0, GetColumnWidth(0) - cbWidth); + } + + m_dirty = true; + m_headerWidth = 0; Refresh(); return true; From 7dd65abaf76574619e24eae13638aad49de1aee7 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Sat, 6 Feb 2016 17:20:40 +0100 Subject: [PATCH 4/6] Implemented checking checkboxes. --- include/wx/generic/private/listctrl.h | 1 + src/generic/listctrl.cpp | 26 +++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/include/wx/generic/private/listctrl.h b/include/wx/generic/private/listctrl.h index 7c13269955..86cc91607a 100644 --- a/include/wx/generic/private/listctrl.h +++ b/include/wx/generic/private/listctrl.h @@ -850,6 +850,7 @@ private: // Compute the minimal width needed to fully display the column header. int ComputeMinHeaderWidth(const wxListHeaderData* header) const; + bool IsClickInsideCheckbox(long item, int x, int y); // the height of one line using the current font wxCoord m_lineHeight; diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index 0ee4531998..068acd5a1d 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -2579,11 +2579,18 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) { if ( IsSingleSel() || !IsHighlighted(current) ) { - HighlightAll( false ); + if (IsClickInsideCheckbox(current, x, y)) + { + CheckItem(current, !IsItemChecked(current)); + } + else + { + HighlightAll(false); - ChangeCurrent(current); + ChangeCurrent(current); - ReverseHighlight(m_current); + ReverseHighlight(m_current); + } } else // multi sel & current is highlighted & no mod keys { @@ -3739,6 +3746,19 @@ bool wxListMainWindow::IsItemChecked(long item) const return line->IsChecked(); } +bool wxListMainWindow::IsClickInsideCheckbox(long item, int x, int y) +{ + if (HasCheckboxes()) { + wxRect lineRect = GetLineRect(item); + wxSize cbSize = wxRendererNative::Get().GetCheckBoxSize(this); + int yOffset = (lineRect.height - cbSize.GetHeight()) / 2; + wxRect rr(0, lineRect.y + yOffset, cbSize.GetWidth(), cbSize.GetHeight()); + + return (rr.Contains(wxPoint(x, y))); + } + return false; +} + // ---------------------------------------------------------------------------- // geometry calculation // ---------------------------------------------------------------------------- From 9301692b688a06320d8404f59fb895aacdf09818 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Sat, 6 Feb 2016 17:30:29 +0100 Subject: [PATCH 5/6] Removed unneeded column width change to match msw behavior. --- src/generic/listctrl.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index 068acd5a1d..a5818503fa 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -3711,17 +3711,8 @@ bool wxListMainWindow::HasCheckboxes() const bool wxListMainWindow::EnableCheckboxes(bool enable) { - bool changed = enable != m_hasCheckboxes; m_hasCheckboxes = enable; - if (changed) { - int cbWidth = wxRendererNative::Get().GetCheckBoxSize(this).GetWidth() + MARGIN_AFTER_CHECKBOX; - if (m_hasCheckboxes) - SetColumnWidth(0, GetColumnWidth(0) + cbWidth); - else - SetColumnWidth(0, GetColumnWidth(0) - cbWidth); - } - m_dirty = true; m_headerWidth = 0; Refresh(); From dedda75b3a82ebd7dfe2683e08a63af8de9db0a0 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Sat, 6 Feb 2016 18:54:08 +0100 Subject: [PATCH 6/6] Fixed checking with multiple-selection enabled, added left offset. --- src/generic/listctrl.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index a5818503fa..61eaf730ee 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -103,7 +103,7 @@ static const int IMAGE_MARGIN_IN_REPORT_MODE = 5; static const int HEADER_IMAGE_MARGIN_IN_REPORT_MODE = 2; // space after a checkbox -static const int MARGIN_AFTER_CHECKBOX = 5; +static const int MARGIN_AROUND_CHECKBOX = 5; // ---------------------------------------------------------------------------- @@ -801,13 +801,14 @@ void wxListLineData::DrawInReportMode( wxDC *dc, wxSize cbSize = wxRendererNative::Get().GetCheckBoxSize(m_owner); int yOffset = (rect.height - cbSize.GetHeight()) / 2; wxRect rr(x, rect.y + yOffset, cbSize.GetWidth(), cbSize.GetHeight()); + rr.x += MARGIN_AROUND_CHECKBOX; int flags = 0; if (m_checked) flags |= wxCONTROL_CHECKED; wxRendererNative::Get().DrawCheckBox(m_owner, *dc, rr, flags); - x += cbSize.GetWidth() + MARGIN_AFTER_CHECKBOX; + x += cbSize.GetWidth() + (2 * MARGIN_AROUND_CHECKBOX); } size_t col = 0; @@ -2577,20 +2578,17 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) bool cmdModifierDown = event.CmdDown(); if ( IsSingleSel() || !(cmdModifierDown || event.ShiftDown()) ) { - if ( IsSingleSel() || !IsHighlighted(current) ) + if (IsClickInsideCheckbox(current, x, y)) { - if (IsClickInsideCheckbox(current, x, y)) - { - CheckItem(current, !IsItemChecked(current)); - } - else - { - HighlightAll(false); + CheckItem(current, !IsItemChecked(current)); + } + else if (IsSingleSel() || !IsHighlighted(current)) + { + HighlightAll(false); - ChangeCurrent(current); + ChangeCurrent(current); - ReverseHighlight(m_current); - } + ReverseHighlight(m_current); } else // multi sel & current is highlighted & no mod keys { @@ -3743,7 +3741,7 @@ bool wxListMainWindow::IsClickInsideCheckbox(long item, int x, int y) wxRect lineRect = GetLineRect(item); wxSize cbSize = wxRendererNative::Get().GetCheckBoxSize(this); int yOffset = (lineRect.height - cbSize.GetHeight()) / 2; - wxRect rr(0, lineRect.y + yOffset, cbSize.GetWidth(), cbSize.GetHeight()); + wxRect rr(MARGIN_AROUND_CHECKBOX, lineRect.y + yOffset, cbSize.GetWidth(), cbSize.GetHeight()); return (rr.Contains(wxPoint(x, y))); }