From bf30fa7490e2febcac152c404d357a11626e0143 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 24 Mar 2018 19:14:52 +0100 Subject: [PATCH 01/10] Include required headers explicitly in the widgets sample Don't rely on wx/treebook.h pulling in wx/treectrl.h and wx/textctrl.h, forward declare or include the headers declaring the classes from these headers explicitly where needed. --- samples/widgets/widgets.cpp | 1 + samples/widgets/widgets.h | 1 + 2 files changed, 2 insertions(+) diff --git a/samples/widgets/widgets.cpp b/samples/widgets/widgets.cpp index 90ac92a059..12e471fe26 100644 --- a/samples/widgets/widgets.cpp +++ b/samples/widgets/widgets.cpp @@ -49,6 +49,7 @@ #include "wx/numdlg.h" #include "wx/textdlg.h" #include "wx/imaglist.h" +#include "wx/treectrl.h" #include "wx/wupdlock.h" #include "wx/textcompleter.h" diff --git a/samples/widgets/widgets.h b/samples/widgets/widgets.h index b228fe110b..65d7708133 100644 --- a/samples/widgets/widgets.h +++ b/samples/widgets/widgets.h @@ -41,6 +41,7 @@ class WXDLLIMPEXP_FWD_CORE wxCheckBox; class WXDLLIMPEXP_FWD_CORE wxSizer; class WXDLLIMPEXP_FWD_CORE wxImageList; class WXDLLIMPEXP_FWD_CORE wxTextCtrl; +class WXDLLIMPEXP_FWD_CORE wxTextEntryBase; class WXDLLIMPEXP_FWD_CORE WidgetsBookCtrl; class WidgetsPageInfo; From bb492b99bd969629a52235fb8abbeb88d487a93a Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 24 Mar 2018 19:21:57 +0100 Subject: [PATCH 02/10] Don't include wx/treectrl.h from wx/treebook.h any more Remove an unnecessary header dependency. This is not completely backwards-compatible as it would break any code relying on getting e.g. wxTextCtrl declaration after including wx/treebook.h, but, hopefully, there shouldn't be that much such code out there and fixing it shouldn't be difficult. If either of these assumptions turns out to be false, this commit can always be reverted later. --- docs/changes.txt | 3 +++ include/wx/treebook.h | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/changes.txt b/docs/changes.txt index 423d79f114..1335498ddd 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -63,6 +63,9 @@ Changes in behaviour which may result in build errors This only affects code defining its own custom renderers, code just using wxGraphicsContext::CreatePen() continues to compile and work as before. +- wx/treebook.h doesn't include wx/treectrl.h (and, via it, wx/textctrl.h) any + more, include these headers explicitly from your code if necessary. + 3.1.2: (released 2018-??-??) ---------------------------- diff --git a/include/wx/treebook.h b/include/wx/treebook.h index 8661349c78..9e93d9cb2a 100644 --- a/include/wx/treebook.h +++ b/include/wx/treebook.h @@ -17,10 +17,11 @@ #include "wx/bookctrl.h" #include "wx/containr.h" -#include "wx/treectrl.h" // for wxArrayTreeItemIds +#include "wx/treebase.h" // for wxTreeItemId typedef wxWindow wxTreebookPage; +class WXDLLIMPEXP_FWD_CORE wxTreeCtrl; class WXDLLIMPEXP_FWD_CORE wxTreeEvent; // ---------------------------------------------------------------------------- From 058c085b21ff69225bdbc88f5553c2d824a129ce Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 24 Mar 2018 19:18:29 +0100 Subject: [PATCH 03/10] Use wxVector<> in wxTreebookPage implementation No real changes, just replace the use of a macro-based array with wxVector<>. --- include/wx/treebook.h | 5 +++-- src/generic/treebkg.cpp | 22 ++++++++++++---------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/include/wx/treebook.h b/include/wx/treebook.h index 9e93d9cb2a..abc95a87bc 100644 --- a/include/wx/treebook.h +++ b/include/wx/treebook.h @@ -18,6 +18,7 @@ #include "wx/bookctrl.h" #include "wx/containr.h" #include "wx/treebase.h" // for wxTreeItemId +#include "wx/vector.h" typedef wxWindow wxTreebookPage; @@ -150,7 +151,7 @@ protected: void OnTreeNodeExpandedCollapsed(wxTreeEvent& event); // array of page ids and page windows - wxArrayTreeItemIds m_treeIds; + wxVector m_treeIds; // in the situation when m_selection page is not wxNOT_FOUND but page is // NULL this is the first (sub)child that has a non-NULL page @@ -217,7 +218,7 @@ private: // Returns internal number of pages which can be different from // GetPageCount() while performing a page insertion or removal. - size_t DoInternalGetPageCount() const { return m_treeIds.GetCount(); } + size_t DoInternalGetPageCount() const { return m_treeIds.size(); } wxDECLARE_EVENT_TABLE(); diff --git a/src/generic/treebkg.cpp b/src/generic/treebkg.cpp index 7e3599564d..85d7158c93 100644 --- a/src/generic/treebkg.cpp +++ b/src/generic/treebkg.cpp @@ -32,6 +32,7 @@ #endif #include "wx/imaglist.h" +#include "wx/treectrl.h" // ---------------------------------------------------------------------------- // various wxWidgets macros @@ -140,7 +141,7 @@ bool wxTreebook::InsertSubPage(size_t pagePos, bool wxTreebook::AddPage(wxWindow *page, const wxString& text, bool bSelect, int imageId) { - return DoInsertPage(m_treeIds.GetCount(), page, text, bSelect, imageId); + return DoInsertPage(m_treeIds.size(), page, text, bSelect, imageId); } // insertion time is linear to the number of top-pages @@ -312,7 +313,7 @@ wxTreebookPage *wxTreebook::DoRemovePage(size_t pagePos) bool wxTreebook::DeleteAllPages() { wxBookCtrlBase::DeleteAllPages(); - m_treeIds.Clear(); + m_treeIds.clear(); m_selection = m_actualSelection = wxNOT_FOUND; @@ -326,20 +327,20 @@ void wxTreebook::DoInternalAddPage(size_t newPos, wxTreebookPage *page, wxTreeItemId pageId) { - wxASSERT_MSG( newPos <= m_treeIds.GetCount(), wxT("Ivalid index passed to wxTreebook::DoInternalAddPage") ); + wxASSERT_MSG( newPos <= m_treeIds.size(), wxT("Ivalid index passed to wxTreebook::DoInternalAddPage") ); // hide newly inserted page initially (it will be shown when selected) if ( page ) page->Hide(); - if ( newPos == m_treeIds.GetCount() ) + if ( newPos == m_treeIds.size() ) { // append - m_treeIds.Add(pageId); + m_treeIds.push_back(pageId); } else // insert { - m_treeIds.Insert(pageId, newPos); + m_treeIds.insert(m_treeIds.begin() + newPos, pageId); if ( m_selection != wxNOT_FOUND && newPos <= (size_t)m_selection ) { @@ -361,12 +362,13 @@ void wxTreebook::DoInternalRemovePageRange(size_t pagePos, size_t subCount) // Attention: this function is only for a situation when we delete a node // with all its children so pagePos is the node's index and subCount is the // node children count - wxASSERT_MSG( pagePos + subCount < m_treeIds.GetCount(), + wxASSERT_MSG( pagePos + subCount < m_treeIds.size(), wxT("Ivalid page index") ); wxTreeItemId pageId = m_treeIds[pagePos]; - m_treeIds.RemoveAt(pagePos, subCount + 1); + wxVector::iterator itPos = m_treeIds.begin() + pagePos; + m_treeIds.erase(itPos, itPos + subCount + 1); if ( m_selection != wxNOT_FOUND ) { @@ -454,7 +456,7 @@ void wxTreebook::DoUpdateSelection(bool bSelect, int newPos) wxTreeItemId wxTreebook::DoInternalGetPage(size_t pagePos) const { - if ( pagePos >= m_treeIds.GetCount() ) + if ( pagePos >= m_treeIds.size() ) { // invalid position but ok here, in this internal function, don't assert // (the caller will do it) @@ -466,7 +468,7 @@ wxTreeItemId wxTreebook::DoInternalGetPage(size_t pagePos) const int wxTreebook::DoInternalFindPageById(wxTreeItemId pageId) const { - const size_t count = m_treeIds.GetCount(); + const size_t count = m_treeIds.size(); for ( size_t i = 0; i < count; ++i ) { if ( m_treeIds[i] == pageId ) From 966dc44c7273791cc2dfdcbbc2b7090ceafcddd0 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 24 Mar 2018 19:41:18 +0100 Subject: [PATCH 04/10] Slightly simplify wxBookCtrlBase::DoSetSelection() No real changes, just simplify the check for whether the page change is allowed: we can assume it is by default, which means we don't have to test for SetSelection_SendEvent twice. --- src/common/bookctrl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/bookctrl.cpp b/src/common/bookctrl.cpp index 25498b0fa4..969ae07a70 100644 --- a/src/common/bookctrl.cpp +++ b/src/common/bookctrl.cpp @@ -479,7 +479,7 @@ int wxBookCtrlBase::DoSetSelection(size_t n, int flags) if ( n != (size_t)oldSel ) { wxBookCtrlEvent *event = CreatePageChangingEvent(); - bool allowed = false; + bool allowed = true; if ( flags & SetSelection_SendEvent ) { @@ -490,7 +490,7 @@ int wxBookCtrlBase::DoSetSelection(size_t n, int flags) allowed = !GetEventHandler()->ProcessEvent(*event) || event->IsAllowed(); } - if ( !(flags & SetSelection_SendEvent) || allowed) + if ( allowed ) { if ( oldSel != wxNOT_FOUND ) DoShowPage(m_pages[oldSel], false); From a3d0748a76c9181b3e0fd88e938f9796db7c121c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 24 Mar 2018 23:54:29 +0100 Subject: [PATCH 05/10] Fix typo in wxTreebook assert messages Fix recurring typo in "Invalid". No real changes. --- src/generic/treebkg.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/generic/treebkg.cpp b/src/generic/treebkg.cpp index 85d7158c93..5146bd7be2 100644 --- a/src/generic/treebkg.cpp +++ b/src/generic/treebkg.cpp @@ -327,7 +327,8 @@ void wxTreebook::DoInternalAddPage(size_t newPos, wxTreebookPage *page, wxTreeItemId pageId) { - wxASSERT_MSG( newPos <= m_treeIds.size(), wxT("Ivalid index passed to wxTreebook::DoInternalAddPage") ); + wxASSERT_MSG( newPos <= m_treeIds.size(), + wxT("Invalid index passed to wxTreebook::DoInternalAddPage") ); // hide newly inserted page initially (it will be shown when selected) if ( page ) @@ -363,7 +364,7 @@ void wxTreebook::DoInternalRemovePageRange(size_t pagePos, size_t subCount) // with all its children so pagePos is the node's index and subCount is the // node children count wxASSERT_MSG( pagePos + subCount < m_treeIds.size(), - wxT("Ivalid page index") ); + wxT("Invalid page index") ); wxTreeItemId pageId = m_treeIds[pagePos]; From af6a61e3a03f2f4f71a0a227ab2f984deb5be699 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 25 Mar 2018 00:07:00 +0100 Subject: [PATCH 06/10] Update wxBookCtrlBase::m_selection outside UpdateSelectedPage() Change m_selection in wxBookCtrlBase::DoSetSelection() itself instead of requiring all the derived class overriding do it in their overridden UpdateSelectedPage(). No real changes, this is just a small simplification. --- include/wx/choicebk.h | 3 +-- include/wx/simplebook.h | 5 +++-- src/common/bookctrl.cpp | 1 + src/generic/listbkg.cpp | 1 - src/generic/toolbkg.cpp | 1 - 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/include/wx/choicebk.h b/include/wx/choicebk.h index f32e8d3a0d..aca809932d 100644 --- a/include/wx/choicebk.h +++ b/include/wx/choicebk.h @@ -86,8 +86,7 @@ protected: void UpdateSelectedPage(size_t newsel) wxOVERRIDE { - m_selection = static_cast(newsel); - GetChoiceCtrl()->Select(m_selection); + GetChoiceCtrl()->Select(newsel); } wxBookCtrlEvent* CreatePageChangingEvent() const wxOVERRIDE; diff --git a/include/wx/simplebook.h b/include/wx/simplebook.h index 7e819700fc..fa859d3044 100644 --- a/include/wx/simplebook.h +++ b/include/wx/simplebook.h @@ -155,9 +155,10 @@ public: } protected: - virtual void UpdateSelectedPage(size_t newsel) wxOVERRIDE + virtual void UpdateSelectedPage(size_t WXUNUSED(newsel)) wxOVERRIDE { - m_selection = (int)newsel; + // Nothing to do here, but must be overridden to avoid the assert in + // the base class version. } virtual wxBookCtrlEvent* CreatePageChangingEvent() const wxOVERRIDE diff --git a/src/common/bookctrl.cpp b/src/common/bookctrl.cpp index 969ae07a70..e027fd9052 100644 --- a/src/common/bookctrl.cpp +++ b/src/common/bookctrl.cpp @@ -500,6 +500,7 @@ int wxBookCtrlBase::DoSetSelection(size_t n, int flags) DoShowPage(page, true); // change selection now to ignore the selection change event + m_selection = n; UpdateSelectedPage(n); if ( flags & SetSelection_SendEvent ) diff --git a/src/generic/listbkg.cpp b/src/generic/listbkg.cpp index a7f9229d5e..93084375a1 100644 --- a/src/generic/listbkg.cpp +++ b/src/generic/listbkg.cpp @@ -293,7 +293,6 @@ void wxListbook::SetImageList(wxImageList *imageList) void wxListbook::UpdateSelectedPage(size_t newsel) { - m_selection = newsel; GetListView()->Select(newsel); GetListView()->Focus(newsel); } diff --git a/src/generic/toolbkg.cpp b/src/generic/toolbkg.cpp index 40ea3a99c2..07cd9fa962 100644 --- a/src/generic/toolbkg.cpp +++ b/src/generic/toolbkg.cpp @@ -197,7 +197,6 @@ void wxToolbook::MakeChangedEvent(wxBookCtrlEvent &event) void wxToolbook::UpdateSelectedPage(size_t newsel) { - m_selection = newsel; GetToolBar()->ToggleTool(newsel + 1, true); } From 02a92e23f35fe183901273ddfca2d6d604b921da Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 25 Mar 2018 00:13:15 +0100 Subject: [PATCH 07/10] Reuse wxBookCtrlBase::DoSetSelection() in wxTreebook too Avoid duplicating base class DoSetSelection() implementation in wxTreebook, just extend it slightly by using DoGetNonNullPage() to allow using a (sub-)page if the page associated to the selected item is null and reuse it. Also get rid of wxTreebook::m_actualSelection, it seems completely unnecessary to bother keeping and updating it when we can just find it whenever we need (which actually seems to only have been the case in the now removed DoSetSelection() implementation anyhow). As a side effect of this, wxTreebook pages should now be sizer correctly when switching to them as DoSetSelection() in the base class does call SetSize() on the page before showing it, unlike the previously used version in wxTreebook, which omitted this call for some reason. There should be no other user-visible changes. Closes #4379. --- include/wx/bookctrl.h | 6 ++ include/wx/treebook.h | 24 ++----- src/common/bookctrl.cpp | 13 +++- src/generic/treebkg.cpp | 139 +++++++++------------------------------- 4 files changed, 53 insertions(+), 129 deletions(-) diff --git a/include/wx/bookctrl.h b/include/wx/bookctrl.h index aad4834a55..963de7a91a 100644 --- a/include/wx/bookctrl.h +++ b/include/wx/bookctrl.h @@ -292,6 +292,12 @@ protected: // having nodes without any associated page) virtual bool AllowNullPage() const { return false; } + // For classes that allow null pages, we also need a way to find the + // closest non-NULL page corresponding to the given index, e.g. the first + // leaf item in wxTreebook tree and this method must be overridden to + // return it if AllowNullPage() is overridden. + virtual wxWindow *DoGetNonNullPage(size_t page) { return m_pages[page]; } + // Remove the page and return a pointer to it. // // It also needs to update the current selection if necessary, i.e. if the diff --git a/include/wx/treebook.h b/include/wx/treebook.h index abc95a87bc..119eb7dddd 100644 --- a/include/wx/treebook.h +++ b/include/wx/treebook.h @@ -38,7 +38,6 @@ public: // Default ctor doesn't create the control, use Create() afterwards wxTreebook() { - Init(); } // This ctor creates the tree book control @@ -49,8 +48,6 @@ public: long style = wxBK_DEFAULT, const wxString& name = wxEmptyString) { - Init(); - (void)Create(parent, id, pos, size, style, name); } @@ -145,22 +142,16 @@ protected: // This subclass of wxBookCtrlBase accepts NULL page pointers (empty pages) virtual bool AllowNullPage() const wxOVERRIDE { return true; } + virtual wxWindow *DoGetNonNullPage(size_t page) wxOVERRIDE; // event handlers void OnTreeSelectionChange(wxTreeEvent& event); void OnTreeNodeExpandedCollapsed(wxTreeEvent& event); - // array of page ids and page windows + // array of tree item ids corresponding to the page indices wxVector m_treeIds; - // in the situation when m_selection page is not wxNOT_FOUND but page is - // NULL this is the first (sub)child that has a non-NULL page - int m_actualSelection; - private: - // common part of all constructors - void Init(); - // The real implementations of page insertion functions // ------------------------------------------------------ // All DoInsert/Add(Sub)Page functions add the page into : @@ -182,12 +173,11 @@ private: bool bSelect = false, int imageId = NO_IMAGE); - // Sets selection in the tree control and updates the page being shown. - int DoSetSelection(size_t pos, int flags = 0) wxOVERRIDE; - - // Returns currently shown page. In a case when selected the node - // has empty (NULL) page finds first (sub)child with not-empty page. - wxTreebookPage *DoGetCurrentPage() const; + // Overridden methods used by the base class DoSetSelection() + // implementation. + void UpdateSelectedPage(size_t newsel) wxOVERRIDE; + wxBookCtrlEvent* CreatePageChangingEvent() const wxOVERRIDE; + void MakeChangedEvent(wxBookCtrlEvent &event) wxOVERRIDE; // Does the selection update. Called from page insertion functions // to update selection if the selected page was pushed by the newly inserted diff --git a/src/common/bookctrl.cpp b/src/common/bookctrl.cpp index e027fd9052..c2dde5fcfe 100644 --- a/src/common/bookctrl.cpp +++ b/src/common/bookctrl.cpp @@ -493,9 +493,9 @@ int wxBookCtrlBase::DoSetSelection(size_t n, int flags) if ( allowed ) { if ( oldSel != wxNOT_FOUND ) - DoShowPage(m_pages[oldSel], false); + DoShowPage(DoGetNonNullPage(oldSel), false); - wxWindow *page = m_pages[n]; + wxWindow* const page = DoGetNonNullPage(n); page->SetSize(GetPageRect()); DoShowPage(page, true); @@ -510,6 +510,15 @@ int wxBookCtrlBase::DoSetSelection(size_t n, int flags) (void)GetEventHandler()->ProcessEvent(*event); } } + else + { + // Selection in the control might have already had changed. + if ( oldSel != wxNOT_FOUND ) + { + m_selection = oldSel; + UpdateSelectedPage(oldSel); + } + } delete event; } diff --git a/src/generic/treebkg.cpp b/src/generic/treebkg.cpp index 5146bd7be2..0abc57f62c 100644 --- a/src/generic/treebkg.cpp +++ b/src/generic/treebkg.cpp @@ -66,12 +66,6 @@ wxEND_EVENT_TABLE() // wxTreebook creation // ---------------------------------------------------------------------------- -void wxTreebook::Init() -{ - m_selection = - m_actualSelection = wxNOT_FOUND; -} - bool wxTreebook::Create(wxWindow *parent, wxWindowID id, @@ -314,8 +308,6 @@ bool wxTreebook::DeleteAllPages() { wxBookCtrlBase::DeleteAllPages(); m_treeIds.clear(); - m_selection = - m_actualSelection = wxNOT_FOUND; wxTreeCtrl *tree = GetTreeCtrl(); tree->DeleteChildren(tree->GetRootItem()); @@ -347,13 +339,6 @@ void wxTreebook::DoInternalAddPage(size_t newPos, { // selection has been moved one unit toward the end ++m_selection; - if ( m_actualSelection != wxNOT_FOUND ) - ++m_actualSelection; - } - else if ( m_actualSelection != wxNOT_FOUND && - newPos <= (size_t)m_actualSelection ) - { - DoSetSelection(m_selection); } } } @@ -377,10 +362,6 @@ void wxTreebook::DoInternalRemovePageRange(size_t pagePos, size_t subCount) { // selection is far after the deleted page, so just update the index and move on m_selection -= 1 + subCount; - if ( m_actualSelection != wxNOT_FOUND) - { - m_actualSelection -= subCount + 1; - } } else if ( (size_t)m_selection >= pagePos ) { @@ -391,7 +372,6 @@ void wxTreebook::DoInternalRemovePageRange(size_t pagePos, size_t subCount) wxTreeItemId nodeId = tree->GetNextSibling(pageId); m_selection = wxNOT_FOUND; - m_actualSelection = wxNOT_FOUND; if ( nodeId.IsOk() ) { @@ -413,17 +393,6 @@ void wxTreebook::DoInternalRemovePageRange(size_t pagePos, size_t subCount) } } } - else if ( m_actualSelection != wxNOT_FOUND && - (size_t)m_actualSelection >= pagePos ) - { - // nothing to do -- selection is before the deleted node, but - // actually shown page (the first (sub)child with page != NULL) is - // already deleted - m_actualSelection = m_selection; - - // send event as documented - DoSetSelection(m_selection, SetSelection_SendEvent); - } //else: nothing to do -- selection is before the deleted node } else @@ -558,91 +527,41 @@ bool wxTreebook::SetPageImage(size_t n, int imageId) return true; } -int wxTreebook::DoSetSelection(size_t pagePos, int flags) +void wxTreebook::UpdateSelectedPage(size_t newsel) { - wxCHECK_MSG( IS_VALID_PAGE(pagePos), wxNOT_FOUND, - wxT("invalid page index in wxListbook::DoSetSelection()") ); - wxASSERT_MSG( GetPageCount() == DoInternalGetPageCount(), - wxT("wxTreebook logic error: m_treeIds and m_pages not in sync!")); - - wxBookCtrlEvent event(wxEVT_TREEBOOK_PAGE_CHANGING, m_windowId); - const int oldSel = m_selection; - wxTreeCtrl *tree = GetTreeCtrl(); - bool allowed = false; - - if (flags & SetSelection_SendEvent) - { - event.SetEventObject(this); - event.SetSelection(pagePos); - event.SetOldSelection(m_selection); - - // don't send the event if the old and new pages are the same; do send it - // otherwise and be prepared for it to be vetoed - allowed = (int)pagePos == m_selection || - !GetEventHandler()->ProcessEvent(event) || - event.IsAllowed(); - } - - if ( !(flags & SetSelection_SendEvent) || allowed ) - { - // hide the previously shown page - wxTreebookPage * const oldPage = DoGetCurrentPage(); - if ( oldPage ) - oldPage->Hide(); - - // then show the new one - m_selection = pagePos; - wxTreebookPage *page = wxBookCtrlBase::GetPage(m_selection); - if ( !page ) - { - // find the next page suitable to be shown: the first (grand)child - // of this one with a non-NULL associated page - wxTreeItemId childId = m_treeIds[pagePos]; - int actualPagePos = pagePos; - while ( !page && childId.IsOk() ) - { - wxTreeItemIdValue cookie; - childId = tree->GetFirstChild( childId, cookie ); - if ( childId.IsOk() ) - { - page = wxBookCtrlBase::GetPage(++actualPagePos); - } - } - - m_actualSelection = page ? actualPagePos : m_selection; - } - - if ( page ) - page->Show(); - - tree->SelectItem(DoInternalGetPage(pagePos)); - - if (flags & SetSelection_SendEvent) - { - // notify about the (now completed) page change - event.SetEventType(wxEVT_TREEBOOK_PAGE_CHANGED); - (void)GetEventHandler()->ProcessEvent(event); - } - } - else if ( (flags & SetSelection_SendEvent) && !allowed) // page change vetoed - { - // tree selection might have already had changed - if ( oldSel != wxNOT_FOUND ) - tree->SelectItem(DoInternalGetPage(oldSel)); - } - - return oldSel; + GetTreeCtrl()->SelectItem(DoInternalGetPage(newsel)); } -wxTreebookPage *wxTreebook::DoGetCurrentPage() const +wxBookCtrlEvent* wxTreebook::CreatePageChangingEvent() const { - if ( m_selection == wxNOT_FOUND ) - return NULL; + return new wxBookCtrlEvent(wxEVT_TREEBOOK_PAGE_CHANGING, m_windowId); +} - wxTreebookPage *page = wxBookCtrlBase::GetPage(m_selection); - if ( !page && m_actualSelection != wxNOT_FOUND ) +void wxTreebook::MakeChangedEvent(wxBookCtrlEvent &event) +{ + event.SetEventType(wxEVT_TREEBOOK_PAGE_CHANGED); +} + +wxWindow *wxTreebook::DoGetNonNullPage(size_t n) +{ + wxWindow* page = wxBookCtrlBase::GetPage(n); + + if ( !page ) { - page = wxBookCtrlBase::GetPage(m_actualSelection); + // Find the next suitable page, i.e. the first (grand)child + // of this one with a non-NULL associated page + wxTreeCtrl* const tree = GetTreeCtrl(); + for ( wxTreeItemId childId = m_treeIds[n]; childId.IsOk(); ) + { + wxTreeItemIdValue cookie; + childId = tree->GetFirstChild( childId, cookie ); + if ( childId.IsOk() ) + { + page = wxBookCtrlBase::GetPage(++n); + if ( page ) + break; + } + } } return page; From 96f9a1289878570e3d5104252d6da660f11d8459 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 25 Mar 2018 00:19:57 +0100 Subject: [PATCH 08/10] Stop resizing widgets sample pages when first showing them The size of wxBookCtrl pages is determined by wxBookCtrl and can't be changed, yet the sample tried to do it, making them larger than the actually available space and cutting them off as the result. Just stop doing this and simply layout the page using the available space -- if there is not enough of it, that's too bad, but the user can always resize the main window in this case. See #4379. --- samples/widgets/widgets.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/samples/widgets/widgets.cpp b/samples/widgets/widgets.cpp index 12e471fe26..2b5dfe9082 100644 --- a/samples/widgets/widgets.cpp +++ b/samples/widgets/widgets.cpp @@ -724,20 +724,7 @@ void WidgetsFrame::OnPageChanged(WidgetsBookCtrlEvent& event) { wxWindowUpdateLocker noUpdates(curPage); curPage->CreateContent(); - //curPage->Layout(); - curPage->GetSizer()->Fit(curPage); - - WidgetsBookCtrl *book = wxStaticCast(curPage->GetParent(), WidgetsBookCtrl); - wxSize size; - for ( size_t i = 0; i < book->GetPageCount(); ++i ) - { - wxWindow *page = book->GetPage(i); - if ( page ) - { - size.IncTo(page->GetSize()); - } - } - curPage->SetSize(size); + curPage->Layout(); } // re-apply the attributes to the widget(s) curPage->SetUpWidget(); From 3d37b8c72a1abb9abacee74b1f71ab982c2bae88 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 25 Mar 2018 00:33:21 +0100 Subject: [PATCH 09/10] Reuse wxBookCtrlBase::DeleteAllPages() in wxNotebook Don't duplicate the base class code unnecessarily. No real changes. --- src/gtk1/notebook.cpp | 1 - src/msw/notebook.cpp | 10 +--------- src/osx/notebook_osx.cpp | 5 ++--- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/gtk1/notebook.cpp b/src/gtk1/notebook.cpp index 79f6cb8ba8..7a11bc1c20 100644 --- a/src/gtk1/notebook.cpp +++ b/src/gtk1/notebook.cpp @@ -586,7 +586,6 @@ bool wxNotebook::DeleteAllPages() wxASSERT_MSG( GetPageCount() == 0, wxT("all pages must have been deleted") ); - InvalidateBestSize(); return wxNotebookBase::DeleteAllPages(); } diff --git a/src/msw/notebook.cpp b/src/msw/notebook.cpp index 4ba23c88a7..62899bc39b 100644 --- a/src/msw/notebook.cpp +++ b/src/msw/notebook.cpp @@ -622,19 +622,11 @@ wxNotebookPage *wxNotebook::DoRemovePage(size_t nPage) // remove all pages bool wxNotebook::DeleteAllPages() { - size_t nPageCount = GetPageCount(); - size_t nPage; - for ( nPage = 0; nPage < nPageCount; nPage++ ) - delete m_pages[nPage]; - - m_pages.Clear(); + wxBookCtrlBase::DeleteAllPages(); if ( !TabCtrl_DeleteAllItems(GetHwnd()) ) wxLogLastError(wxS("TabCtrl_DeleteAllItems()")); - m_selection = wxNOT_FOUND; - - InvalidateBestSize(); return true; } diff --git a/src/osx/notebook_osx.cpp b/src/osx/notebook_osx.cpp index 29391e583c..fc94045154 100644 --- a/src/osx/notebook_osx.cpp +++ b/src/osx/notebook_osx.cpp @@ -199,11 +199,10 @@ wxNotebookPage* wxNotebook::DoRemovePage(size_t nPage) // remove all pages bool wxNotebook::DeleteAllPages() { - WX_CLEAR_ARRAY(m_pages); + wxBookCtrlBase::DeleteAllPages(); + m_images.clear(); MacSetupTabs(); - m_selection = wxNOT_FOUND ; - InvalidateBestSize(); return true; } From bee28c2730ce94a4e0eead18139c7d28ad6186ed Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 25 Mar 2018 00:38:16 +0100 Subject: [PATCH 10/10] Use wxVector<> for wxBookCtrlBase::m_pages array Get rid of another macro-based array in favour of wxVector<>. No real changes. --- include/wx/bookctrl.h | 8 +++----- src/common/bookctrl.cpp | 10 +++++----- src/gtk/notebook.cpp | 2 +- src/gtk1/notebook.cpp | 2 +- src/msw/notebook.cpp | 14 +++++++------- src/osx/notebook_osx.cpp | 4 ++-- src/qt/notebook.cpp | 2 +- src/univ/notebook.cpp | 4 ++-- 8 files changed, 22 insertions(+), 24 deletions(-) diff --git a/include/wx/bookctrl.h b/include/wx/bookctrl.h index 963de7a91a..267e81b692 100644 --- a/include/wx/bookctrl.h +++ b/include/wx/bookctrl.h @@ -20,11 +20,9 @@ #if wxUSE_BOOKCTRL #include "wx/control.h" -#include "wx/dynarray.h" +#include "wx/vector.h" #include "wx/withimages.h" -WX_DEFINE_EXPORTED_ARRAY_PTR(wxWindow *, wxArrayPages); - class WXDLLIMPEXP_FWD_CORE wxImageList; class WXDLLIMPEXP_FWD_CORE wxBookCtrlEvent; @@ -94,7 +92,7 @@ public: virtual size_t GetPageCount() const { return m_pages.size(); } // get the panel which represents the given page - virtual wxWindow *GetPage(size_t n) const { return m_pages[n]; } + virtual wxWindow *GetPage(size_t n) const { return m_pages.at(n); } // get the current page or NULL if none wxWindow *GetCurrentPage() const @@ -331,7 +329,7 @@ protected: // the array of all pages of this control - wxArrayPages m_pages; + wxVector m_pages; // get the page area virtual wxRect GetPageRect() const; diff --git a/src/common/bookctrl.cpp b/src/common/bookctrl.cpp index c2dde5fcfe..3ed66c98a1 100644 --- a/src/common/bookctrl.cpp +++ b/src/common/bookctrl.cpp @@ -241,8 +241,8 @@ void wxBookCtrlBase::DoSize() // resize all pages to fit the new control size const wxRect pageRect = GetPageRect(); - const unsigned pagesCount = m_pages.GetCount(); - for ( unsigned int i = 0; i < pagesCount; ++i ) + const size_t pagesCount = m_pages.size(); + for ( size_t i = 0; i < pagesCount; ++i ) { wxWindow * const page = m_pages[i]; if ( !page ) @@ -310,7 +310,7 @@ void wxBookCtrlBase::OnHelp(wxHelpEvent& event) source = source->GetParent(); } - if ( source && m_pages.Index(source) == wxNOT_FOUND ) + if ( source && FindPage(source) == wxNOT_FOUND ) { // this event is for the book control itself, redirect it to the // corresponding page @@ -368,7 +368,7 @@ wxBookCtrlBase::InsertPage(size_t nPage, wxCHECK_MSG( nPage <= m_pages.size(), false, wxT("invalid page index in wxBookCtrlBase::InsertPage()") ); - m_pages.Insert(page, nPage); + m_pages.insert(m_pages.begin() + nPage, page); if ( page ) page->SetSize(GetPageRect()); @@ -395,7 +395,7 @@ wxWindow *wxBookCtrlBase::DoRemovePage(size_t nPage) wxT("invalid page index in wxBookCtrlBase::DoRemovePage()") ); wxWindow *pageRemoved = m_pages[nPage]; - m_pages.RemoveAt(nPage); + m_pages.erase(m_pages.begin() + nPage); DoInvalidateBestSize(); return pageRemoved; diff --git a/src/gtk/notebook.cpp b/src/gtk/notebook.cpp index 8f75c84c25..35cd915ca6 100644 --- a/src/gtk/notebook.cpp +++ b/src/gtk/notebook.cpp @@ -418,7 +418,7 @@ bool wxNotebook::InsertPage( size_t position, wxGtkNotebookPage* pageData = new wxGtkNotebookPage; - m_pages.Insert(win, position); + m_pages.insert(m_pages.begin() + position, win); m_pagesData.Insert(position, pageData); // set the label image and text diff --git a/src/gtk1/notebook.cpp b/src/gtk1/notebook.cpp index 7a11bc1c20..6dc0752862 100644 --- a/src/gtk1/notebook.cpp +++ b/src/gtk1/notebook.cpp @@ -660,7 +660,7 @@ bool wxNotebook::InsertPage( size_t position, else m_pagesData.Insert( position, nb_page ); - m_pages.Insert(win, position); + m_pages.insert(m_pages.begin() + position, win); nb_page->m_box = gtk_hbox_new( FALSE, 1 ); gtk_container_border_width( GTK_CONTAINER(nb_page->m_box), 2 ); diff --git a/src/msw/notebook.cpp b/src/msw/notebook.cpp index 62899bc39b..62fa2d61b3 100644 --- a/src/msw/notebook.cpp +++ b/src/msw/notebook.cpp @@ -309,9 +309,9 @@ wxNotebook::~wxNotebook() size_t wxNotebook::GetPageCount() const { // consistency check - wxASSERT( (int)m_pages.Count() == TabCtrl_GetItemCount(GetHwnd()) ); + wxASSERT( (int)m_pages.size() == TabCtrl_GetItemCount(GetHwnd()) ); - return m_pages.Count(); + return m_pages.size(); } int wxNotebook::GetRowCount() const @@ -404,7 +404,7 @@ bool wxNotebook::SetPageText(size_t nPage, const wxString& strText) if ( ret && rows != GetRowCount() ) { const wxRect r = GetPageSize(); - const size_t count = m_pages.Count(); + const size_t count = m_pages.size(); for ( size_t page = 0; page < count; page++ ) m_pages[page]->SetSize(r); } @@ -578,7 +578,7 @@ wxNotebookPage *wxNotebook::DoRemovePage(size_t nPage) if ( !TabCtrl_DeleteItem(GetHwnd(), nPage) ) wxLogLastError(wxS("TabCtrl_DeleteItem()")); - if ( m_pages.IsEmpty() ) + if ( m_pages.empty() ) { // no selection any more, the notebook becamse empty m_selection = wxNOT_FOUND; @@ -693,13 +693,13 @@ bool wxNotebook::InsertPage(size_t nPage, } // succeeded: save the pointer to the page - m_pages.Insert(pPage, nPage); + m_pages.insert(m_pages.begin() + nPage, pPage); // we may need to adjust the size again if the notebook size changed: // normally this only happens for the first page we add (the tabs which // hadn't been there before are now shown) but for a multiline notebook it // can happen for any page at all as a new row could have been started - if ( m_pages.GetCount() == 1 || HasFlag(wxNB_MULTILINE) ) + if ( m_pages.size() == 1 || HasFlag(wxNB_MULTILINE) ) { AdjustPageSize(pPage); @@ -959,7 +959,7 @@ void wxNotebook::OnSize(wxSizeEvent& event) int width = rc.right - rc.left, height = rc.bottom - rc.top; - size_t nCount = m_pages.Count(); + size_t nCount = m_pages.size(); for ( size_t nPage = 0; nPage < nCount; nPage++ ) { wxNotebookPage *pPage = m_pages[nPage]; pPage->SetSize(rc.left, rc.top, width, height); diff --git a/src/osx/notebook_osx.cpp b/src/osx/notebook_osx.cpp index fc94045154..144797a9dc 100644 --- a/src/osx/notebook_osx.cpp +++ b/src/osx/notebook_osx.cpp @@ -173,7 +173,7 @@ wxNotebookPage* wxNotebook::DoRemovePage(size_t nPage) wxT("DoRemovePage: invalid notebook page") ); wxNotebookPage* page = m_pages[nPage] ; - m_pages.RemoveAt(nPage); + m_pages.erase(m_pages.begin() + nPage); m_images.RemoveAt(nPage); MacSetupTabs(); @@ -285,7 +285,7 @@ wxRect wxNotebook::GetPageRect() const // time because doing it in ::Create() doesn't work (for unknown reasons) void wxNotebook::OnSize(wxSizeEvent& event) { - unsigned int nCount = m_pages.Count(); + unsigned int nCount = m_pages.size(); wxRect rect = GetPageRect() ; for ( unsigned int nPage = 0; nPage < nCount; nPage++ ) diff --git a/src/qt/notebook.cpp b/src/qt/notebook.cpp index 5a3b8affcf..8fd294f1f5 100644 --- a/src/qt/notebook.cpp +++ b/src/qt/notebook.cpp @@ -150,7 +150,7 @@ bool wxNotebook::InsertPage(size_t n, wxWindow *page, const wxString& text, m_qtTabWidget->insertTab( n, page->GetHandle(), wxQtConvertString( text )); } - m_pages.Insert(page, n); + m_pages.insert(m_pages.begin() + n, page); m_images.insert(m_images.begin() + n, imageId); // reenable firing qt signals as internal wx initialization was completed diff --git a/src/univ/notebook.cpp b/src/univ/notebook.cpp index e68d51f07e..143b8ec82c 100644 --- a/src/univ/notebook.cpp +++ b/src/univ/notebook.cpp @@ -304,7 +304,7 @@ bool wxNotebook::InsertPage(size_t nPage, wxT("invalid notebook page in InsertPage()") ); // modify the data - m_pages.Insert(pPage, nPage); + m_pages.insert(m_pages.begin() + nPage, pPage); wxString label; m_accels.Insert(FindAccelIndex(strText, &label), nPage); @@ -378,7 +378,7 @@ wxNotebookPage *wxNotebook::DoRemovePage(size_t nPage) wxCHECK_MSG( IS_VALID_PAGE(nPage), NULL, wxT("invalid notebook page") ); wxNotebookPage *page = m_pages[nPage]; - m_pages.RemoveAt(nPage); + m_pages.erase(m_pages.begin() + nPage); m_titles.RemoveAt(nPage); m_accels.RemoveAt(nPage); m_widths.RemoveAt(nPage);