]> git.saurik.com Git - wxWidgets.git/blame - src/msw/notebook.cpp
compilation fixes for !USE_PCH
[wxWidgets.git] / src / msw / notebook.cpp
CommitLineData
88310e2e
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: msw/notebook.cpp
3// Purpose: implementation of wxNotebook
4// Author: Vadim Zeitlin
907f37b3 5// Modified by:
88310e2e
VZ
6// Created: 11.06.98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
6c9a19aa 9// Licence: wxWindows licence
88310e2e
VZ
10///////////////////////////////////////////////////////////////////////////////
11
88310e2e 12#ifdef __GNUG__
a3b46648 13#pragma implementation "notebook.h"
88310e2e
VZ
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
1e6feb95 20 #pragma hdrstop
88310e2e
VZ
21#endif
22
1e6feb95
VZ
23#if wxUSE_NOTEBOOK
24
88310e2e
VZ
25// wxWindows
26#ifndef WX_PRECOMP
3096bd2f 27 #include "wx/string.h"
88310e2e
VZ
28#endif // WX_PRECOMP
29
3096bd2f
VZ
30#include "wx/log.h"
31#include "wx/imaglist.h"
32#include "wx/event.h"
33#include "wx/control.h"
34#include "wx/notebook.h"
88310e2e 35
3096bd2f 36#include "wx/msw/private.h"
88310e2e
VZ
37
38// Windows standard headers
39#ifndef __WIN95__
2432b92d 40 #error "wxNotebook is only supported Windows 95 and above"
88310e2e
VZ
41#endif //Win95
42
aaab7c01
VZ
43#include <windowsx.h> // for SetWindowFont
44
b39dbf34
JS
45#ifdef __GNUWIN32_OLD__
46 #include "wx/msw/gnuwin32/extra.h"
65fd5cb0 47#endif
57c208c5 48
b39dbf34 49#if defined(__WIN95__) && !(defined(__GNUWIN32_OLD__) && !defined(__CYGWIN10__))
c42404a5 50 #include <commctrl.h>
88310e2e
VZ
51#endif
52
85b43fbf
JS
53#include "wx/msw/winundef.h"
54
55#if wxUSE_UXTHEME
56#include "wx/msw/uxtheme.h"
57
58#include "wx/radiobut.h"
59#include "wx/radiobox.h"
60#include "wx/checkbox.h"
61#include "wx/bmpbuttn.h"
62#include "wx/statline.h"
63#include "wx/statbox.h"
64#include "wx/stattext.h"
65#include "wx/slider.h"
66#include "wx/scrolwin.h"
67#include "wx/panel.h"
68#endif
69
88310e2e
VZ
70// ----------------------------------------------------------------------------
71// macros
72// ----------------------------------------------------------------------------
73
74// check that the page index is valid
75#define IS_VALID_PAGE(nPage) (((nPage) >= 0) && ((nPage) < GetPageCount()))
76
77// hide the ugly cast
78#define m_hwnd (HWND)GetHWND()
79
74b31181
VZ
80// ----------------------------------------------------------------------------
81// constants
82// ----------------------------------------------------------------------------
83
84// This is a work-around for missing defines in gcc-2.95 headers
85#ifndef TCS_RIGHT
86 #define TCS_RIGHT 0x0002
87#endif
88
89#ifndef TCS_VERTICAL
90 #define TCS_VERTICAL 0x0080
91#endif
92
93#ifndef TCS_BOTTOM
94 #define TCS_BOTTOM TCS_RIGHT
95#endif
96
88310e2e
VZ
97// ----------------------------------------------------------------------------
98// event table
99// ----------------------------------------------------------------------------
100
2e4df4bf
VZ
101DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED)
102DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING)
103
d9317fd4 104BEGIN_EVENT_TABLE(wxNotebook, wxControl)
88310e2e
VZ
105 EVT_NOTEBOOK_PAGE_CHANGED(-1, wxNotebook::OnSelChange)
106
9026ad85 107 EVT_SIZE(wxNotebook::OnSize)
42e69d6b 108
88310e2e 109 EVT_SET_FOCUS(wxNotebook::OnSetFocus)
42e69d6b 110
88310e2e 111 EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey)
d9317fd4 112END_EVENT_TABLE()
88310e2e 113
d9317fd4
VZ
114IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxControl)
115IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxNotifyEvent)
88310e2e
VZ
116
117// ============================================================================
118// implementation
119// ============================================================================
120
121// ----------------------------------------------------------------------------
122// wxNotebook construction
123// ----------------------------------------------------------------------------
124
125// common part of all ctors
126void wxNotebook::Init()
127{
1e6feb95 128 m_imageList = NULL;
88310e2e
VZ
129 m_nSelection = -1;
130}
131
132// default for dynamic class
133wxNotebook::wxNotebook()
134{
135 Init();
136}
137
138// the same arguments as for wxControl
139wxNotebook::wxNotebook(wxWindow *parent,
8b9518ee 140 wxWindowID id,
88310e2e
VZ
141 const wxPoint& pos,
142 const wxSize& size,
8b9518ee 143 long style,
88310e2e
VZ
144 const wxString& name)
145{
146 Init();
147
148 Create(parent, id, pos, size, style, name);
149}
150
151// Create() function
152bool wxNotebook::Create(wxWindow *parent,
8b9518ee 153 wxWindowID id,
88310e2e
VZ
154 const wxPoint& pos,
155 const wxSize& size,
8b9518ee 156 long style,
88310e2e
VZ
157 const wxString& name)
158{
0df3fbd7 159 // base init
6dd16e4f
VZ
160 if ( !CreateControl(parent, id, pos, size, style | wxTAB_TRAVERSAL,
161 wxDefaultValidator, name) )
0df3fbd7 162 return FALSE;
88310e2e 163
6dd16e4f 164 if ( !MSWCreateControl(WC_TABCONTROL, _T(""), pos, size) )
0df3fbd7 165 return FALSE;
907f37b3 166
0df3fbd7
VZ
167 SetBackgroundColour(wxColour(::GetSysColor(COLOR_BTNFACE)));
168
169 return TRUE;
170}
171
172WXDWORD wxNotebook::MSWGetStyle(long style, WXDWORD *exstyle) const
173{
174 WXDWORD tabStyle = wxControl::MSWGetStyle(style, exstyle);
175
176 tabStyle |= WS_TABSTOP | TCS_TABS;
177
2b5f62a0 178 if ( style & wxNB_MULTILINE )
0df3fbd7
VZ
179 tabStyle |= TCS_MULTILINE;
180 if ( style & wxNB_FIXEDWIDTH )
181 tabStyle |= TCS_FIXEDWIDTH;
182
183 if ( style & wxNB_BOTTOM )
184 tabStyle |= TCS_RIGHT;
185 else if ( style & wxNB_LEFT )
186 tabStyle |= TCS_VERTICAL;
187 else if ( style & wxNB_RIGHT )
188 tabStyle |= TCS_VERTICAL | TCS_RIGHT;
189
190 // ex style
191 if ( exstyle )
192 {
193 // note that we never want to have the default WS_EX_CLIENTEDGE style
194 // as it looks too ugly for the notebooks
195 *exstyle = 0;
196 }
197
198 return tabStyle;
88310e2e
VZ
199}
200
88310e2e
VZ
201// ----------------------------------------------------------------------------
202// wxNotebook accessors
203// ----------------------------------------------------------------------------
07b8d7ec 204
88310e2e
VZ
205int wxNotebook::GetPageCount() const
206{
207 // consistency check
1e6feb95 208 wxASSERT( (int)m_pages.Count() == TabCtrl_GetItemCount(m_hwnd) );
88310e2e 209
1e6feb95 210 return m_pages.Count();
88310e2e
VZ
211}
212
213int wxNotebook::GetRowCount() const
214{
215 return TabCtrl_GetRowCount(m_hwnd);
216}
217
218int wxNotebook::SetSelection(int nPage)
219{
223d09f6 220 wxCHECK_MSG( IS_VALID_PAGE(nPage), -1, wxT("notebook page out of range") );
88310e2e 221
2b5f62a0
VZ
222 if ( nPage != m_nSelection )
223 {
224 wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, m_windowId);
225 event.SetSelection(nPage);
226 event.SetOldSelection(m_nSelection);
227 event.SetEventObject(this);
228 if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
229 {
230 // program allows the page change
231 event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED);
232 (void)GetEventHandler()->ProcessEvent(event);
233
234 TabCtrl_SetCurSel(m_hwnd, nPage);
235 }
236 }
88310e2e 237
2b5f62a0 238 return m_nSelection;
88310e2e
VZ
239}
240
88310e2e
VZ
241bool wxNotebook::SetPageText(int nPage, const wxString& strText)
242{
223d09f6 243 wxCHECK_MSG( IS_VALID_PAGE(nPage), FALSE, wxT("notebook page out of range") );
88310e2e
VZ
244
245 TC_ITEM tcItem;
246 tcItem.mask = TCIF_TEXT;
837e5743 247 tcItem.pszText = (wxChar *)strText.c_str();
88310e2e
VZ
248
249 return TabCtrl_SetItem(m_hwnd, nPage, &tcItem) != 0;
250}
251
252wxString wxNotebook::GetPageText(int nPage) const
253{
223d09f6 254 wxCHECK_MSG( IS_VALID_PAGE(nPage), wxT(""), wxT("notebook page out of range") );
88310e2e 255
837e5743 256 wxChar buf[256];
88310e2e
VZ
257 TC_ITEM tcItem;
258 tcItem.mask = TCIF_TEXT;
259 tcItem.pszText = buf;
260 tcItem.cchTextMax = WXSIZEOF(buf);
261
262 wxString str;
263 if ( TabCtrl_GetItem(m_hwnd, nPage, &tcItem) )
264 str = tcItem.pszText;
265
266 return str;
267}
268
269int wxNotebook::GetPageImage(int nPage) const
270{
223d09f6 271 wxCHECK_MSG( IS_VALID_PAGE(nPage), -1, wxT("notebook page out of range") );
88310e2e
VZ
272
273 TC_ITEM tcItem;
274 tcItem.mask = TCIF_IMAGE;
275
276 return TabCtrl_GetItem(m_hwnd, nPage, &tcItem) ? tcItem.iImage : -1;
277}
278
279bool wxNotebook::SetPageImage(int nPage, int nImage)
280{
223d09f6 281 wxCHECK_MSG( IS_VALID_PAGE(nPage), FALSE, wxT("notebook page out of range") );
88310e2e
VZ
282
283 TC_ITEM tcItem;
284 tcItem.mask = TCIF_IMAGE;
285 tcItem.iImage = nImage;
286
287 return TabCtrl_SetItem(m_hwnd, nPage, &tcItem) != 0;
288}
289
290void wxNotebook::SetImageList(wxImageList* imageList)
907f37b3 291{
07b8d7ec
VZ
292 wxNotebookBase::SetImageList(imageList);
293
294 if ( imageList )
1e6feb95 295 {
07b8d7ec 296 TabCtrl_SetImageList(m_hwnd, (HIMAGELIST)imageList->GetHIMAGELIST());
1e6feb95 297 }
b656febd
VS
298}
299
d9506e77
VZ
300// ----------------------------------------------------------------------------
301// wxNotebook size settings
302// ----------------------------------------------------------------------------
303
304void wxNotebook::SetPageSize(const wxSize& size)
305{
306 // transform the page size into the notebook size
307 RECT rc;
308 rc.left =
309 rc.top = 0;
310 rc.right = size.x;
311 rc.bottom = size.y;
312
313 TabCtrl_AdjustRect(GetHwnd(), TRUE, &rc);
314
315 // and now set it
316 SetSize(rc.right - rc.left, rc.bottom - rc.top);
317}
318
319void wxNotebook::SetPadding(const wxSize& padding)
320{
321 TabCtrl_SetPadding(GetHwnd(), padding.x, padding.y);
322}
42e69d6b
VZ
323
324// Windows-only at present. Also, you must use the wxNB_FIXEDWIDTH
325// style.
326void wxNotebook::SetTabSize(const wxSize& sz)
327{
328 ::SendMessage(GetHwnd(), TCM_SETITEMSIZE, 0, MAKELPARAM(sz.x, sz.y));
329}
330
2ce7af35
JS
331wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const
332{
333 wxSize sizeTotal = sizePage;
334
335 // We need to make getting tab size part of the wxWindows API.
336 wxSize tabSize(0, 0);
337 if (GetPageCount() > 0)
338 {
339 RECT rect;
340 TabCtrl_GetItemRect((HWND) GetHWND(), 0, & rect);
341 tabSize.x = rect.right - rect.left;
342 tabSize.y = rect.bottom - rect.top;
343 }
344 if ( HasFlag(wxNB_LEFT) || HasFlag(wxNB_RIGHT) )
345 {
346 sizeTotal.x += tabSize.x + 7;
347 sizeTotal.y += 7;
348 }
349 else
350 {
351 sizeTotal.x += 7;
352 sizeTotal.y += tabSize.y + 7;
353 }
354
355 return sizeTotal;
356}
357
2015f2b3
VZ
358void wxNotebook::AdjustPageSize(wxNotebookPage *page)
359{
360 wxCHECK_RET( page, _T("NULL page in wxNotebook::AdjustPageSize") );
361
362 RECT rc;
363 rc.left =
364 rc.top = 0;
365
366 // get the page size from the notebook size
367 GetSize((int *)&rc.right, (int *)&rc.bottom);
368 TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
369
370 page->SetSize(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
371}
372
88310e2e
VZ
373// ----------------------------------------------------------------------------
374// wxNotebook operations
375// ----------------------------------------------------------------------------
376
621793f4 377// remove one page from the notebook, without deleting
1e6feb95 378wxNotebookPage *wxNotebook::DoRemovePage(int nPage)
621793f4 379{
df7145da
VZ
380 wxNotebookPage *pageRemoved = wxNotebookBase::DoRemovePage(nPage);
381 if ( !pageRemoved )
382 return NULL;
621793f4 383
df7145da 384 TabCtrl_DeleteItem(m_hwnd, nPage);
621793f4 385
df7145da
VZ
386 if ( m_pages.IsEmpty() )
387 {
388 // no selection any more, the notebook becamse empty
389 m_nSelection = -1;
390 }
391 else // notebook still not empty
392 {
43a997b6
VZ
393 // change the selected page if it was deleted or became invalid
394 int selNew;
df7145da
VZ
395 if ( m_nSelection == GetPageCount() )
396 {
43a997b6
VZ
397 // last page deleted, make the new last page the new selection
398 selNew = m_nSelection - 1;
df7145da 399 }
43a997b6
VZ
400 else if ( nPage <= m_nSelection )
401 {
402 // we must show another page, even if it has the same index
403 selNew = m_nSelection;
404 }
405 else // nothing changes for the currently selected page
406 {
407 selNew = -1;
df7145da 408
43a997b6
VZ
409 // we still must refresh the current page: this needs to be done
410 // for some unknown reason if the tab control shows the up-down
411 // control (i.e. when there are too many pages) -- otherwise after
412 // deleting a page nothing at all is shown
413 m_pages[m_nSelection]->Refresh();
414 }
415
416 if ( selNew != -1 )
417 {
418 // m_nSelection must be always valid so reset it before calling
419 // SetSelection()
420 m_nSelection = -1;
421 SetSelection(selNew);
422 }
df7145da 423 }
47f12f58 424
df7145da 425 return pageRemoved;
621793f4
JS
426}
427
88310e2e
VZ
428// remove all pages
429bool wxNotebook::DeleteAllPages()
430{
88310e2e
VZ
431 int nPageCount = GetPageCount();
432 int nPage;
433 for ( nPage = 0; nPage < nPageCount; nPage++ )
1e6feb95 434 delete m_pages[nPage];
88310e2e 435
1e6feb95 436 m_pages.Clear();
88310e2e 437
907f37b3
VZ
438 TabCtrl_DeleteAllItems(m_hwnd);
439
47f12f58
JS
440 m_nSelection = -1;
441
88310e2e
VZ
442 return TRUE;
443}
444
88310e2e
VZ
445// same as AddPage() but does it at given position
446bool wxNotebook::InsertPage(int nPage,
447 wxNotebookPage *pPage,
448 const wxString& strText,
449 bool bSelect,
450 int imageId)
451{
22f3361e
VZ
452 wxCHECK_MSG( pPage != NULL, FALSE, _T("NULL page in wxNotebook::InsertPage") );
453 wxCHECK_MSG( IS_VALID_PAGE(nPage) || nPage == GetPageCount(), FALSE,
454 _T("invalid index in wxNotebook::InsertPage") );
88310e2e 455
efa14cf2
VZ
456 wxASSERT_MSG( pPage->GetParent() == this,
457 _T("notebook pages must have notebook as parent") );
43427087 458
85b43fbf
JS
459#if wxUSE_UXTHEME && wxUSE_UXTHEME_AUTO
460 // Automatically apply the theme background,
461 // changing the colour of the panel to match the
462 // tab page colour. This won't work well with all
463 // themes but it's a start.
464 if (wxUxThemeEngine::Get() && pPage->IsKindOf(CLASSINFO(wxPanel)))
465 {
466 ApplyThemeBackground(pPage, GetThemeBackgroundColour());
467 }
468#endif
469
22f3361e
VZ
470 // add a new tab to the control
471 // ----------------------------
58a8ab88 472
22f3361e
VZ
473 // init all fields to 0
474 TC_ITEM tcItem;
475 wxZeroMemory(tcItem);
58a8ab88 476
22f3361e
VZ
477 // set the image, if any
478 if ( imageId != -1 )
479 {
480 tcItem.mask |= TCIF_IMAGE;
481 tcItem.iImage = imageId;
482 }
88310e2e 483
22f3361e
VZ
484 // and the text
485 if ( !strText.IsEmpty() )
486 {
487 tcItem.mask |= TCIF_TEXT;
488 tcItem.pszText = (wxChar *)strText.c_str(); // const_cast
489 }
43427087 490
22f3361e
VZ
491 // fit the notebook page to the tab control's display area: this should be
492 // done before adding it to the notebook or TabCtrl_InsertItem() will
493 // change the notebooks size itself!
2015f2b3 494 AdjustPageSize(pPage);
43427087 495
22f3361e 496 // finally do insert it
2015f2b3
VZ
497 if ( TabCtrl_InsertItem(m_hwnd, nPage, &tcItem) == -1 )
498 {
22f3361e 499 wxLogError(wxT("Can't create the notebook page '%s'."), strText.c_str());
88310e2e 500
22f3361e
VZ
501 return FALSE;
502 }
88310e2e 503
22f3361e
VZ
504 // succeeded: save the pointer to the page
505 m_pages.Insert(pPage, nPage);
42e69d6b 506
2015f2b3
VZ
507 // for the first page (only) we need to adjust the size again because the
508 // notebook size changed: the tabs which hadn't been there before are now
509 // shown
510 if ( m_pages.GetCount() == 1 )
511 {
512 AdjustPageSize(pPage);
513 }
514
22f3361e
VZ
515 // hide the page: unless it is selected, it shouldn't be shown (and if it
516 // is selected it will be shown later)
517 HWND hwnd = GetWinHwnd(pPage);
518 SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_VISIBLE);
0398b1d6 519
22f3361e
VZ
520 // this updates internal flag too -- otherwise it would get out of sync
521 // with the real state
522 pPage->Show(FALSE);
43427087 523
96d37807 524
22f3361e
VZ
525 // now deal with the selection
526 // ---------------------------
527
528 // if the inserted page is before the selected one, we must update the
529 // index of the selected page
530 if ( nPage <= m_nSelection )
531 {
532 // one extra page added
533 m_nSelection++;
534 }
535
536 // some page should be selected: either this one or the first one if there
537 // is still no selection
538 int selNew = -1;
539 if ( bSelect )
540 selNew = nPage;
541 else if ( m_nSelection == -1 )
542 selNew = 0;
543
544 if ( selNew != -1 )
545 SetSelection(selNew);
546
547 return TRUE;
88310e2e
VZ
548}
549
ef094fa0
JS
550// Hit test
551int wxNotebook::HitTest(const wxPoint& pt, long& flags)
552{
553 TC_HITTESTINFO hitTestInfo;
554 hitTestInfo.pt.x = pt.x;
555 hitTestInfo.pt.y = pt.y;
556 int item = TabCtrl_HitTest( (HWND) GetHWND(), & hitTestInfo ) ;
557 flags = 0;
558
559 if ((hitTestInfo.flags & TCHT_NOWHERE) == TCHT_NOWHERE)
560 flags |= wxNB_HITTEST_NOWHERE;
561 if ((hitTestInfo.flags & TCHT_ONITEMICON) == TCHT_ONITEMICON)
562 flags |= wxNB_HITTEST_ONICON;
563 if ((hitTestInfo.flags & TCHT_ONITEMLABEL) == TCHT_ONITEMLABEL)
564 flags |= wxNB_HITTEST_ONLABEL;
565
566 return item;
567}
568
88310e2e
VZ
569// ----------------------------------------------------------------------------
570// wxNotebook callbacks
571// ----------------------------------------------------------------------------
572
9026ad85 573void wxNotebook::OnSize(wxSizeEvent& event)
88310e2e 574{
b5c3b538
VZ
575 // fit the notebook page to the tab control's display area
576 RECT rc;
577 rc.left = rc.top = 0;
578 GetSize((int *)&rc.right, (int *)&rc.bottom);
579
580 TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
4b7f2165
VZ
581
582 int width = rc.right - rc.left,
583 height = rc.bottom - rc.top;
1e6feb95 584 size_t nCount = m_pages.Count();
c86f1403 585 for ( size_t nPage = 0; nPage < nCount; nPage++ ) {
1e6feb95 586 wxNotebookPage *pPage = m_pages[nPage];
4b7f2165 587 pPage->SetSize(rc.left, rc.top, width, height);
b5c3b538
VZ
588 }
589
88310e2e
VZ
590 event.Skip();
591}
592
593void wxNotebook::OnSelChange(wxNotebookEvent& event)
594{
595 // is it our tab control?
596 if ( event.GetEventObject() == this )
5d1d2d46 597 {
5d1d2d46
VZ
598 int sel = event.GetOldSelection();
599 if ( sel != -1 )
1e6feb95 600 m_pages[sel]->Show(FALSE);
0398b1d6 601
5d1d2d46
VZ
602 sel = event.GetSelection();
603 if ( sel != -1 )
604 {
1e6feb95 605 wxNotebookPage *pPage = m_pages[sel];
5d1d2d46
VZ
606 pPage->Show(TRUE);
607 pPage->SetFocus();
608 }
0398b1d6 609
5d1d2d46
VZ
610 m_nSelection = sel;
611 }
88310e2e
VZ
612
613 // we want to give others a chance to process this message as well
614 event.Skip();
615}
616
617void wxNotebook::OnSetFocus(wxFocusEvent& event)
618{
d9506e77
VZ
619 // this function is only called when the focus is explicitly set (i.e. from
620 // the program) to the notebook - in this case we don't need the
621 // complicated OnNavigationKey() logic because the programmer knows better
622 // what [s]he wants
88310e2e 623
d9506e77
VZ
624 // set focus to the currently selected page if any
625 if ( m_nSelection != -1 )
1e6feb95 626 m_pages[m_nSelection]->SetFocus();
d9506e77
VZ
627
628 event.Skip();
88310e2e
VZ
629}
630
631void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
632{
d9506e77
VZ
633 if ( event.IsWindowChange() ) {
634 // change pages
635 AdvanceSelection(event.GetDirection());
636 }
637 else {
638 // we get this event in 2 cases
639 //
640 // a) one of our pages might have generated it because the user TABbed
641 // out from it in which case we should propagate the event upwards and
642 // our parent will take care of setting the focus to prev/next sibling
643 //
644 // or
645 //
646 // b) the parent panel wants to give the focus to us so that we
647 // forward it to our selected page. We can't deal with this in
648 // OnSetFocus() because we don't know which direction the focus came
649 // from in this case and so can't choose between setting the focus to
650 // first or last panel child
651
652 wxWindow *parent = GetParent();
653 if ( event.GetEventObject() == parent )
654 {
655 // no, it doesn't come from child, case (b): forward to a page
656 if ( m_nSelection != -1 )
657 {
658 // so that the page knows that the event comes from it's parent
659 // and is being propagated downwards
660 event.SetEventObject(this);
661
1e6feb95 662 wxWindow *page = m_pages[m_nSelection];
d9506e77
VZ
663 if ( !page->GetEventHandler()->ProcessEvent(event) )
664 {
665 page->SetFocus();
666 }
667 //else: page manages focus inside it itself
668 }
669 else
670 {
671 // we have no pages - still have to give focus to _something_
672 SetFocus();
673 }
674 }
675 else
676 {
677 // it comes from our child, case (a), pass to the parent
678 if ( parent ) {
679 event.SetCurrentFocus(this);
680 parent->GetEventHandler()->ProcessEvent(event);
681 }
682 }
88310e2e 683 }
88310e2e
VZ
684}
685
686// ----------------------------------------------------------------------------
687// wxNotebook base class virtuals
688// ----------------------------------------------------------------------------
b5c3b538 689
0b481c72
VZ
690#if wxUSE_CONSTRAINTS
691
b5c3b538
VZ
692// override these 2 functions to do nothing: everything is done in OnSize
693
4b7f2165 694void wxNotebook::SetConstraintSizes(bool WXUNUSED(recurse))
b5c3b538
VZ
695{
696 // don't set the sizes of the pages - their correct size is not yet known
697 wxControl::SetConstraintSizes(FALSE);
698}
699
4b7f2165 700bool wxNotebook::DoPhase(int WXUNUSED(nPhase))
b5c3b538
VZ
701{
702 return TRUE;
703}
704
0b481c72
VZ
705#endif // wxUSE_CONSTRAINTS
706
0df3fbd7
VZ
707// ----------------------------------------------------------------------------
708// wxNotebook Windows message handlers
709// ----------------------------------------------------------------------------
710
711bool wxNotebook::MSWOnScroll(int orientation, WXWORD nSBCode,
712 WXWORD pos, WXHWND control)
713{
714 // don't generate EVT_SCROLLWIN events for the WM_SCROLLs coming from the
715 // up-down control
716 if ( control )
717 return FALSE;
718
719 return wxNotebookBase::MSWOnScroll(orientation, nSBCode, pos, control);
720}
721
a23fd0e1 722bool wxNotebook::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM* result)
88310e2e 723{
93a19f17 724 wxNotebookEvent event(wxEVT_NULL, m_windowId);
88310e2e
VZ
725
726 NMHDR* hdr = (NMHDR *)lParam;
727 switch ( hdr->code ) {
728 case TCN_SELCHANGE:
729 event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED);
730 break;
731
732 case TCN_SELCHANGING:
733 event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING);
734 break;
735
fd3f686c 736 default:
a23fd0e1 737 return wxControl::MSWOnNotify(idCtrl, lParam, result);
88310e2e
VZ
738 }
739
93a19f17
VZ
740 event.SetSelection(TabCtrl_GetCurSel(m_hwnd));
741 event.SetOldSelection(m_nSelection);
88310e2e 742 event.SetEventObject(this);
a23fd0e1 743 event.SetInt(idCtrl);
88310e2e 744
fd3f686c
VZ
745 bool processed = GetEventHandler()->ProcessEvent(event);
746 *result = !event.IsAllowed();
747 return processed;
88310e2e
VZ
748}
749
85b43fbf
JS
750// Windows only: attempts to get colour for UX theme page background
751wxColour wxNotebook::GetThemeBackgroundColour()
752{
753#if wxUSE_UXTHEME
754 if (wxUxThemeEngine::Get())
755 {
756 WXHTHEME hTheme = wxUxThemeEngine::Get()->m_pfnOpenThemeData(GetHWND(), L"TAB");
757 if (hTheme)
758 {
759 // This is total guesswork.
760 // See PlatformSDK\Include\Tmschema.h for values
761 COLORREF themeColor;
762 wxUxThemeEngine::Get()->
763 m_pfnGetThemeColor(hTheme,
764 10 /* TABP_BODY */,
765 1 /* NORMAL */,
766 3821, /* FILLCOLORHINT */
767 & themeColor);
768
769 wxUxThemeEngine::Get()->m_pfnCloseThemeData(hTheme);
770
771 wxColour colour(GetRValue(themeColor), GetGValue(themeColor), GetBValue(themeColor));
772 return colour;
773 }
774 }
775#endif
776 return GetBackgroundColour();
777}
778
779// Windows only: attempts to apply the UX theme page background to this page
780void wxNotebook::ApplyThemeBackground(wxWindow* window, const wxColour& colour)
781{
782#if wxUSE_UXTHEME
783 // Don't set the background for buttons since this will
784 // switch it into ownerdraw mode
785 if (window->IsKindOf(CLASSINFO(wxButton)) && !window->IsKindOf(CLASSINFO(wxBitmapButton)))
786 // This is essential, otherwise you'll see dark grey
787 // corners in the buttons.
788 ((wxButton*)window)->wxControl::SetBackgroundColour(colour);
789 else if (window->IsKindOf(CLASSINFO(wxStaticText)) ||
790 window->IsKindOf(CLASSINFO(wxStaticBox)) ||
791 window->IsKindOf(CLASSINFO(wxStaticLine)) ||
792 window->IsKindOf(CLASSINFO(wxRadioButton)) ||
793 window->IsKindOf(CLASSINFO(wxRadioBox)) ||
794 window->IsKindOf(CLASSINFO(wxCheckBox)) ||
795 window->IsKindOf(CLASSINFO(wxBitmapButton)) ||
796 window->IsKindOf(CLASSINFO(wxSlider)) ||
797 window->IsKindOf(CLASSINFO(wxPanel)) ||
798 (window->IsKindOf(CLASSINFO(wxNotebook)) && (window != this)) ||
799 window->IsKindOf(CLASSINFO(wxScrolledWindow))
800 )
801 {
802 window->SetBackgroundColour(colour);
803 }
804
805 for ( wxWindowList::Node *node = window->GetChildren().GetFirst(); node; node = node->GetNext() )
806 {
807 wxWindow *child = node->GetData();
808 ApplyThemeBackground(child, colour);
809 }
810#endif
811}
812
1e6feb95 813#endif // wxUSE_NOTEBOOK