From 1d6fcbcc7088e9c104b3dc5b4704a07f728d55ae Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
Date: Sun, 8 Oct 2006 17:37:23 +0000
Subject: [PATCH] added wxBookCtrl::ChangeSelection() which is the same as
 SetSelection() but doesn't send the page change events (second part of patch
 1553551)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41738 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/notebook.tex       | 13 ++++++
 docs/latex/wx/treebook.tex       | 14 ++++++
 include/wx/bookctrl.h            | 20 +++++++++
 include/wx/choicebk.h            | 23 ++++++++--
 include/wx/cocoa/notebook.h      |  3 ++
 include/wx/generic/notebook.h    |  3 ++
 include/wx/gtk/notebook.h        | 10 ++++-
 include/wx/gtk1/notebook.h       | 12 +++++-
 include/wx/listbook.h            | 18 ++++++--
 include/wx/mac/carbon/notebook.h |  7 ++-
 include/wx/msw/notebook.h        |  6 +++
 include/wx/os2/notebook.h        |  3 ++
 include/wx/palmos/notebook.h     |  3 ++
 include/wx/toolbook.h            | 23 ++++++++--
 include/wx/treebook.h            |  5 ++-
 include/wx/univ/notebook.h       |  7 ++-
 samples/notebook/notebook.cpp    | 15 +++++++
 samples/notebook/notebook.h      |  2 +
 src/common/bookctrl.cpp          | 45 ++++++++++++++++++++
 src/generic/choicbkg.cpp         | 35 ++-------------
 src/generic/listbkg.cpp          | 43 +++++--------------
 src/generic/toolbkg.cpp          | 35 ++-------------
 src/generic/treebkg.cpp          | 53 ++++++++++++-----------
 src/gtk/notebook.cpp             | 61 +++++++++++++++++++-------
 src/gtk1/notebook.cpp            | 61 ++++++++++++++++++--------
 src/mac/carbon/notebmac.cpp      | 31 ++++++++------
 src/msw/notebook.cpp             | 73 ++++++++++++++++++++------------
 src/os2/notebook.cpp             | 16 +++++++
 src/palmos/notebook.cpp          |  5 +++
 src/univ/notebook.cpp            | 28 +++++++-----
 30 files changed, 448 insertions(+), 225 deletions(-)

diff --git a/docs/latex/wx/notebook.tex b/docs/latex/wx/notebook.tex
index 5b38276454..038be5568b 100644
--- a/docs/latex/wx/notebook.tex
+++ b/docs/latex/wx/notebook.tex
@@ -404,8 +404,21 @@ Sets the selection for the given page, returning the previous selection.
 
 The call to this function generates the page changing events.
 
+This function is deprecated and should not be used in new code. Please use the
+\helpref{ChangeSelection}{wxnotebookchangeselection} function instead.
+
 \wxheading{See also}
 
 \helpref{wxNotebook::GetSelection}{wxnotebookgetselection}
 
 
+
+\membersection{wxNotebook::ChangeSelection}\label{wxnotebookchangeselection}
+
+\func{int}{ChangeSelection}{\param{size\_t}{ page}}
+
+Changes the selection for the given page, returning the previous selection.
+
+The call to this function \emph{does not} generate the page changing events.
+This is the only difference with \helpref{SetSelection}{wxnotebooksetselection}.
+See \helpref{this topic}{progevent} for more info.
diff --git a/docs/latex/wx/treebook.tex b/docs/latex/wx/treebook.tex
index 426c402e4d..7541ba0245 100644
--- a/docs/latex/wx/treebook.tex
+++ b/docs/latex/wx/treebook.tex
@@ -271,7 +271,21 @@ Sets the selection for the given page, returning the previous selection.
 
 The call to this function generates the page changing events.
 
+This function is deprecated and should not be used in new code. Please use the
+\helpref{ChangeSelection}{wxtreebookchangeselection} function instead.
+
 \wxheading{See also}
 
 \helpref{wxTreebook::GetSelection}{wxtreebookgetselection}
 
+
+
+\membersection{wxTreebook::ChangeSelection}\label{wxtreebookchangeselection}
+
+\func{int}{ChangeSelection}{\param{size\_t}{ page}}
+
+Changes the selection for the given page, returning the previous selection.
+
+The call to this function \emph{does not} generate the page changing events.
+This is the only difference with \helpref{SetSelection}{wxtreebooksetselection}.
+See \helpref{this topic}{progevent} for more info.
diff --git a/include/wx/bookctrl.h b/include/wx/bookctrl.h
index 2d5c4ad04a..85d769d71a 100644
--- a/include/wx/bookctrl.h
+++ b/include/wx/bookctrl.h
@@ -26,6 +26,7 @@
 WX_DEFINE_EXPORTED_ARRAY_PTR(wxWindow *, wxArrayPages);
 
 class WXDLLEXPORT wxImageList;
+class WXDLLEXPORT wxBookCtrlBaseEvent;
 
 // ----------------------------------------------------------------------------
 // constants
@@ -194,6 +195,9 @@ public:
     // NB: this function will generate PAGE_CHANGING/ED events
     virtual int SetSelection(size_t n) = 0;
 
+    // acts as SetSelection but does not generate events
+    virtual int ChangeSelection(size_t n) = 0;
+
 
     // cycle thru the pages
     void AdvanceSelection(bool forward = true)
@@ -218,6 +222,22 @@ public:
     virtual bool HasMultiplePages() const { return true; }
 
 protected:
+    // typically, wxBookCtrl-derived classes will use DoSetSelection() function
+    // to implement SetSelection() and ChangeSelection() functions.
+    // these flags make DoSetSelection() more readable
+    enum
+    {
+        SetSelection_SendEvent = 1
+    };
+
+    // if using DoSetSelection() for implementing [Set|Change]Selection,
+    // then override UpdateSelectedPage() and MakeChangedEvent()
+    virtual int DoSetSelection(size_t nPage, int flags, wxBookCtrlBaseEvent &event);
+    virtual void UpdateSelectedPage(size_t WXUNUSED(newsel))
+        { wxFAIL_MSG(wxT("Override this function!")); }
+    virtual void MakeChangedEvent(wxBookCtrlBaseEvent &WXUNUSED(event))
+        { wxFAIL_MSG(wxT("Override this function!")); }
+
     // Should we accept NULL page pointers in Add/InsertPage()?
     //
     // Default is no but derived classes may override it if they can treat NULL
