1 /////////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     implementation of wxNotebook 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  17   #include  <wx/string.h> 
  21 #include  <wx/imaglist.h> 
  23 #include  <wx/control.h> 
  24 #include  <wx/notebook.h> 
  26 #include  <wx/os2/private.h> 
  29 // ---------------------------------------------------------------------------- 
  31 // ---------------------------------------------------------------------------- 
  32 // check that the page index is valid 
  33 #define IS_VALID_PAGE(nPage) (((nPage) >= 0) && ((nPage) < GetPageCount())) 
  36 #define m_hwnd    (HWND)GetHWND() 
  38 // ---------------------------------------------------------------------------- 
  40 // ---------------------------------------------------------------------------- 
  42 // This is a work-around for missing defines in gcc-2.95 headers 
  44     #define TCS_RIGHT       0x0002 
  48     #define TCS_VERTICAL    0x0080 
  52     #define TCS_BOTTOM      TCS_RIGHT 
  55 // ---------------------------------------------------------------------------- 
  57 // ---------------------------------------------------------------------------- 
  59 DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
) 
  60 DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING
) 
  62 BEGIN_EVENT_TABLE(wxNotebook
, wxControl
) 
  63     EVT_NOTEBOOK_PAGE_CHANGED(-1, wxNotebook::OnSelChange
) 
  64     EVT_SIZE(wxNotebook::OnSize
) 
  65     EVT_SET_FOCUS(wxNotebook::OnSetFocus
) 
  66     EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey
) 
  69 IMPLEMENT_DYNAMIC_CLASS(wxNotebook
, wxControl
) 
  70 IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent
, wxNotifyEvent
) 
  72 // ============================================================================ 
  74 // ============================================================================ 
  76 // ---------------------------------------------------------------------------- 
  77 // wxNotebook construction 
  78 // ---------------------------------------------------------------------------- 
  80 // common part of all ctors 
  81 void wxNotebook::Init() 
  87 // default for dynamic class 
  88 wxNotebook::wxNotebook() 
  93 // the same arguments as for wxControl 
  94 wxNotebook::wxNotebook(wxWindow 
*parent
, 
 103     Create(parent
, id
, pos
, size
, style
, name
); 
 107 bool wxNotebook::Create(wxWindow 
*parent
, 
 112                         const wxString
& name
) 
 115   if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) ) 
 119 // TODO:  m_backgroundColour = wxColour(GetSysColor(COLOR_BTNFACE)); 
 120   m_foregroundColour 
