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