diff --git a/include/wx/choicebk.h b/include/wx/choicebk.h
index 6c215fc764..06a071c237 100644
--- a/include/wx/choicebk.h
+++ b/include/wx/choicebk.h
@@ -20,6 +20,10 @@
 
 class WXDLLEXPORT wxChoice;
 
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGED;
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGING;
+
+
 // ----------------------------------------------------------------------------
 // wxChoicebook
 // ----------------------------------------------------------------------------
@@ -64,7 +68,8 @@ public:
                             const wxString& text,
                             bool bSelect = false,
                             int imageId = -1);
-    virtual int SetSelection(size_t n);
+    virtual int SetSelection(size_t n) { return DoSetSelection(n, SetSelection_SendEvent); }
+    virtual int ChangeSelection(size_t n) { return DoSetSelection(n); }
     virtual void SetImageList(wxImageList *imageList);
 
     virtual bool DeleteAllPages();
@@ -78,6 +83,19 @@ protected:
     // get the size which the choice control should have
     virtual wxSize GetControllerSize() const;
 
+    int DoSetSelection(size_t nPage, int flags = 0);
+
+    void UpdateSelectedPage(size_t newsel)
+    {
+        m_selection = newsel;
+        GetChoiceCtrl()->Select(newsel);
+    }
+
+    void MakeChangedEvent(wxBookCtrlBaseEvent &event)
+    {
+        event.SetEventType(wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGED);
+    }
+
     // event handlers
     void OnChoiceSelected(wxCommandEvent& event);
 
@@ -116,9 +134,6 @@ private:
     DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxChoicebookEvent)
 };
 
-extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGED;
-extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGING;
-
 typedef void (wxEvtHandler::*wxChoicebookEventFunction)(wxChoicebookEvent&);
 
 #define wxChoicebookEventHandler(func) \
diff --git a/include/wx/cocoa/notebook.h b/include/wx/cocoa/notebook.h
index 5ba76c2d38..97cfd33c4c 100644
--- a/include/wx/cocoa/notebook.h
+++ b/include/wx/cocoa/notebook.h
@@ -62,6 +62,9 @@ public:
     // get the currently selected page
     int GetSelection() const;
 
+    // changes selected page without sending events
+    int ChangeSelection(size_t nPage);
+
     // set/get the title of a page
     bool SetPageText(size_t nPage, const wxString& strText);
     wxString GetPageText(size_t nPage) const;
diff --git a/include/wx/generic/notebook.h b/include/wx/generic/notebook.h
index 6913929298..116286eb1e 100644
--- a/include/wx/generic/notebook.h
+++ b/include/wx/generic/notebook.h
@@ -68,6 +68,9 @@ public:
     // get the currently selected page
   int GetSelection() const { return m_nSelection; }
 
+    // changes selected page without sending events
+  int ChangeSelection(size_t nPage);
+
     // set/get the title of a page
   bool SetPageText(size_t nPage, const wxString& strText);
   wxString GetPageText(size_t nPage) const;
diff --git a/include/wx/gtk/notebook.h b/include/wx/gtk/notebook.h
index 8965c2d2f6..d58bbdf345 100644
--- a/include/wx/gtk/notebook.h
+++ b/include/wx/gtk/notebook.h
@@ -52,10 +52,13 @@ public:
     // set the currently selected page, return the index of the previously
     // selected one (or -1 on error)
     // NB: this function will _not_ generate wxEVT_NOTEBOOK_PAGE_xxx events
-  int SetSelection(size_t nPage);
+    int SetSelection(size_t nPage) { return DoSetSelection(nPage, SetSelection_SendEvent); }
     // get the currently selected page
   int GetSelection() const;
 
+  // changes selected page without sending events
+  int ChangeSelection(size_t nPage) { return DoSetSelection(nPage); }
+
     // set/get the title of a page
   bool SetPageText(size_t nPage, const wxString& strText);
   wxString GetPageText(size_t nPage) const;
@@ -120,6 +123,9 @@ public:
     // flag set to true while we're inside "switch_page" callback
     bool m_inSwitchPage;
 
+    // flag set to true when the switch-page signal has been programatically generated
+    bool m_skipNextPageChangeEvent;
+
 protected:
     // set all page's attributes
     virtual void DoApplyWidgetStyle(GtkRcStyle *style);
@@ -128,6 +134,8 @@ protected:
     // remove one page from the notebook but do not destroy it
     virtual wxNotebookPage *DoRemovePage(size_t nPage);
 
+    int DoSetSelection(size_t nPage, int flags = 0);
+
 private:
     // the padding set by SetPadding()
     int m_padding;
diff --git a/include/wx/gtk1/notebook.h b/include/wx/gtk1/notebook.h
index 27eccbbe23..9acd18e460 100644
--- a/include/wx/gtk1/notebook.h
+++ b/include/wx/gtk1/notebook.h
@@ -52,9 +52,12 @@ public:
     // set the currently selected page, return the index of the previously
     // selected one (or -1 on error)
     // NB: this function will _not_ generate wxEVT_NOTEBOOK_PAGE_xxx events
-  int SetSelection(size_t nPage);
+    int SetSelection(size_t nPage) { return DoSetSelection(nPage, SetSelection_SendEvent); }
     // get the currently selected page
-  int GetSelection() const;
+    int GetSelection() const;
+
+    // changes selected page without sending events
+    int ChangeSelection(size_t nPage) { return DoSetSelection(nPage); }
 
     // set/get the title of a page
   bool SetPageText(size_t nPage, const wxString& strText);
@@ -126,10 +129,15 @@ public:
     // flag set to true while we're inside "switch_page" callback
     bool m_inSwitchPage;
 
+    // flag set to true when the switch-page signal has been programatically generated
+    bool m_skipNextPageChangeEvent;
+
 protected:
     // remove one page from the notebook but do not destroy it
     virtual wxNotebookPage *DoRemovePage(size_t nPage);
 
+    int DoSetSelection(size_t nPage, int flags = 0);
+
 private:
     // the padding set by SetPadding()
     int m_padding;
