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