1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: implementation of wxNotebook
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #pragma implementation "notebook.h"
23 #include <wx/string.h>
25 #include <wx/imaglist.h>
26 #include <wx/notebook.h>
27 #include <wx/dcclient.h>
30 #include <wx/motif/private.h>
32 // ----------------------------------------------------------------------------
34 // ----------------------------------------------------------------------------
36 // check that the page index is valid
37 #define IS_VALID_PAGE(nPage) (((nPage) >= 0) && ((nPage) < GetPageCount()))
39 // ----------------------------------------------------------------------------
41 // ----------------------------------------------------------------------------
43 #if !USE_SHARED_LIBRARIES
44 BEGIN_EVENT_TABLE(wxNotebook
, wxControl
)
45 EVT_NOTEBOOK_PAGE_CHANGED(-1, wxNotebook::OnSelChange
)
46 EVT_SIZE(wxNotebook::OnSize
)
47 EVT_PAINT(wxNotebook::OnPaint
)
48 EVT_MOUSE_EVENTS(wxNotebook::OnMouseEvent
)
49 EVT_SET_FOCUS(wxNotebook::OnSetFocus
)
50 EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey
)
53 IMPLEMENT_DYNAMIC_CLASS(wxNotebook
, wxControl
)
54 IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent
, wxCommandEvent
)
57 // ============================================================================
59 // ============================================================================
61 // ----------------------------------------------------------------------------
62 // wxNotebook construction
63 // ----------------------------------------------------------------------------
65 // common part of all ctors
66 void wxNotebook::Init()
68 m_tabView
= (wxNotebookTabView
*) NULL
;
73 // default for dynamic class
74 wxNotebook::wxNotebook()
79 // the same arguments as for wxControl
80 wxNotebook::wxNotebook(wxWindow
*parent
,
89 Create(parent
, id
, pos
, size
, style
, name
);
93 bool wxNotebook::Create(wxWindow
*parent
,
103 m_windowId
= id
== -1 ? NewControlId() : id
;
105 // It's like a normal window...
106 if (!wxWindow::Create(parent
, id
, pos
, size
, style
, name
))
109 SetTabView(new wxNotebookTabView(this));
115 wxNotebook::~wxNotebook()
120 // ----------------------------------------------------------------------------
121 // wxNotebook accessors
122 // ----------------------------------------------------------------------------
123 int wxNotebook::GetPageCount() const
125 return m_aPages
.Count();
128 int wxNotebook::GetRowCount() const
134 int wxNotebook::SetSelection(int nPage
)
139 wxASSERT( IS_VALID_PAGE(nPage
) );
141 wxNotebookPage
* pPage
= GetPage(nPage
);
143 m_tabView
->SetTabSelection((int) (long) pPage
);
144 // ChangePage(m_nSelection, nPage);
150 void wxNotebook::AdvanceSelection(bool bForward
)
152 int nSel
= GetSelection();
153 int nMax
= GetPageCount() - 1;
155 SetSelection(nSel
== nMax
? 0 : nSel
+ 1);
157 SetSelection(nSel
== 0 ? nMax
: nSel
- 1);
160 bool wxNotebook::SetPageText(int nPage
, const wxString
& strText
)
162 wxASSERT( IS_VALID_PAGE(nPage
) );
168 wxString
wxNotebook::GetPageText(int nPage
) const
170 wxASSERT( IS_VALID_PAGE(nPage
) );
176 int wxNotebook::GetPageImage(int nPage
) const
178 wxASSERT( IS_VALID_PAGE(nPage
) );
184 bool wxNotebook::SetPageImage(int nPage
, int nImage
)
186 wxASSERT( IS_VALID_PAGE(nPage
) );
192 void wxNotebook::SetImageList(wxImageList
* imageList
)
194 m_pImageList
= imageList
;
198 // ----------------------------------------------------------------------------
199 // wxNotebook operations
200 // ----------------------------------------------------------------------------
202 // remove one page from the notebook and delete it
203 bool wxNotebook::DeletePage(int nPage
)
205 wxCHECK( IS_VALID_PAGE(nPage
), FALSE
);
207 if (m_nSelection
!= -1)
209 m_aPages
[m_nSelection
]->Show(FALSE
);
210 m_aPages
[m_nSelection
]->Lower();
213 wxNotebookPage
* pPage
= GetPage(nPage
);
214 m_tabView
->RemoveTab((int) (long) pPage
);
216 delete m_aPages
[nPage
];
217 m_aPages
.Remove(nPage
);
219 if (m_aPages
.GetCount() == 0)
222 m_tabView
->SetTabSelection(-1, FALSE
);
224 else if (m_nSelection
> 0)
227 m_tabView
->SetTabSelection((int) (long) GetPage(0), FALSE
);
234 bool wxNotebook::DeletePage(wxNotebookPage
* page
)
236 int pagePos
= FindPagePosition(page
);
238 return DeletePage(pagePos
);
243 // remove one page from the notebook
244 bool wxNotebook::RemovePage(int nPage
)
246 wxCHECK( IS_VALID_PAGE(nPage
), FALSE
);
248 if (m_nSelection
!= -1)
250 m_aPages
[m_nSelection
]->Show(FALSE
);
251 m_aPages
[m_nSelection
]->Lower();
254 wxNotebookPage
* pPage
= GetPage(nPage
);
255 m_tabView
->RemoveTab((int) (long) pPage
);
257 m_aPages
.Remove(nPage
);
259 if (m_aPages
.GetCount() == 0)
262 m_tabView
->SetTabSelection(-1, FALSE
);
264 else if (m_nSelection
> 0)
267 m_tabView
->SetTabSelection((int) (long) GetPage(0), FALSE
);
274 bool wxNotebook::RemovePage(wxNotebookPage
* page
)
276 int pagePos
= FindPagePosition(page
);
278 return RemovePage(pagePos
);
283 // Find the position of the wxNotebookPage, -1 if not found.
284 int wxNotebook::FindPagePosition(wxNotebookPage
* page
) const
286 int nPageCount
= GetPageCount();
288 for ( nPage
= 0; nPage
< nPageCount
; nPage
++ )
289 if (m_aPages
[nPage
] == page
)
295 bool wxNotebook::DeleteAllPages()
297 m_tabView
->ClearTabs(TRUE
);
299 int nPageCount
= GetPageCount();
301 for ( nPage
= 0; nPage
< nPageCount
; nPage
++ )
302 delete m_aPages
[nPage
];
309 // add a page to the notebook
310 bool wxNotebook::AddPage(wxNotebookPage
*pPage
,
311 const wxString
& strText
,
315 return InsertPage(GetPageCount(), pPage
, strText
, bSelect
, imageId
);
318 // same as AddPage() but does it at given position
319 bool wxNotebook::InsertPage(int nPage
,
320 wxNotebookPage
*pPage
,
321 const wxString
& strText
,
325 wxASSERT( pPage
!= NULL
);
326 wxCHECK( IS_VALID_PAGE(nPage
) || nPage
== GetPageCount(), FALSE
);
328 m_tabView
->AddTab((int) (long) pPage
, strText
);
332 // save the pointer to the page
333 m_aPages
.Insert(pPage
, nPage
);
337 // This will cause ChangePage to be called, via OnSelPage
338 m_tabView
->SetTabSelection((int) (long) pPage
, TRUE
);
341 // some page must be selected: either this one or the first one if there is
342 // still no selection
343 if ( m_nSelection
== -1 )
349 // ----------------------------------------------------------------------------
350 // wxNotebook callbacks
351 // ----------------------------------------------------------------------------
353 // @@@ OnSize() is used for setting the font when it's called for the first
354 // time because doing it in ::Create() doesn't work (for unknown reasons)
355 void wxNotebook::OnSize(wxSizeEvent
& event
)
357 static bool s_bFirstTime
= TRUE
;
358 if ( s_bFirstTime
) {
359 // TODO: any first-time-size processing.
360 s_bFirstTime
= FALSE
;
366 GetClientSize(& cw
, & ch
);
368 int tabHeight
= m_tabView
->GetTotalTabHeight();
371 rect
.y
= tabHeight
+ 4;
373 rect
.height
= ch
- 4 - rect
.y
;
375 m_tabView
->SetViewRect(rect
);
379 // Need to do it a 2nd time to get the tab height with
380 // the new view width, since changing the view width changes the
382 tabHeight
= m_tabView
->GetTotalTabHeight();
384 rect
.y
= tabHeight
+ 4;
386 rect
.height
= ch
- 4 - rect
.y
;
388 m_tabView
->SetViewRect(rect
);
392 // emulate page change (it's esp. important to do it first time because
393 // otherwise our page would stay invisible)
394 int nSel = m_nSelection;
399 // fit the notebook page to the tab control's display area
401 unsigned int nCount
= m_aPages
.Count();
402 for ( unsigned int nPage
= 0; nPage
< nCount
; nPage
++ ) {
403 wxNotebookPage
*pPage
= m_aPages
[nPage
];
404 if (pPage
->IsShown())
406 wxRect clientRect
= GetAvailableClientSize();
407 pPage
->SetSize(clientRect
.x
, clientRect
.y
, clientRect
.width
, clientRect
.height
);
408 if ( pPage
->GetAutoLayout() )
415 // Processing continues to next OnSize
419 void wxNotebook::OnSelChange(wxNotebookEvent
& event
)
421 // is it our tab control?
422 if ( event
.GetEventObject() == this )
423 ChangePage(event
.GetOldSelection(), event
.GetSelection());
425 // we want to give others a chance to process this message as well
429 void wxNotebook::OnSetFocus(wxFocusEvent
& event
)
431 // set focus to the currently selected page if any
432 if ( m_nSelection
!= -1 )
433 m_aPages
[m_nSelection
]->SetFocus();
438 void wxNotebook::OnNavigationKey(wxNavigationKeyEvent
& event
)
440 if ( event
.IsWindowChange() ) {
442 AdvanceSelection(event
.GetDirection());
445 // pass to the parent
447 event
.SetCurrentFocus(this);
448 GetParent()->ProcessEvent(event
);
453 // ----------------------------------------------------------------------------
454 // wxNotebook base class virtuals
455 // ----------------------------------------------------------------------------
457 // override these 2 functions to do nothing: everything is done in OnSize
459 void wxNotebook::SetConstraintSizes(bool /* recurse */)
461 // don't set the sizes of the pages - their correct size is not yet known
462 wxControl::SetConstraintSizes(FALSE
);
465 bool wxNotebook::DoPhase(int /* nPhase */)
470 void wxNotebook::Command(wxCommandEvent
& event
)
472 wxFAIL_MSG("wxNotebook::Command not implemented");
475 // ----------------------------------------------------------------------------
476 // wxNotebook helper functions
477 // ----------------------------------------------------------------------------
479 // hide the currently active panel and show the new one
480 void wxNotebook::ChangePage(int nOldSel
, int nSel
)
482 wxASSERT( nOldSel
!= nSel
); // impossible
484 if ( nOldSel
!= -1 ) {
485 m_aPages
[nOldSel
]->Show(FALSE
);
486 m_aPages
[nOldSel
]->Lower();
489 wxNotebookPage
*pPage
= m_aPages
[nSel
];
491 wxRect clientRect
= GetAvailableClientSize();
492 pPage
->SetSize(clientRect
.x
, clientRect
.y
, clientRect
.width
, clientRect
.height
);
503 void wxNotebook::ChangeFont(bool keepOriginalSize
)
505 wxWindow::ChangeFont(keepOriginalSize
);
508 void wxNotebook::ChangeBackgroundColour()
510 wxWindow::ChangeBackgroundColour();
513 void wxNotebook::ChangeForegroundColour()
515 wxWindow::ChangeForegroundColour();
518 void wxNotebook::OnMouseEvent(wxMouseEvent
& event
)
521 m_tabView
->OnEvent(event
);
524 void wxNotebook::OnPaint(wxPaintEvent
& WXUNUSED(event
) )
531 wxRect
wxNotebook::GetAvailableClientSize()
534 GetClientSize(& cw
, & ch
);
536 int tabHeight
= m_tabView
->GetTotalTabHeight();
538 // TODO: these margins should be configurable.
541 rect
.y
= tabHeight
+ 6;
542 rect
.width
= cw
- 12;
543 rect
.height
= ch
- 4 - rect
.y
;
552 IMPLEMENT_CLASS(wxNotebookTabView
, wxTabView
)
554 wxNotebookTabView::wxNotebookTabView(wxNotebook
*notebook
, long style
): wxTabView(style
)
556 m_notebook
= notebook
;
558 m_notebook
->SetTabView(this);
560 SetWindow(m_notebook
);
563 wxNotebookTabView::~wxNotebookTabView(void)
567 // Called when a tab is activated
568 void wxNotebookTabView::OnTabActivate(int activateId
, int deactivateId
)
573 wxNotebookEvent
event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
, m_notebook
->GetId());
575 // Translate from wxTabView's ids (which aren't position-dependent)
576 // to wxNotebook's (which are).
577 wxNotebookPage
* pActive
= (wxNotebookPage
*) activateId
;
578 wxNotebookPage
* pDeactive
= (wxNotebookPage
*) deactivateId
;
580 int activatePos
= m_notebook
->FindPagePosition(pActive
);
581 int deactivatePos
= m_notebook
->FindPagePosition(pDeactive
);
583 event
.SetEventObject(m_notebook
);
584 event
.SetSelection(activatePos
);
585 event
.SetOldSelection(deactivatePos
);
586 m_notebook
->GetEventHandler()->ProcessEvent(event
);