diff --git a/include/wx/listbook.h b/include/wx/listbook.h
index b8022730f7..b62da59d47 100644
--- a/include/wx/listbook.h
+++ b/include/wx/listbook.h
@@ -21,6 +21,9 @@
 class WXDLLEXPORT wxListView;
 class WXDLLEXPORT wxListEvent;
 
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED;
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING;
+
 // ----------------------------------------------------------------------------
 // wxListbook
 // ----------------------------------------------------------------------------
@@ -65,7 +68,8 @@ public:
                             const wxString& text,
                             bool bSelect = false,
                             int imageId = -1);
-    virtual int SetSelection(size_t n);
+    virtual int SetSelection(size_t n) { return DoSetSelection(n, SetSelection_SendEvent); }
+    virtual int ChangeSelection(size_t n) { return DoSetSelection(n); }
     virtual void SetImageList(wxImageList *imageList);
 
     virtual bool DeleteAllPages();
@@ -81,6 +85,15 @@ protected:
     // return the page corresponding to the tab at the specified position
     virtual int HitTest(const wxPoint& pt, long *flags = NULL) const;
 
+    int DoSetSelection(size_t nPage, int flags = 0);
+
+    void UpdateSelectedPage(size_t newsel);
+
+    void MakeChangedEvent(wxBookCtrlBaseEvent &event)
+    {
+        event.SetEventType(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED);
+    }
+
     // event handlers
     void OnListSelected(wxListEvent& event);
     void OnSize(wxSizeEvent& event);
@@ -120,9 +133,6 @@ private:
     DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxListbookEvent)
 };
 
-extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED;
-extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING;
-
 typedef void (wxEvtHandler::*wxListbookEventFunction)(wxListbookEvent&);
 
 #define wxListbookEventHandler(func) \
diff --git a/include/wx/mac/carbon/notebook.h b/include/wx/mac/carbon/notebook.h
index 299b438dbe..859bbc9bee 100644
--- a/include/wx/mac/carbon/notebook.h
+++ b/include/wx/mac/carbon/notebook.h
@@ -57,10 +57,13 @@ public:
     // set the currently selected page, return the index of the previously
     // selected one (or -1 on error)
     // NB: this function will _not_ generate wxEVT_NOTEBOOK_PAGE_xxx events
-  int SetSelection(size_t nPage);
+  int SetSelection(size_t nPage) { return DoSetSelection(nPage, SetSelection_SendEvent); }
     // get the currently selected page
   int GetSelection() const { return m_nSelection; }
 
+    // changes selected page without sending events
+  int ChangeSelection(size_t nPage) { return DoSetSelection(nPage); }
+
     // set/get the title of a page
   bool SetPageText(size_t nPage, const wxString& strText);
   wxString GetPageText(size_t nPage) const;
@@ -125,6 +128,8 @@ protected:
   void ChangePage(int nOldSel, int nSel); // change pages
   void MacSetupTabs();
 
+  int DoSetSelection(size_t nPage, int flags = 0);
+
   // the icon indices
   wxArrayInt m_images;
 
diff --git a/include/wx/msw/notebook.h b/include/wx/msw/notebook.h
index 2075b5fe62..0b99f664d5 100644
--- a/include/wx/msw/notebook.h
+++ b/include/wx/msw/notebook.h
@@ -92,6 +92,9 @@ public:
     // get the currently selected page
   int GetSelection() const { return m_nSelection; }
 
+    // changes selected page without sending events
+  int ChangeSelection(size_t nPage);
+
     // set/get the title of a page
   bool SetPageText(size_t nPage, const wxString& strText);
   wxString GetPageText(size_t nPage) const;
@@ -193,6 +196,9 @@ protected:
   // common part of all ctors
   void Init();
 
+  // hides m_nSelection-th page, shows the newsel-th one and updates m_nSelection
+  void UpdateSelection(size_t newsel);
+
   // remove one page from the notebook, without deleting
   virtual wxNotebookPage *DoRemovePage(size_t nPage);
 
diff --git a/include/wx/os2/notebook.h b/include/wx/os2/notebook.h
index 30a3a81031..af22bc4b54 100644
--- a/include/wx/os2/notebook.h
+++ b/include/wx/os2/notebook.h
@@ -66,6 +66,9 @@ public:
     //
     int      SetSelection(size_t nPage);
 
+    // changes selected page without sending events
+    int ChangeSelection(size_t nPage);
+
     //
     // Get the currently selected page
     //
diff --git a/include/wx/palmos/notebook.h b/include/wx/palmos/notebook.h
index b06f9552f6..f4ef524cda 100644
--- a/include/wx/palmos/notebook.h
+++ b/include/wx/palmos/notebook.h
@@ -87,6 +87,9 @@ public:
     // get the currently selected page
     int GetSelection() const { return m_nSelection; }
 
+    // changes the selected page without sending events
+    int ChangeSelection(size_t nPage);
+
     // set/get the title of a page
     bool SetPageText(size_t nPage, const wxString& strText);
     wxString GetPageText(size_t nPage) const;
diff --git a/include/wx/toolbook.h b/include/wx/toolbook.h
index 1227d82483..097ccff314 100644
--- a/include/wx/toolbook.h
+++ b/include/wx/toolbook.h
@@ -21,6 +21,10 @@
 class WXDLLEXPORT wxToolBarBase;
 class WXDLLEXPORT wxCommandEvent;
 
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED;
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGING;
+
+
 // Use wxButtonToolBar
 #define wxBK_BUTTONBAR            0x0100
 
@@ -69,7 +73,8 @@ public:
                             const wxString& text,
                             bool bSelect = false,
                             int imageId = -1);
-    virtual int SetSelection(size_t n);
+    virtual int SetSelection(size_t n) { return DoSetSelection(n, SetSelection_SendEvent); }
+    virtual int ChangeSelection(size_t n) { return DoSetSelection(n); }
     virtual void SetImageList(wxImageList *imageList);
 
     virtual bool DeleteAllPages();
@@ -96,6 +101,19 @@ protected:
     void OnSize(wxSizeEvent& event);
     void OnIdle(wxIdleEvent& event);
 
+    int DoSetSelection(size_t nPage, int flags = 0);
+
+    void UpdateSelectedPage(size_t newsel)
+    {
+        m_selection = newsel;
+        GetToolBar()->ToggleTool(newsel + 1, true);
+    }
+
+    void MakeChangedEvent(wxBookCtrlBaseEvent &event)
+    {
+        event.SetEventType(wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED);
+    }
+
     // the currently selected page or wxNOT_FOUND if none
     int m_selection;
 
