1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/generic/notebook.cpp
3 // Purpose:     generic implementation of wxNotebook
4 // Author:      Julian Smart
5 // Modified by:
6 // Created:     17/09/98
7 // Copyright:   (c) Julian Smart
8 // Licence:     wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10 
11 // ============================================================================
12 // declarations
13 // ============================================================================
14 
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18 
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21 
22 #ifdef __BORLANDC__
23     #pragma hdrstop
24 #endif
25 
26 #if wxUSE_NOTEBOOK
27 
28 #include  "wx/notebook.h"
29 
30 #ifndef WX_PRECOMP
31     #include "wx/string.h"
32     #include "wx/log.h"
33     #include  "wx/dcclient.h"
34     #include  "wx/settings.h"
35 #endif
36 
37 #include  "wx/imaglist.h"
38 #include  "wx/generic/tabg.h"
39 
40 // ----------------------------------------------------------------------------
41 // macros
42 // ----------------------------------------------------------------------------
43 
44 // check that the page index is valid
45 #define IS_VALID_PAGE(nPage) ((nPage) < GetPageCount())
46 
47 // ----------------------------------------------------------------------------
48 // event table
49 // ----------------------------------------------------------------------------
50 
51 BEGIN_EVENT_TABLE(wxNotebook, wxBookCtrlBase)
52     EVT_NOTEBOOK_PAGE_CHANGED(wxID_ANY, wxNotebook::OnSelChange)
53     EVT_SIZE(wxNotebook::OnSize)
54     EVT_PAINT(wxNotebook::OnPaint)
55     EVT_MOUSE_EVENTS(wxNotebook::OnMouseEvent)
56     EVT_SET_FOCUS(wxNotebook::OnSetFocus)
57     EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey)
58 END_EVENT_TABLE()
59 
60 // ============================================================================
61 // implementation
62 // ============================================================================
63 
64 // ============================================================================
65 // Private class
66 // ============================================================================
67 
68 WX_DECLARE_HASH_MAP(int, wxNotebookPage*, wxIntegerHash, wxIntegerEqual,
69                     wxIntToNotebookPageHashMap);
70 
71 WX_DECLARE_HASH_MAP(wxNotebookPage*, int, wxPointerHash, wxPointerEqual,
72                     wxNotebookPageToIntHashMap);
73 
74 // This reuses wxTabView to draw the tabs.
75 class WXDLLEXPORT wxNotebookTabView: public wxTabView
76 {
77 DECLARE_DYNAMIC_CLASS(wxNotebookTabView)
78 public:
79     wxNotebookTabView(wxNotebook* notebook, long style = wxTAB_STYLE_DRAW_BOX | wxTAB_STYLE_COLOUR_INTERIOR);
80     virtual ~wxNotebookTabView(void);
81 
82     // Called when a tab is activated
83     virtual void OnTabActivate(int activateId, int deactivateId);
84     // Allows vetoing
85     virtual bool OnTabPreActivate(int activateId, int deactivateId);
86 
87     // map integer ids used by wxTabView to wxNotebookPage pointers
88     int GetId(wxNotebookPage *page);
GetPage(int id)89     wxNotebookPage *GetPage(int id) { return m_idToPage[id]; }
90 
91 protected:
92     wxNotebook* m_notebook;
93 
94 private:
95     wxIntToNotebookPageHashMap m_idToPage;
96     wxNotebookPageToIntHashMap m_pageToId;
97     int m_nextid;
98 };
99 
GetPageId(wxTabView * tabview,wxNotebookPage * page)100 static int GetPageId(wxTabView *tabview, wxNotebookPage *page)
101 {
102     return static_cast<wxNotebookTabView*>(tabview)->GetId(page);
103 }
104 
105 // ----------------------------------------------------------------------------
106 // wxNotebook construction
107 // ----------------------------------------------------------------------------
108 
109 // common part of all ctors
Init()110 void wxNotebook::Init()
111 {
112     m_tabView = NULL;
113     m_selection = -1;
114 }
115 
116 // default for dynamic class
wxNotebook()117 wxNotebook::wxNotebook()
118 {
119     Init();
120 }
121 
122 // the same arguments as for wxControl
wxNotebook(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)123 wxNotebook::wxNotebook(wxWindow *parent,
124                        wxWindowID id,
125                        const wxPoint& pos,
126                        const wxSize& size,
127                        long style,
128                        const wxString& name)
129 {
130     Init();
131 
132     Create(parent, id, pos, size, style, name);
133 }
134 
135 // Create() function
Create(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)136 bool wxNotebook::Create(wxWindow *parent,
137                         wxWindowID id,
138                         const wxPoint& pos,
139                         const wxSize& size,
140                         long style,
141                         const wxString& name)
142 {
143     // base init
144     SetName(name);
145 
146     if ( (style & wxBK_ALIGN_MASK) == wxBK_DEFAULT )
147         style |= wxBK_TOP;
148 
149     m_windowId = id == wxID_ANY ? NewControlId() : id;
150 
151     if (!wxControl::Create(parent, id, pos, size, style|wxNO_BORDER, wxDefaultValidator, name))
152         return false;
153 
154     SetTabView(new wxNotebookTabView(this));
155 
156     return true;
157 }
158 
159 // dtor
~wxNotebook()160 wxNotebook::~wxNotebook()
161 {
162     delete m_tabView;
163 }
164 
165 // ----------------------------------------------------------------------------
166 // wxNotebook accessors
167 // ----------------------------------------------------------------------------
GetRowCount() const168 int wxNotebook::GetRowCount() const
169 {
170     // TODO
171     return 0;
172 }
173 
SetSelection(size_t nPage)174 int wxNotebook::SetSelection(size_t nPage)
175 {
176     wxASSERT( IS_VALID_PAGE(nPage) );
177 
178     wxNotebookPage* pPage = GetPage(nPage);
179 
180     m_tabView->SetTabSelection(GetPageId(m_tabView, pPage));
181 
182     // TODO
183     return 0;
184 }
185 
ChangeSelection(size_t nPage)186 int wxNotebook::ChangeSelection(size_t nPage)
187 {
188     // FIXME: currently it does generate events too
189     return SetSelection(nPage);
190 }
191 
192 #if 0
193 void wxNotebook::AdvanceSelection(bool bForward)
194 {
195     int nSel = GetSelection();
196     int nMax = GetPageCount() - 1;
197     if ( bForward )
198         SetSelection(nSel == nMax ? 0 : nSel + 1);
199     else
200         SetSelection(nSel == 0 ? nMax : nSel - 1);
201 }
202 #endif
203 
SetPageText(size_t nPage,const wxString & strText)204 bool wxNotebook::SetPageText(size_t nPage, const wxString& strText)
205 {
206     wxASSERT( IS_VALID_PAGE(nPage) );
207 
208     wxNotebookPage* page = GetPage(nPage);
209     if (page)
210     {
211         m_tabView->SetTabText(GetPageId(m_tabView, page), strText);
212         Refresh();
213         return true;
214     }
215 
216     return false;
217 }
218 
GetPageText(size_t nPage) const219 wxString wxNotebook::GetPageText(size_t nPage) const
220 {
221     wxASSERT( IS_VALID_PAGE(nPage) );
222 
223     wxNotebookPage* page = ((wxNotebook*)this)->GetPage(nPage);
224     if (page)
225         return m_tabView->GetTabText(GetPageId(m_tabView, page));
226     else
227         return wxEmptyString;
228 }
229 
GetPageImage(size_t WXUNUSED_UNLESS_DEBUG (nPage)) const230 int wxNotebook::GetPageImage(size_t WXUNUSED_UNLESS_DEBUG(nPage)) const
231 {
232     wxASSERT( IS_VALID_PAGE(nPage) );
233 
234     // TODO
235     return 0;
236 }
237 
SetPageImage(size_t WXUNUSED_UNLESS_DEBUG (nPage),int WXUNUSED (nImage))238 bool wxNotebook::SetPageImage(size_t WXUNUSED_UNLESS_DEBUG(nPage),
239                               int WXUNUSED(nImage))
240 {
241     wxASSERT( IS_VALID_PAGE(nPage) );
242 
243     // TODO
244     return false;
245 }
246 
247 // set the size (the same for all pages)
SetPageSize(const wxSize & WXUNUSED (size))248 void wxNotebook::SetPageSize(const wxSize& WXUNUSED(size))
249 {
250     // TODO
251 }
252 
253 // set the padding between tabs (in pixels)
SetPadding(const wxSize & WXUNUSED (padding))254 void wxNotebook::SetPadding(const wxSize& WXUNUSED(padding))
255 {
256     // TODO
257 }
258 
259 // set the size of the tabs for wxNB_FIXEDWIDTH controls
SetTabSize(const wxSize & WXUNUSED (sz))260 void wxNotebook::SetTabSize(const wxSize& WXUNUSED(sz))
261 {
262     // TODO
263 }
264 
265 // ----------------------------------------------------------------------------
266 // wxNotebook operations
267 // ----------------------------------------------------------------------------
268 
269 // remove one page from the notebook and delete it
DeletePage(size_t nPage)270 bool wxNotebook::DeletePage(size_t nPage)
271 {
272     wxCHECK( IS_VALID_PAGE(nPage), false );
273 
274     if (m_selection != -1)
275     {
276         m_pages[m_selection]->Show(false);
277         m_pages[m_selection]->Lower();
278     }
279 
280     wxNotebookPage* pPage = GetPage(nPage);
281 
282     m_tabView->RemoveTab(GetPageId(m_tabView, pPage));
283 
284     m_pages.Remove(pPage);
285     delete pPage;
286 
287     if (m_pages.GetCount() == 0)
288     {
289         m_selection = -1;
290         m_tabView->SetTabSelection(-1, false);
291     }
292     else if (m_selection > -1)
293     {
294         m_selection = -1;
295 
296         m_tabView->SetTabSelection(GetPageId(m_tabView, GetPage(0)), false);
297 
298         if (m_selection != 0)
299             ChangePage(-1, 0);
300     }
301 
302     RefreshLayout(false);
303 
304     return true;
305 }
306 
DeletePage(wxNotebookPage * page)307 bool wxNotebook::DeletePage(wxNotebookPage* page)
308 {
309     int pagePos = FindPagePosition(page);
310     if (pagePos > -1)
311         return DeletePage(pagePos);
312     else
313         return false;
314 }
315 
RemovePage(size_t nPage)316 bool wxNotebook::RemovePage(size_t nPage)
317 {
318     return DoRemovePage(nPage) != NULL;
319 }
320 
321 // remove one page from the notebook
DoRemovePage(size_t nPage)322 wxWindow* wxNotebook::DoRemovePage(size_t nPage)
323 {
324     wxCHECK( IS_VALID_PAGE(nPage), NULL );
325 
326     m_pages[nPage]->Show(false);
327     //    m_pages[nPage]->Lower();
328 
329     wxNotebookPage* pPage = GetPage(nPage);
330 
331     m_tabView->RemoveTab(GetPageId(m_tabView, pPage));
332 
333     m_pages.Remove(pPage);
334 
335     if (m_pages.GetCount() == 0)
336     {
337       m_selection = -1;
338       m_tabView->SetTabSelection(-1, true);
339     }
340     else if (m_selection > -1)
341     {
342       // Only change the selection if the page we
343       // deleted was the selection.
344       if (nPage == (size_t)m_selection)
345       {
346          m_selection = -1;
347          // Select the first tab. Generates a ChangePage.
348          m_tabView->SetTabSelection(0, true);
349       }
350       else
351       {
352         // We must adjust which tab we think is selected.
353         // If greater than the page we deleted, it must be moved down
354         // a notch.
355         if (size_t(m_selection) > nPage)
356           m_selection -- ;
357       }
358     }
359 
360     RefreshLayout(false);
361 
362     return pPage;
363 }
364 
RemovePage(wxNotebookPage * page)365 bool wxNotebook::RemovePage(wxNotebookPage* page)
366 {
367     int pagePos = FindPagePosition(page);
368     if (pagePos > -1)
369         return RemovePage(pagePos);
370     else
371         return false;
372 }
373 
374 // Find the position of the wxNotebookPage, -1 if not found.
FindPagePosition(wxNotebookPage * page) const375 int wxNotebook::FindPagePosition(wxNotebookPage* page) const
376 {
377     size_t nPageCount = GetPageCount();
378     size_t nPage;
379     for ( nPage = 0; nPage < nPageCount; nPage++ )
380         if (m_pages[nPage] == page)
381             return nPage;
382     return -1;
383 }
384 
385 // remove all pages
DeleteAllPages()386 bool wxNotebook::DeleteAllPages()
387 {
388     m_tabView->ClearTabs(true);
389 
390     size_t nPageCount = GetPageCount();
391     size_t nPage;
392     for ( nPage = 0; nPage < nPageCount; nPage++ )
393         delete m_pages[nPage];
394 
395     m_pages.Clear();
396 
397     return true;
398 }
399 
400 // same as AddPage() but does it at given position
InsertPage(size_t nPage,wxNotebookPage * pPage,const wxString & strText,bool bSelect,int WXUNUSED (imageId))401 bool wxNotebook::InsertPage(size_t nPage,
402                             wxNotebookPage *pPage,
403                             const wxString& strText,
404                             bool bSelect,
405                             int WXUNUSED(imageId))
406 {
407     wxASSERT( pPage != NULL );
408     wxCHECK( IS_VALID_PAGE(nPage) || nPage == GetPageCount(), false );
409 
410     m_tabView->AddTab(GetPageId(m_tabView, pPage), strText);
411 
412     if (!bSelect)
413       pPage->Show(false);
414 
415     // save the pointer to the page
416     m_pages.Insert(pPage, nPage);
417 
418     if (bSelect)
419     {
420         // This will cause ChangePage to be called, via OnSelPage
421 
422         m_tabView->SetTabSelection(GetPageId(m_tabView, pPage), true);
423     }
424 
425     // some page must be selected: either this one or the first one if there is
426     // still no selection
427     if ( m_selection == -1 )
428       ChangePage(-1, 0);
429 
430     RefreshLayout(false);
431 
432     return true;
433 }
434 
435 // ----------------------------------------------------------------------------
436 // wxNotebook callbacks
437 // ----------------------------------------------------------------------------
438 
439 // @@@ OnSize() is used for setting the font when it's called for the first
440 //     time because doing it in ::Create() doesn't work (for unknown reasons)
OnSize(wxSizeEvent & event)441 void wxNotebook::OnSize(wxSizeEvent& event)
442 {
443     static bool s_bFirstTime = true;
444     if ( s_bFirstTime ) {
445         // TODO: any first-time-size processing.
446         s_bFirstTime = false;
447     }
448 
449     RefreshLayout();
450 
451     // Processing continues to next OnSize
452     event.Skip();
453 }
454 
455 // This was supposed to cure the non-display of the notebook
456 // until the user resizes the window.
457 // What's going on?
OnInternalIdle()458 void wxNotebook::OnInternalIdle()
459 {
460     wxWindow::OnInternalIdle();
461 
462 #if 0
463     static bool s_bFirstTime = true;
464     if ( s_bFirstTime ) {
465       /*
466       wxSize sz(GetSize());
467       sz.x ++;
468       SetSize(sz);
469       sz.x --;
470       SetSize(sz);
471       */
472 
473       /*
474       wxSize sz(GetSize());
475       wxSizeEvent sizeEvent(sz, GetId());
476       sizeEvent.SetEventObject(this);
477       GetEventHandler()->ProcessEvent(sizeEvent);
478       Refresh();
479       */
480       s_bFirstTime = false;
481     }
482 #endif
483 }
484 
485 // Implementation: calculate the layout of the view rect
486 // and resize the children if required
RefreshLayout(bool force)487 bool wxNotebook::RefreshLayout(bool force)
488 {
489     if (m_tabView)
490     {
491         wxRect oldRect = m_tabView->GetViewRect();
492 
493         int cw, ch;
494         GetClientSize(& cw, & ch);
495 
496         int tabHeight = m_tabView->GetTotalTabHeight();
497         wxRect rect;
498         rect.x = 4;
499         rect.y = tabHeight + 4;
500         rect.width = cw - 8;
501         rect.height = ch - 4 - rect.y ;
502 
503         m_tabView->SetViewRect(rect);
504 
505         m_tabView->LayoutTabs();
506 
507         // Need to do it a 2nd time to get the tab height with
508         // the new view width, since changing the view width changes the
509         // tab layout.
510         tabHeight = m_tabView->GetTotalTabHeight();
511         rect.x = 4;
512         rect.y = tabHeight + 4;
513         rect.width = cw - 8;
514         rect.height = ch - 4 - rect.y ;
515 
516         m_tabView->SetViewRect(rect);
517 
518         m_tabView->LayoutTabs();
519 
520         if (!force && (rect == oldRect))
521           return false;
522 
523         // fit the notebook page to the tab control's display area
524 
525         size_t nCount = m_pages.Count();
526         for ( size_t nPage = 0; nPage < nCount; nPage++ ) {
527             wxNotebookPage *pPage = m_pages[nPage];
528             wxRect clientRect = GetAvailableClientSize();
529             if (pPage->IsShown())
530             {
531                 pPage->SetSize(clientRect.x, clientRect.y, clientRect.width, clientRect.height);
532                 if ( pPage->GetAutoLayout() )
533                    pPage->Layout();
534             }
535         }
536         Refresh();
537     }
538     return true;
539 }
540 
OnSelChange(wxBookCtrlEvent & event)541 void wxNotebook::OnSelChange(wxBookCtrlEvent& event)
542 {
543     // is it our tab control?
544     if ( event.GetEventObject() == this )
545     {
546         if (event.GetSelection() != m_selection)
547           ChangePage(event.GetOldSelection(), event.GetSelection());
548     }
549 
550     // we want to give others a chance to process this message as well
551     event.Skip();
552 }
553 
OnSetFocus(wxFocusEvent & event)554 void wxNotebook::OnSetFocus(wxFocusEvent& event)
555 {
556     // set focus to the currently selected page if any
557     if ( m_selection != -1 )
558         m_pages[m_selection]->SetFocus();
559 
560     event.Skip();
561 }
562 
OnNavigationKey(wxNavigationKeyEvent & event)563 void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
564 {
565     if ( event.IsWindowChange() )
566     {
567         // change pages
568         AdvanceSelection(event.GetDirection());
569     }
570     else {
571         // pass to the parent
572         if ( GetParent() )
573         {
574             event.SetCurrentFocus(this);
575             GetParent()->ProcessWindowEvent(event);
576         }
577     }
578 }
579 
580 // ----------------------------------------------------------------------------
581 // wxNotebook base class virtuals
582 // ----------------------------------------------------------------------------
583 
584 // override these 2 functions to do nothing: everything is done in OnSize
585 
SetConstraintSizes(bool)586 void wxNotebook::SetConstraintSizes(bool /* recurse */)
587 {
588     // don't set the sizes of the pages - their correct size is not yet known
589     wxControl::SetConstraintSizes(false);
590 }
591 
DoPhase(int)592 bool wxNotebook::DoPhase(int /* nPhase */)
593 {
594     return true;
595 }
596 
Command(wxCommandEvent & WXUNUSED (event))597 void wxNotebook::Command(wxCommandEvent& WXUNUSED(event))
598 {
599     wxFAIL_MSG(wxT("wxNotebook::Command not implemented"));
600 }
601 
602 // ----------------------------------------------------------------------------
603 // wxNotebook helper functions
604 // ----------------------------------------------------------------------------
605 
606 // hide the currently active panel and show the new one
ChangePage(int nOldSel,int nSel)607 void wxNotebook::ChangePage(int nOldSel, int nSel)
608 {
609   //  cout << "ChangePage: " << nOldSel << ", " << nSel << "\n";
610     wxASSERT( nOldSel != nSel ); // impossible
611 
612     if ( nOldSel != -1 ) {
613         m_pages[nOldSel]->Show(false);
614         m_pages[nOldSel]->Lower();
615     }
616 
617     wxNotebookPage *pPage = m_pages[nSel];
618 
619     wxRect clientRect = GetAvailableClientSize();
620     pPage->SetSize(clientRect.x, clientRect.y, clientRect.width, clientRect.height);
621 
622     Refresh();
623 
624     pPage->Show(true);
625     pPage->Raise();
626     pPage->SetFocus();
627 
628     m_selection = nSel;
629 }
630 
OnMouseEvent(wxMouseEvent & event)631 void wxNotebook::OnMouseEvent(wxMouseEvent& event)
632 {
633   if (m_tabView)
634     m_tabView->OnEvent(event);
635 }
636 
OnPaint(wxPaintEvent & WXUNUSED (event))637 void wxNotebook::OnPaint(wxPaintEvent& WXUNUSED(event) )
638 {
639     wxPaintDC dc(this);
640     if (m_tabView)
641         m_tabView->Draw(dc);
642 }
643 
CalcSizeFromPage(const wxSize & sizePage) const644 wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const
645 {
646     // MBN: since the total tab height is really a function of the
647     // width, this should really call
648     // GetTotalTabHeightPretendingWidthIs(), but the current
649     // implementation will suffice, provided the wxNotebook has been
650     // created with a sensible initial width.
651     return wxSize( sizePage.x + 12,
652                    sizePage.y + m_tabView->GetTotalTabHeight() + 6 + 4 );
653 }
654 
GetAvailableClientSize()655 wxRect wxNotebook::GetAvailableClientSize()
656 {
657     int cw, ch;
658     GetClientSize(& cw, & ch);
659 
660     int tabHeight = m_tabView->GetTotalTabHeight();
661 
662     // TODO: these margins should be configurable.
663     wxRect rect;
664     rect.x = 6;
665     rect.y = tabHeight + 6;
666     rect.width = cw - 12;
667     rect.height = ch - 4 - rect.y ;
668 
669     return rect;
670 }
671 
672 /*
673  * wxNotebookTabView
674  */
675 
IMPLEMENT_CLASS(wxNotebookTabView,wxTabView)676 IMPLEMENT_CLASS(wxNotebookTabView, wxTabView)
677 
678 wxNotebookTabView::wxNotebookTabView(wxNotebook *notebook, long style)
679     : wxTabView(style), m_nextid(1)
680 {
681   m_notebook = notebook;
682 
683   m_notebook->SetTabView(this);
684 
685   SetWindow(m_notebook);
686 }
687 
~wxNotebookTabView(void)688 wxNotebookTabView::~wxNotebookTabView(void)
689 {
690 }
691 
GetId(wxNotebookPage * page)692 int wxNotebookTabView::GetId(wxNotebookPage *page)
693 {
694     int& id = m_pageToId[page];
695 
696     if (!id)
697     {
698         id = m_nextid++;
699         m_idToPage[id] = page;
700     }
701 
702     return id;
703 }
704 
705 // Called when a tab is activated
OnTabActivate(int activateId,int deactivateId)706 void wxNotebookTabView::OnTabActivate(int activateId, int deactivateId)
707 {
708   if (!m_notebook)
709     return;
710 
711   wxBookCtrlEvent event(wxEVT_NOTEBOOK_PAGE_CHANGED, m_notebook->GetId());
712 
713   // Translate from wxTabView's ids (which aren't position-dependent)
714   // to wxNotebook's (which are).
715   wxNotebookPage* pActive = GetPage(activateId);
716   wxNotebookPage* pDeactive = GetPage(deactivateId);
717 
718   int activatePos = m_notebook->FindPagePosition(pActive);
719   int deactivatePos = m_notebook->FindPagePosition(pDeactive);
720 
721   event.SetEventObject(m_notebook);
722   event.SetSelection(activatePos);
723   event.SetOldSelection(deactivatePos);
724   m_notebook->GetEventHandler()->ProcessEvent(event);
725 }
726 
727 // Allows Vetoing
OnTabPreActivate(int activateId,int deactivateId)728 bool wxNotebookTabView::OnTabPreActivate(int activateId, int deactivateId)
729 {
730   bool retval = true;
731 
732   if (m_notebook)
733   {
734     wxBookCtrlEvent event(wxEVT_NOTEBOOK_PAGE_CHANGING, m_notebook->GetId());
735 
736     // Translate from wxTabView's ids (which aren't position-dependent)
737     // to wxNotebook's (which are).
738     wxNotebookPage* pActive = GetPage(activateId);
739     wxNotebookPage* pDeactive = GetPage(deactivateId);
740 
741     int activatePos = m_notebook->FindPagePosition(pActive);
742     int deactivatePos = m_notebook->FindPagePosition(pDeactive);
743 
744     event.SetEventObject(m_notebook);
745     event.SetSelection(activatePos);
746     event.SetOldSelection(deactivatePos);
747     if (m_notebook->GetEventHandler()->ProcessEvent(event))
748     {
749       retval = event.IsAllowed();
750     }
751   }
752   return retval;
753 }
754 
755 #endif // wxUSE_NOTEBOOK
756