= *wxBLACK 
; 
 125   m_windowStyle = style | wxTAB_TRAVERSAL; 
 127   long tabStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | TCS_TABS; 
 129   if (m_windowStyle & wxCLIP_CHILDREN) 
 130     tabStyle |= WS_CLIPCHILDREN; 
 131   if ( m_windowStyle & wxTC_MULTILINE ) 
 132     tabStyle |= TCS_MULTILINE; 
 133   if ( m_windowStyle & wxBORDER ) 
 134     tabStyle &= WS_BORDER; 
 135   if (m_windowStyle & wxNB_FIXEDWIDTH) 
 136     tabStyle |= TCS_FIXEDWIDTH ; 
 137   if (m_windowStyle & wxNB_BOTTOM) 
 138     tabStyle |= TCS_RIGHT; 
 139   if (m_windowStyle & wxNB_LEFT) 
 140     tabStyle |= TCS_VERTICAL; 
 141   if (m_windowStyle & wxNB_RIGHT) 
 142     tabStyle |= TCS_VERTICAL|TCS_RIGHT; 
 145   if ( !MSWCreate(GetId(), GetParent(), WC_TABCONTROL, 
 146                   this, NULL, pos.x, pos.y, size.x, size.y, 
 152   // Not all compilers recognise SetWindowFont 
 153   ::SendMessage(GetHwnd(), WM_SETFONT, 
 154                 (WPARAM)::GetStockObject(DEFAULT_GUI_FONT), TRUE); 
 157   if ( parent != NULL ) 
 158     parent->AddChild(this); 
 166 wxNotebook::~wxNotebook() 
 170 // ---------------------------------------------------------------------------- 
 171 // wxNotebook accessors 
 172 // ---------------------------------------------------------------------------- 
 173 int wxNotebook::GetPageCount() const 
 175     return m_aPages
.Count(); 
 178 int wxNotebook::GetRowCount() const 
 184 int wxNotebook::SetSelection(int nPage
) 
 186     wxCHECK_MSG( IS_VALID_PAGE(nPage
), -1, wxT("notebook page out of range") ); 
 188     ChangePage(m_nSelection
, nPage
); 
 194 void wxNotebook::AdvanceSelection(bool bForward
) 
 196     int nSel 
= GetSelection(); 
 197     int nMax 
= GetPageCount() - 1; 
 199         SetSelection(nSel 
== nMax 
? 0 : nSel 
+ 1); 
 201         SetSelection(nSel 
== 0 ? nMax 
: nSel 
- 1); 
 204 bool wxNotebook::SetPageText(int nPage
, const wxString
& strText
) 
 206     wxCHECK_MSG( IS_VALID_PAGE(nPage
), FALSE
, wxT("notebook page out of range") ); 
 212 wxString 
wxNotebook::GetPageText(int nPage
) const 
 214     wxCHECK_MSG( IS_VALID_PAGE(nPage
), wxT(""), wxT("notebook page out of range") ); 
 220 int wxNotebook::GetPageImage(int nPage
) const 
 222     wxCHECK_MSG( IS_VALID_PAGE(nPage
), -1, wxT("notebook page out of range") ); 
 228 bool wxNotebook::SetPageImage(int nPage
, int nImage
) 
 230     wxCHECK_MSG( IS_VALID_PAGE(nPage
), FALSE
, wxT("notebook page out of range") ); 
 236 void wxNotebook::SetImageList(wxImageList
* imageList
) 
 238     m_pImageList 
= imageList
; 
 242 void wxNotebook::SetTabSize(const wxSize
& sz
) 
 247 // ---------------------------------------------------------------------------- 
 248 // wxNotebook operations 
 249 // ---------------------------------------------------------------------------- 
 251 void wxNotebook::SetPageSize(const wxSize
& size
) 
 253     // transform the page size into the notebook size 
 255     rc
.xLeft 
= rc
.yTop 
= 0; 
 259 //    TabCtrl_AdjustRect(GetHwnd(), TRUE, &rc); 
 262     SetSize(rc
.xRight 
- rc
.xLeft
, rc
.yBottom 
- rc
.yTop
); 
 265 void wxNotebook::SetPadding(const wxSize
& padding
) 
 267 //    TabCtrl_SetPadding(GetHwnd(), padding.x, padding.y); 
 270 // remove one page from the notebook 
 271 bool wxNotebook::DeletePage(int nPage
) 
 273     wxCHECK_MSG( IS_VALID_PAGE(nPage
), FALSE
, wxT("notebook page out of range") ); 
 275     // TODO: delete native widget page 
 277     delete m_aPages
[nPage
]; 
 278     m_aPages
.RemoveAt(nPage
); 
 283 // remove one page from the notebook, without deleting the window 
 284 bool wxNotebook::RemovePage(int nPage
) 
 286     wxCHECK_MSG( IS_VALID_PAGE(nPage
), FALSE
, wxT("notebook page out of range") ); 
 288     m_aPages
.RemoveAt(nPage
); 
 294 bool wxNotebook::DeleteAllPages() 
 296     // TODO: delete native widget pages 
 298     int nPageCount 
= GetPageCount(); 
 300     for ( nPage 
= 0; nPage 
< nPageCount
; nPage
++ ) 
 301         delete m_aPages
[nPage
]; 
 308 // add a page to the notebook 
 309 bool wxNotebook::AddPage(wxNotebookPage 
*pPage
, 
 310                          const wxString
& strText
, 
 314     return InsertPage(GetPageCount(), pPage
, strText
, bSelect
, imageId
); 
 317 // same as AddPage() but does it at given position 
 318 bool wxNotebook::InsertPage(int nPage
, 
 319                             wxNotebookPage 
*pPage
, 
 320                             const wxString
& strText
, 
 324     wxASSERT( pPage 
!= NULL 
); 
 325     wxCHECK( IS_VALID_PAGE(nPage
) || nPage 
== GetPageCount(), FALSE 
); 
 327     // TODO: insert native widget page 
 329     // save the pointer to the page 
 330     m_aPages
.Insert(pPage
, nPage
); 
 332     // some page must be selected: either this one or the first one if there is 
 333     // still no selection 
 335         m_nSelection 
= nPage
; 
 336     else if ( m_nSelection 
== -1 ) 
 342 // ---------------------------------------------------------------------------- 
 343 // wxNotebook callbacks 
 344 // ---------------------------------------------------------------------------- 
 346 // @@@ OnSize() is used for setting the font when it's called for the first 
 347 //     time because doing it in ::Create() doesn't work (for unknown reasons) 
 348 void wxNotebook::OnSize(wxSizeEvent
& event
) 
 350     static bool s_bFirstTime 
= TRUE
; 
 351     if ( s_bFirstTime 
) { 
 352         // TODO: any first-time-size processing. 
 353         s_bFirstTime 
= FALSE
; 
 356     // TODO: all this may or may not be necessary for your platform 
 358     // emulate page change (it's esp. important to do it first time because 
 359     // otherwise our page would stay invisible) 
 360     int nSel 
= m_nSelection
; 
 364     // fit the notebook page to the tab control's display area 
 368     unsigned int nCount 
= m_aPages
.Count(); 
 369     for ( unsigned int nPage 
= 0; nPage 
< nCount
; nPage
++ ) { 
 370         wxNotebookPage 
*pPage 
= m_aPages
[nPage
]; 
 371         pPage
->SetSize(0, 0, w
, h
); 
 372 #if wxUSE_CONSTRAINTS 
 373         if ( pPage
->GetAutoLayout() ) 
 375 #endif //wxUSE_CONSTRAINTS 
 379     // Processing continues to next OnSize 
 383 void wxNotebook::OnSelChange(wxNotebookEvent
& event
) 
 385     // is it our tab control? 
 386     if ( event
.GetEventObject() == this ) 
 388         int sel 
= event
.GetOldSelection(); 
 390             m_aPages
[sel
]->Show(FALSE
); 
 392         sel 
= event
.GetSelection(); 
 395             wxNotebookPage 
*pPage 
= m_aPages
[sel
]; 
 402     // we want to give others a chance to process this message as well 
 406 void wxNotebook::OnSetFocus(wxFocusEvent
& event
) 
 408     // set focus to the currently selected page if any 
 409     if ( m_nSelection 
!= -1 ) 
 410         m_aPages
[m_nSelection
]->SetFocus(); 
 415 void wxNotebook::OnNavigationKey(wxNavigationKeyEvent
& event
) 
 417     if ( event
.IsWindowChange() ) { 
 419         AdvanceSelection(event
.GetDirection()); 
 422         // pass to the parent 
 424             event
.SetCurrentFocus(this); 
 425             GetParent()->ProcessEvent(event
); 
 430 // ---------------------------------------------------------------------------- 
 431 // wxNotebook base class virtuals 
 432 // ---------------------------------------------------------------------------- 
 434 // override these 2 functions to do nothing: everything is done in OnSize 
 436 void wxNotebook::SetConstraintSizes(bool /* recurse */) 
 438 #if wxUSE_CONSTRAINTS 
 439     // don't set the sizes of the pages - their correct size is not yet known 
 440     wxControl::SetConstraintSizes(FALSE
); 
 444 bool wxNotebook::DoPhase(int /* nPhase */) 
 449 bool wxNotebook::OS2OnNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
* result
) 
 451   wxNotebookEvent 
event(wxEVT_NULL
, m_windowId
); 
 454   NMHDR* hdr = (NMHDR *)lParam; 
 455   switch ( hdr->code ) { 
 457       event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED); 
 460     case TCN_SELCHANGING: 
 461       event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING); 
 465       return wxControl::MSWOnNotify(idCtrl, lParam, result); 
 468 // TODO:    event.SetSelection(TabCtrl_GetCurSel(m_hwnd)); 
 469     event
.SetOldSelection(m_nSelection
); 
 470     event
.SetEventObject(this); 
 471     event
.SetInt(idCtrl
); 
 473     bool processed 
= GetEventHandler()->ProcessEvent(event
); 
 474 // TODO:   *result = !event.IsAllowed(); 
 478 // ---------------------------------------------------------------------------- 
 479 // wxNotebook helper functions 
 480 // ---------------------------------------------------------------------------- 
 482 // hide the currently active panel and show the new one 
 483 void wxNotebook::ChangePage(int nOldSel
, int nSel
) 
 485     // MT-FIXME should use a real semaphore 
 486     static bool s_bInsideChangePage 
= FALSE
; 
 488     // when we call ProcessEvent(), our own OnSelChange() is called which calls 
 489     // this function - break the infinite loop 
 490     if ( s_bInsideChangePage 
) 
 493     // it's not an error (the message may be generated by the tab control itself) 
 494     // and it may happen - just do nothing 
 495     if ( nSel 
== nOldSel 
) 
 498     s_bInsideChangePage 
= TRUE
; 
 500     wxNotebookEvent 
event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING
, m_windowId
); 
 501     event
.SetSelection(nSel
); 
 502     event
.SetOldSelection(nOldSel
); 
 503     event
.SetEventObject(this); 
 504     if ( ProcessEvent(event
) && !event
.IsAllowed() ) 
 506         // program doesn't allow the page change 
 507         s_bInsideChangePage 
= FALSE
; 
 511     event
.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
); 
 514     s_bInsideChangePage 
= FALSE
;