@@ -137,9 +155,6 @@ private:
     DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxToolbookEvent)
 };
 
-extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED;
-extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGING;
-
 typedef void (wxEvtHandler::*wxToolbookEventFunction)(wxToolbookEvent&);
 
 #define wxToolbookEventHandler(func) \
diff --git a/include/wx/treebook.h b/include/wx/treebook.h
index 578ec3ade3..5334073d44 100644
--- a/include/wx/treebook.h
+++ b/include/wx/treebook.h
@@ -133,7 +133,8 @@ public:
     virtual int GetPageImage(size_t n) const;
     virtual bool SetPageImage(size_t n, int imageId);
     virtual wxSize CalcSizeFromPage(const wxSize& sizePage) const;
-    virtual int SetSelection(size_t n);
+    virtual int SetSelection(size_t n) { return DoSetSelection(n, SetSelection_SendEvent); }
+    virtual int ChangeSelection(size_t n) { return DoSetSelection(n); }
     virtual void SetImageList(wxImageList *imageList);
     virtual void AssignImageList(wxImageList *imageList);
     virtual bool DeleteAllPages();
@@ -188,7 +189,7 @@ private:
                          int imageId = wxNOT_FOUND);
 
     // Sets selection in the tree control and updates the page being shown.
-    int DoSetSelection(size_t pos);
+    int DoSetSelection(size_t pos, int flags = 0);
 
     // Returns currently shown page. In a case when selected the node
     // has empty (NULL) page finds first (sub)child with not-empty page.
diff --git a/include/wx/univ/notebook.h b/include/wx/univ/notebook.h
index c87ad704fb..44befbf909 100644
--- a/include/wx/univ/notebook.h
+++ b/include/wx/univ/notebook.h
@@ -63,9 +63,12 @@ public:
     // implement wxNotebookBase pure virtuals
     // --------------------------------------
 
-    virtual int SetSelection(size_t nPage);
+    virtual int SetSelection(size_t nPage) { return DoSetSelection(nPage, SetSelection_SendEvent); }
     virtual int GetSelection() const { return (int) m_sel; }
 
+    // changes selected page without sending events
+    int ChangeSelection(size_t nPage) { return DoSetSelection(nPage); }
+
     virtual bool SetPageText(size_t nPage, const wxString& strText);
     virtual wxString GetPageText(size_t nPage) const;
 
@@ -134,6 +137,8 @@ protected:
                            int width, int height,
                            int sizeFlags = wxSIZE_AUTO);
 
+    int DoSetSelection(size_t nPage, int flags = 0);
+
     // common part of all ctors
     void Init();
 
diff --git a/samples/notebook/notebook.cpp b/samples/notebook/notebook.cpp
index 4149cd884a..4e5737b60f 100644
--- a/samples/notebook/notebook.cpp
+++ b/samples/notebook/notebook.cpp
@@ -265,6 +265,8 @@ MyFrame::MyFrame()
     menuPageOperations->Append(ID_ADD_PAGE_BEFORE, wxT("Insert page &before\tAlt-B"));
     menuPageOperations->Append(ID_ADD_SUB_PAGE, wxT("Add s&ub page\tAlt-U"));
 #endif
+    menuPageOperations->AppendSeparator();
+    menuPageOperations->Append(ID_GO_HOME, wxT("Go to the first page\tCtrl-F"));
 
     wxMenu *menuOperations = new wxMenu;
 #if wxUSE_HELP
@@ -517,6 +519,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
     EVT_MENU(ID_DELETE_CUR_PAGE, MyFrame::OnDeleteCurPage)
     EVT_MENU(ID_DELETE_LAST_PAGE, MyFrame::OnDeleteLastPage)
     EVT_MENU(ID_NEXT_PAGE, MyFrame::OnNextPage)
+    EVT_MENU(ID_GO_HOME, MyFrame::OnGoHome)
 
 #if wxUSE_HELP
     EVT_MENU(ID_CONTEXT_HELP, MyFrame::OnContextHelp)
@@ -788,6 +791,18 @@ void MyFrame::OnNextPage(wxCommandEvent& WXUNUSED(event))
     }
 }
 
+void MyFrame::OnGoHome(wxCommandEvent& WXUNUSED(event))
+{
+    wxBookCtrlBase *currBook = GetCurrentBook();
+
+    if ( currBook )
+    {
+        // ChangeSelection shouldn't send any events, SetSelection() should
+        currBook->ChangeSelection(0);
+        //currBook->SetSelection(0);
+    }
+}
+
 void MyFrame::OnIdle( wxIdleEvent& WXUNUSED(event) )
 {
     static int s_nPages = wxNOT_FOUND;
diff --git a/samples/notebook/notebook.h b/samples/notebook/notebook.h
index 68b732e7b4..41d44068c8 100644
--- a/samples/notebook/notebook.h
+++ b/samples/notebook/notebook.h
@@ -48,6 +48,7 @@ public:
     void OnDeleteCurPage(wxCommandEvent& event);
     void OnDeleteLastPage(wxCommandEvent& event);
     void OnNextPage(wxCommandEvent& event);
+    void OnGoHome(wxCommandEvent &event);
 
     void OnAddSubPage(wxCommandEvent& event);
     void OnAddPageBefore(wxCommandEvent& event);
@@ -147,6 +148,7 @@ enum ID_COMMANDS
     ID_NEXT_PAGE,
     ID_ADD_PAGE_BEFORE,
     ID_ADD_SUB_PAGE,
+    ID_GO_HOME,
 
 #if wxUSE_HELP
     ID_CONTEXT_HELP,
diff --git a/src/common/bookctrl.cpp b/src/common/bookctrl.cpp
index ffae3d708d..d194cc20a9 100644
--- a/src/common/bookctrl.cpp
+++ b/src/common/bookctrl.cpp
@@ -423,4 +423,49 @@ wxSize wxBookCtrlBase::GetControllerSize() const
     return size;
 }
 
+int wxBookCtrlBase::DoSetSelection(size_t n, int flags, wxBookCtrlBaseEvent &event)
+{
+    wxCHECK_MSG( n < GetPageCount(), wxNOT_FOUND,
+                 wxT("invalid page index in wxBookCtrlBase::DoSetSelection()") );
+
+    const int oldSel = GetSelection();
+
+    if ( oldSel != wxNOT_FOUND && n != (size_t)oldSel )
+    {
+        bool allowed = false;
+
+        if ( flags & SetSelection_SendEvent )
+        {
+            event.SetSelection(n);
+            event.SetOldSelection(oldSel);
+            event.SetEventObject(this);
+
+            allowed = !GetEventHandler()->ProcessEvent(event) || event.IsAllowed();
+        }
+
+        if ( !(flags & SetSelection_SendEvent) || allowed)
+        {
+            if ( oldSel != wxNOT_FOUND )
+                m_pages[oldSel]->Hide();
+
+            wxWindow *page = m_pages[n];
+            page->SetSize(GetPageRect());
+            page->Show();
+
+            // change selection now to ignore the selection change event
+            UpdateSelectedPage(n);
+
+            if ( flags & SetSelection_SendEvent )
+            {
+                // program allows the page change
+                MakeChangedEvent(event);
+                (void)GetEventHandler()->ProcessEvent(event);
+            }
+        }
+    }
+
+    return oldSel;
+}
+
+
 #endif // wxUSE_BOOKCTRL
diff --git a/src/generic/choicbkg.cpp b/src/generic/choicbkg.cpp
index 445d0f575a..d74d0b575f 100644
--- a/src/generic/choicbkg.cpp
+++ b/src/generic/choicbkg.cpp
@@ -209,39 +209,10 @@ int wxChoicebook::GetSelection() const
     return m_selection;
 }
 
-int wxChoicebook::SetSelection(size_t n)
+int wxChoicebook::DoSetSelection(size_t n, int flags)
 {
-    wxCHECK_MSG( IS_VALID_PAGE(n), wxNOT_FOUND,
-                 wxT("invalid page index in wxChoicebook::SetSelection()") );
-
-    const int oldSel = m_selection;
-
-    if ( int(n) != m_selection )
-    {
-        wxChoicebookEvent event(wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGING, m_windowId);
-        event.SetSelection(n);
-        event.SetOldSelection(m_selection);
-        event.SetEventObject(this);
-        if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
-        {
-            if ( m_selection != wxNOT_FOUND )
-                m_pages[m_selection]->Hide();
-
-            wxWindow *page = m_pages[n];
-            page->SetSize(GetPageRect());
-            page->Show();
-
-            // change m_selection now to ignore the selection change event
-            m_selection = n;
-            GetChoiceCtrl()->Select(n);
-
-            // program allows the page change
-            event.SetEventType(wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGED);
-            (void)GetEventHandler()->ProcessEvent(event);
-        }
-    }
-
-    return oldSel;
+    wxChoicebookEvent event(wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGING, m_windowId);
+    return wxBookCtrlBase::DoSetSelection(n, flags, event);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/src/generic/listbkg.cpp b/src/generic/listbkg.cpp
index b21319248a..9f725353c0 100644
--- a/src/generic/listbkg.cpp
+++ b/src/generic/listbkg.cpp
@@ -262,45 +262,22 @@ void wxListbook::SetImageList(wxImageList *imageList)
 // selection
 // ----------------------------------------------------------------------------
 
+void wxListbook::UpdateSelectedPage(size_t newsel)
+{
+    m_selection = newsel;
+    GetListView()->Select(newsel);
+    GetListView()->Focus(newsel);
+}
+
 int wxListbook::GetSelection() const
 {
     return m_selection;
 }
 
-int wxListbook::SetSelection(size_t n)
+int wxListbook::DoSetSelection(size_t n, int flags)
 {
-    wxCHECK_MSG( IS_VALID_PAGE(n), wxNOT_FOUND,
-                 wxT("invalid page index in wxListbook::SetSelection()") );
-
-    const int oldSel = m_selection;
-
-    if ( int(n) != m_selection )
-    {
-        wxListbookEvent event(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING, m_windowId);
-        event.SetSelection(n);
-        event.SetOldSelection(m_selection);
-        event.SetEventObject(this);
-        if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
-        {
-            if ( m_selection != wxNOT_FOUND )
-                m_pages[m_selection]->Hide();
-
-            wxWindow *page = m_pages[n];
-            page->SetSize(GetPageRect());
-            page->Show();
-
-            // change m_selection now to ignore the selection change event
-            m_selection = n;
-            GetListView()->Select(n);
-            GetListView()->Focus(n);
-
-            // program allows the page change
-            event.SetEventType(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED);
-            (void)GetEventHandler()->ProcessEvent(event);
-        }
-    }
-
-    return oldSel;
+    wxListbookEvent event(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING, m_windowId);
+    return wxBookCtrlBase::DoSetSelection(n, flags, event);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/src/generic/toolbkg.cpp b/src/generic/toolbkg.cpp
index f85a27462b..fbfbd0b0bc 100644
--- a/src/generic/toolbkg.cpp
+++ b/src/generic/toolbkg.cpp
@@ -245,39 +245,10 @@ int wxToolbook::GetSelection() const
     return m_selection;
 }
 
-int wxToolbook::SetSelection(size_t n)
+int wxToolbook::DoSetSelection(size_t n, int flags)
 {
-    wxCHECK_MSG( IS_VALID_PAGE(n), wxNOT_FOUND,
-                 wxT("invalid page index in wxToolbook::SetSelection()") );
-
-    const int oldSel = m_selection;
-
-    if ( int(n) != m_selection )
-    {
-        wxToolbookEvent event(wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGING, m_windowId);
-        event.SetSelection(n);
-        event.SetOldSelection(m_selection);
-        event.SetEventObject(this);
-        if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
-        {
-            if ( m_selection != wxNOT_FOUND )
-                m_pages[m_selection]->Hide();
-
-            wxWindow *page = m_pages[n];
-            page->SetSize(GetPageRect());
-            page->Show();
-
-            // change m_selection now to ignore the selection change event
-            m_selection = n;
-            GetToolBar()->ToggleTool(n + 1, true);
-
-            // program allows the page change
-            event.SetEventType(wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED);
-            (void)GetEventHandler()->ProcessEvent(event);
-        }
-    }
-
-    return oldSel;
+    wxToolbookEvent event(wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGING, m_windowId);
+    return wxBookCtrlBase::DoSetSelection(n, flags, event);
 }
 
 // Not part of the wxBookctrl API, but must be called in OnIdle or
diff --git a/src/generic/treebkg.cpp b/src/generic/treebkg.cpp
index 2bcb1da8dd..8f34b7ef4d 100644
--- a/src/generic/treebkg.cpp
+++ b/src/generic/treebkg.cpp
@@ -432,7 +432,9 @@ void wxTreebook::DoInternalRemovePageRange(size_t pagePos, size_t subCount)
             // actually shown page (the first (sub)child with page != NULL) is
             // already deleted
             m_actualSelection = m_selection;
-            DoSetSelection(m_selection);
+
+            // send event as documented
+            DoSetSelection(m_selection, SetSelection_SendEvent);
         }
         //else: nothing to do -- selection is before the deleted node
     }
@@ -583,34 +585,32 @@ int wxTreebook::GetSelection() const
    return m_selection;
 }
 
-int wxTreebook::SetSelection(size_t pagePos)
-{
-   if ( (size_t)m_selection != pagePos )
-       return DoSetSelection(pagePos);
-
-   return m_selection;
-}
-
-int wxTreebook::DoSetSelection(size_t pagePos)
+int wxTreebook::DoSetSelection(size_t pagePos, int flags)
 {
     wxCHECK_MSG( IS_VALID_PAGE(pagePos), wxNOT_FOUND,
-                 wxT("invalid page index in wxListbook::SetSelection()") );
+                 wxT("invalid page index in wxListbook::DoSetSelection()") );
     wxASSERT_MSG( GetPageCount() == DoInternalGetPageCount(),
                   wxT("wxTreebook logic error: m_treeIds and m_pages not in sync!"));
 
+    wxTreebookEvent event(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING, m_windowId);
     const int oldSel = m_selection;
     wxTreeCtrl *tree = GetTreeCtrl();
+    bool allowed = false;
 
-    wxTreebookEvent event(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING, m_windowId);
-    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
-    if ( (int)pagePos == m_selection ||
-            !GetEventHandler()->ProcessEvent(event) ||
-                event.IsAllowed() )
+    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();
@@ -644,11 +644,14 @@ int wxTreebook::DoSetSelection(size_t pagePos)
 
         tree->SelectItem(DoInternalGetPage(pagePos));
 
-        // notify about the (now completed) page change
-        event.SetEventType(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED);
-        (void)GetEventHandler()->ProcessEvent(event);
+        if (flags & SetSelection_SendEvent)
+        {
+            // notify about the (now completed) page change
+            event.SetEventType(wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED);
+            (void)GetEventHandler()->ProcessEvent(event);
+        }
     }
-    else // page change vetoed
+    else if ( (flags & SetSelection_SendEvent) && !allowed) // page change vetoed
     {
         // tree selection might have already had changed
         if ( oldSel != wxNOT_FOUND )
diff --git a/src/gtk/notebook.cpp b/src/gtk/notebook.cpp
index 9c4b4a3932..27105979a5 100644
--- a/src/gtk/notebook.cpp
+++ b/src/gtk/notebook.cpp
@@ -104,28 +104,43 @@ static void gtk_notebook_page_change_callback(GtkNotebook *WXUNUSED(widget),
 
     int old = notebook->GetSelection();
 
-    wxNotebookEvent eventChanging( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING,
-                                   notebook->GetId(), page, old );
-    eventChanging.SetEventObject( notebook );
 
-    if ( (notebook->GetEventHandler()->ProcessEvent(eventChanging)) &&
-         !eventChanging.IsAllowed() )
-    {
-        /* program doesn't allow the page change */
-        g_signal_stop_emission_by_name (notebook->m_widget,
-                                        "switch_page");
-    }
-    else // change allowed
+    if (notebook->m_skipNextPageChangeEvent)
     {
+        // this event was programatically generated by ChangeSelection() and thus must
+        // be skipped
+        notebook->m_skipNextPageChangeEvent = false;
+
         // make wxNotebook::GetSelection() return the correct (i.e. consistent
         // with wxNotebookEvent::GetSelection()) value even though the page is
         // not really changed in GTK+
         notebook->m_selection = page;
+    }
+    else
+    {
+        wxNotebookEvent eventChanging( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING,
+                                    notebook->GetId(), page, old );
+        eventChanging.SetEventObject( notebook );
 
-        wxNotebookEvent eventChanged( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
-                                      notebook->GetId(), page, old );
-        eventChanged.SetEventObject( notebook );
-        notebook->GetEventHandler()->ProcessEvent( eventChanged );
+        if ( (notebook->GetEventHandler()->ProcessEvent(eventChanging)) &&
+            !eventChanging.IsAllowed() )
+        {
+            /* program doesn't allow the page change */
+            g_signal_stop_emission_by_name (notebook->m_widget,
+                                            "switch_page");
+        }
+        else // change allowed
+        {
+            // make wxNotebook::GetSelection() return the correct (i.e. consistent
+            // with wxNotebookEvent::GetSelection()) value even though the page is
+            // not really changed in GTK+
+            notebook->m_selection = page;
+
+            wxNotebookEvent eventChanged( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
+                                        notebook->GetId(), page, old );
+            eventChanged.SetEventObject( notebook );
+            notebook->GetEventHandler()->ProcessEvent( eventChanged );
+        }
     }
 
     notebook->m_inSwitchPage = false;
@@ -289,6 +304,7 @@ void wxNotebook::Init()
 {
     m_padding = 0;
     m_inSwitchPage = false;
+    m_skipNextPageChangeEvent = false;
 
     m_imageList = (wxImageList *) NULL;
     m_selection = -1;
@@ -414,7 +430,7 @@ wxGtkNotebookPage* wxNotebook::GetNotebookPage( int page ) const
     return m_pagesData.Item(page)->GetData();
 }
 
-int wxNotebook::SetSelection( size_t page )
+int wxNotebook::DoSetSelection( size_t page, int flags )
 {
     wxCHECK_MSG( m_widget != NULL, -1, wxT("invalid notebook") );
 
@@ -422,10 +438,23 @@ int wxNotebook::SetSelection( size_t page )
 
     int selOld = GetSelection();
 
+    if ( !(flags & SetSelection_SendEvent) )
+        m_skipNextPageChangeEvent = true;
+
     // cache the selection
     m_selection = page;
     gtk_notebook_set_current_page( GTK_NOTEBOOK(m_widget), page );
 
+#ifdef __WXDEBUG__
+    if ( !(flags & SetSelection_SendEvent) )
+    {
+        // gtk_notebook_set_current_page will emit the switch-page signal which will be
+        // caught by our gtk_notebook_page_change_callback which should have reset the
+        // flag to false:
+        wxASSERT(!m_skipNextPageChangeEvent);
+    }
+#endif // __WXDEBUG__
+
     wxNotebookPage *client = GetPage(page);
     if ( client )
         client->SetFocus();
diff --git a/src/gtk1/notebook.cpp b/src/gtk1/notebook.cpp
index ffa2e2a428..7c51c6d91b 100644
--- a/src/gtk1/notebook.cpp
+++ b/src/gtk1/notebook.cpp
@@ -105,28 +105,42 @@ static void gtk_notebook_page_change_callback(GtkNotebook *WXUNUSED(widget),
 
     int old = notebook->GetSelection();
 
-    wxNotebookEvent eventChanging( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING,
-                                   notebook->GetId(), page, old );
-    eventChanging.SetEventObject( notebook );
-
-    if ( (notebook->GetEventHandler()->ProcessEvent(eventChanging)) &&
-         !eventChanging.IsAllowed() )
-    {
-        /* program doesn't allow the page change */
-        gtk_signal_emit_stop_by_name( GTK_OBJECT(notebook->m_widget),
-                                      "switch_page" );
-    }
-    else // change allowed
+    if (notebook->m_skipNextPageChangeEvent)
     {
+        // this event was programatically generated by ChangeSelection() and thus must
+        // be skipped
+        notebook->m_skipNextPageChangeEvent = false;
+
         // make wxNotebook::GetSelection() return the correct (i.e. consistent
         // with wxNotebookEvent::GetSelection()) value even though the page is
         // not really changed in GTK+
         notebook->m_selection = page;
+    }
+    else
+    {
+        wxNotebookEvent eventChanging( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING,
+                                       notebook->GetId(), page, old );
+        eventChanging.SetEventObject( notebook );
 
-        wxNotebookEvent eventChanged( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
-                                      notebook->GetId(), page, old );
-        eventChanged.SetEventObject( notebook );
-        notebook->GetEventHandler()->ProcessEvent( eventChanged );
+        if ( (notebook->GetEventHandler()->ProcessEvent(eventChanging)) &&
+              !eventChanging.IsAllowed() )
+        {
+            /* program doesn't allow the page change */
+            g_signal_stop_emission_by_name (notebook->m_widget,
+                                            "switch_page");
+        }
+        else // change allowed
+        {
+            // make wxNotebook::GetSelection() return the correct (i.e. consistent
+            // with wxNotebookEvent::GetSelection()) value even though the page is
+            // not really changed in GTK+
+            notebook->m_selection = page;
+
+            wxNotebookEvent eventChanged( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
+                                          notebook->GetId(), page, old );
+            eventChanged.SetEventObject( notebook );
+            notebook->GetEventHandler()->ProcessEvent( eventChanged );
+        }
     }
 
     notebook->m_inSwitchPage = FALSE;
@@ -417,7 +431,7 @@ wxGtkNotebookPage* wxNotebook::GetNotebookPage( int page ) const
     return m_pagesData.Item(page)->GetData();
 }
 
-int wxNotebook::SetSelection( size_t page )
+int wxNotebook::DoSetSelection( size_t page, int flags )
 {
     wxCHECK_MSG( m_widget != NULL, -1, wxT("invalid notebook") );
 
@@ -425,10 +439,23 @@ int wxNotebook::SetSelection( size_t page )
 
     int selOld = GetSelection();
 
+    if ( !(flags & SetSelection_SendEvent) )
+        m_skipNextPageChangeEvent = true;
+
     // cache the selection
     m_selection = page;
     gtk_notebook_set_page( GTK_NOTEBOOK(m_widget), page );
 
+#ifdef __WXDEBUG__
+    if ( !(flags & SetSelection_SendEvent) )
+    {
+            // gtk_notebook_set_current_page will emit the switch-page signal which will be
+            // caught by our gtk_notebook_page_change_callback which should have reset the
+            // flag to false:
+        wxASSERT(!m_skipNextPageChangeEvent);
+    }
+#endif // __WXDEBUG__
+
     wxNotebookPage *client = GetPage(page);
     if ( client )
         client->SetFocus();
diff --git a/src/mac/carbon/notebmac.cpp b/src/mac/carbon/notebmac.cpp
index 414bc978f9..9d90682bc0 100644
--- a/src/mac/carbon/notebmac.cpp
+++ b/src/mac/carbon/notebmac.cpp
@@ -160,25 +160,27 @@ wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const
     return DoGetSizeFromClientSize( sizePage );
 }
 
-int wxNotebook::SetSelection(size_t nPage)
+int wxNotebook::DoSetSelection(size_t nPage, int flags = 0)
 {
-    wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("SetSelection: invalid notebook page") );
+    wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("DoSetSelection: invalid notebook page") );
 
     if ( int(nPage) != m_nSelection )
     {
-        wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, m_windowId);
-        event.SetSelection(nPage);
-        event.SetOldSelection(m_nSelection);
-        event.SetEventObject(this);
-        if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
+        if (flags & SetSelection_SendEvent)
         {
-            // program allows the page change
-            event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED);
-            (void)GetEventHandler()->ProcessEvent(event);
+            wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, m_windowId);
+            event.SetSelection(nPage);
+            event.SetOldSelection(m_nSelection);
+            event.SetEventObject(this);
+            if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
+            {
+                // program allows the page change
+                event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED);
+                (void)GetEventHandler()->ProcessEvent(event);
 
-            ChangePage(m_nSelection, nPage);
+                ChangePage(m_nSelection, nPage);
+            }
         }
-    }
 
     return m_nSelection;
 }
@@ -226,6 +228,11 @@ bool wxNotebook::SetPageImage(size_t nPage, int nImage)
 
         MacSetupTabs() ;
     }
+        else
+        {
+            ChangePage(m_nSelection, nPage);
+        }
+    }
 
     return true;
 }
diff --git a/src/msw/notebook.cpp b/src/msw/notebook.cpp
index cd19ed2b0d..1efd29f383 100644
--- a/src/msw/notebook.cpp
+++ b/src/msw/notebook.cpp
@@ -462,6 +462,44 @@ int wxNotebook::SetSelection(size_t nPage)
     return m_nSelection;
 }
 
+void wxNotebook::UpdateSelection(size_t newsel)
+{
+    if ( m_nSelection != -1 )
+        m_pages[m_nSelection]->Show(false);
+
+    if ( newsel != -1 )
+    {
+        wxNotebookPage *pPage = m_pages[newsel];
+        pPage->Show(true);
+    }
+
+    // Changing the page should give the focus to it but, as per bug report
+    // http://sf.net/tracker/index.php?func=detail&aid=1150659&group_id=9863&atid=109863,
+    // we should not set the focus to it directly since it erroneously
+    // selects radio buttons and breaks keyboard handling for a notebook's
+    // scroll buttons. So give focus to the notebook and not the page.
+
+    // but don't do this is the notebook is hidden
+    if ( ::IsWindowVisible(GetHwnd()) )
+        SetFocus();
+
+    m_nSelection = newsel;
+}
+
+int wxNotebook::ChangeSelection(size_t nPage)
+{
+    wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("notebook page out of range") );
+
+    if ( int(nPage) != m_nSelection )
+    {
+        TabCtrl_SetCurSel(GetHwnd(), nPage);
+
+        UpdateSelection(nPage);
+    }
+
+    return m_nSelection;
+}
+
 bool wxNotebook::SetPageText(size_t nPage, const wxString& strText)
 {
     wxCHECK_MSG( IS_VALID_PAGE(nPage), false, wxT("notebook page out of range") );
@@ -1030,35 +1068,14 @@ void wxNotebook::OnSize(wxSizeEvent& event)
 
 void wxNotebook::OnSelChange(wxNotebookEvent& event)
 {
-  // is it our tab control?
-  if ( event.GetEventObject() == this )
-  {
-      int sel = event.GetOldSelection();
-      if ( sel != -1 )
-        m_pages[sel]->Show(false);
-
-      sel = event.GetSelection();
-      if ( sel != -1 )
-      {
-        wxNotebookPage *pPage = m_pages[sel];
-        pPage->Show(true);
-      }
-
-      // Changing the page should give the focus to it but, as per bug report
-      // http://sf.net/tracker/index.php?func=detail&aid=1150659&group_id=9863&atid=109863,
-      // we should not set the focus to it directly since it erroneously
-      // selects radio buttons and breaks keyboard handling for a notebook's
-      // scroll buttons. So give focus to the notebook and not the page.
-
-      // but don't do this is the notebook is hidden
-      if ( ::IsWindowVisible(GetHwnd()) )
-        SetFocus();
-
-      m_nSelection = sel;
-  }
+    // is it our tab control?
+    if ( event.GetEventObject() == this )
+    {
+        UpdateSelection(event.GetSelection());
+    }
 
-  // we want to give others a chance to process this message as well
-  event.Skip();
+    // we want to give others a chance to process this message as well
+    event.Skip();
 }
 
 void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
diff --git a/src/os2/notebook.cpp b/src/os2/notebook.cpp
index 26f5212468..e0051d4fd4 100644
--- a/src/os2/notebook.cpp
+++ b/src/os2/notebook.cpp
@@ -243,6 +243,22 @@ int wxNotebook::SetSelection( size_t nPage )
     return nPage;
 } // end of wxNotebook::SetSelection
 
+int wxNotebook::ChangeSelection( size_t nPage )
+{
+    wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("notebook page out of range") );
+
+    if (nPage != (size_t)m_nSelection)
+    {
+        ::WinSendMsg( GetHWND()
+                ,BKM_TURNTOPAGE
+                ,MPFROMLONG((ULONG)m_alPageId[nPage])
+                        ,(MPARAM)0
+                    );
+    }
+    m_nSelection = nPage;
+    return nPage;
+}
+
 bool wxNotebook::SetPageText( size_t nPage,
                               const wxString& rsStrText )
 {
diff --git a/src/palmos/notebook.cpp b/src/palmos/notebook.cpp
index 0fb00011a3..2f73ee9e9d 100644
--- a/src/palmos/notebook.cpp
+++ b/src/palmos/notebook.cpp
@@ -194,6 +194,11 @@ int wxNotebook::SetSelection(size_t nPage)
     return 0;
 }
 
+int wxNotebook::ChangeSelection(size_t nPage)
+{
+    return 0;
+}
+
 bool wxNotebook::SetPageText(size_t nPage, const wxString& strText)
 {
     return false;
diff --git a/src/univ/notebook.cpp b/src/univ/notebook.cpp
index be60137093..7a72aaf22e 100644
--- a/src/univ/notebook.cpp
+++ b/src/univ/notebook.cpp
@@ -233,7 +233,7 @@ wxNotebook::~wxNotebook()
 // wxNotebook page switching
 // ----------------------------------------------------------------------------
 
-int wxNotebook::SetSelection(size_t nPage)
+int wxNotebook::DoSetSelection(size_t nPage, int flags = 0)
 {
     wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, _T("invalid notebook page") );
 
@@ -243,15 +243,18 @@ int wxNotebook::SetSelection(size_t nPage)
         return m_sel;
     }
 
-    // event handling
     wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, m_windowId);
-    event.SetSelection(nPage);
-    event.SetOldSelection(m_sel);
-    event.SetEventObject(this);
-    if ( GetEventHandler()->ProcessEvent(event) && !event.IsAllowed() )
+    if (flags & SetSelection_SendEvent)
     {
-        // program doesn't allow the page change
-        return m_sel;
+        // event handling
+        event.SetSelection(nPage);
+        event.SetOldSelection(m_sel);
+        event.SetEventObject(this);
+        if ( GetEventHandler()->ProcessEvent(event) && !event.IsAllowed() )
+        {
+            // program doesn't allow the page change
+            return m_sel;
+        }
     }
 
     // we need to change m_sel first, before calling RefreshTab() below as
@@ -297,9 +300,12 @@ int wxNotebook::SetSelection(size_t nPage)
         m_pages[m_sel]->Show();
     }
 
-    // event handling
-    event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED);
-    GetEventHandler()->ProcessEvent(event);
+    if (flags & SetSelection_SendEvent)
+    {
+        // event handling
+        event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED);
+        GetEventHandler()->ProcessEvent(event);
+    }
 
     return selOld;
 }
-- 
2.50.0

