1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/aui/auibook.cpp
3 // Purpose: wxaui: wx advanced user interface - notebook
4 // Author: Benjamin I. Williams
5 // Modified by: Jens Lody
6 // Created: 2006-06-28
7 // Copyright: (C) Copyright 2006, Kirix Corporation, All Rights Reserved
8 // Licence: wxWindows Library Licence, Version 3.1
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ----------------------------------------------------------------------------
12 // headers
13 // ----------------------------------------------------------------------------
14
15 #include "wx/wxprec.h"
16
17 #ifdef __BORLANDC__
18 #pragma hdrstop
19 #endif
20
21 #if wxUSE_AUI
22
23 #include "wx/aui/auibook.h"
24
25 #ifndef WX_PRECOMP
26 #include "wx/settings.h"
27 #include "wx/dcclient.h"
28 #include "wx/dcmemory.h"
29 #endif
30
31 #include "wx/aui/tabmdi.h"
32
33 #ifdef __WXMAC__
34 #include "wx/osx/private.h"
35 #endif
36
37 #include "wx/arrimpl.cpp"
38 WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray)
39 WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray)
40
41 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEvent);
42 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_PAGE_CLOSED, wxAuiNotebookEvent);
43 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_PAGE_CHANGING, wxAuiNotebookEvent);
44 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEvent);
45 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_BUTTON, wxAuiNotebookEvent);
46 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_BEGIN_DRAG, wxAuiNotebookEvent);
47 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_END_DRAG, wxAuiNotebookEvent);
48 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_CANCEL_DRAG, wxAuiNotebookEvent);
49 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_DRAG_MOTION, wxAuiNotebookEvent);
50 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_ALLOW_DND, wxAuiNotebookEvent);
51 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_BG_DCLICK, wxAuiNotebookEvent);
52 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_DRAG_DONE, wxAuiNotebookEvent);
53 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_TAB_MIDDLE_UP, wxAuiNotebookEvent);
54 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_TAB_MIDDLE_DOWN, wxAuiNotebookEvent);
55 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_TAB_RIGHT_UP, wxAuiNotebookEvent);
56 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN, wxAuiNotebookEvent);
57
IMPLEMENT_CLASS(wxAuiNotebook,wxControl)58 IMPLEMENT_CLASS(wxAuiNotebook, wxControl)
59 IMPLEMENT_CLASS(wxAuiTabCtrl, wxControl)
60 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent, wxBookCtrlEvent)
61
62
63 // -- wxAuiTabContainer class implementation --
64
65
66 // wxAuiTabContainer is a class which contains information about each
67 // tab. It also can render an entire tab control to a specified DC.
68 // It's not a window class itself, because this code will be used by
69 // the wxFrameMananger, where it is disadvantageous to have separate
70 // windows for each tab control in the case of "docked tabs"
71
72 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
73 // which can be used as a tab control in the normal sense.
74
75
76 wxAuiTabContainer::wxAuiTabContainer()
77 {
78 m_tabOffset = 0;
79 m_flags = 0;
80 m_art = new wxAuiDefaultTabArt;
81
82 AddButton(wxAUI_BUTTON_LEFT, wxLEFT);
83 AddButton(wxAUI_BUTTON_RIGHT, wxRIGHT);
84 AddButton(wxAUI_BUTTON_WINDOWLIST, wxRIGHT);
85 AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT);
86 }
87
~wxAuiTabContainer()88 wxAuiTabContainer::~wxAuiTabContainer()
89 {
90 delete m_art;
91 }
92
SetArtProvider(wxAuiTabArt * art)93 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt* art)
94 {
95 delete m_art;
96 m_art = art;
97
98 if (m_art)
99 {
100 m_art->SetFlags(m_flags);
101 }
102 }
103
GetArtProvider() const104 wxAuiTabArt* wxAuiTabContainer::GetArtProvider() const
105 {
106 return m_art;
107 }
108
SetFlags(unsigned int flags)109 void wxAuiTabContainer::SetFlags(unsigned int flags)
110 {
111 m_flags = flags;
112
113 // check for new close button settings
114 RemoveButton(wxAUI_BUTTON_LEFT);
115 RemoveButton(wxAUI_BUTTON_RIGHT);
116 RemoveButton(wxAUI_BUTTON_WINDOWLIST);
117 RemoveButton(wxAUI_BUTTON_CLOSE);
118
119
120 if (flags & wxAUI_NB_SCROLL_BUTTONS)
121 {
122 AddButton(wxAUI_BUTTON_LEFT, wxLEFT);
123 AddButton(wxAUI_BUTTON_RIGHT, wxRIGHT);
124 }
125
126 if (flags & wxAUI_NB_WINDOWLIST_BUTTON)
127 {
128 AddButton(wxAUI_BUTTON_WINDOWLIST, wxRIGHT);
129 }
130
131 if (flags & wxAUI_NB_CLOSE_BUTTON)
132 {
133 AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT);
134 }
135
136 if (m_art)
137 {
138 m_art->SetFlags(m_flags);
139 }
140 }
141
GetFlags() const142 unsigned int wxAuiTabContainer::GetFlags() const
143 {
144 return m_flags;
145 }
146
147
SetNormalFont(const wxFont & font)148 void wxAuiTabContainer::SetNormalFont(const wxFont& font)
149 {
150 m_art->SetNormalFont(font);
151 }
152
SetSelectedFont(const wxFont & font)153 void wxAuiTabContainer::SetSelectedFont(const wxFont& font)
154 {
155 m_art->SetSelectedFont(font);
156 }
157
SetMeasuringFont(const wxFont & font)158 void wxAuiTabContainer::SetMeasuringFont(const wxFont& font)
159 {
160 m_art->SetMeasuringFont(font);
161 }
162
SetColour(const wxColour & colour)163 void wxAuiTabContainer::SetColour(const wxColour& colour)
164 {
165 m_art->SetColour(colour);
166 }
167
SetActiveColour(const wxColour & colour)168 void wxAuiTabContainer::SetActiveColour(const wxColour& colour)
169 {
170 m_art->SetActiveColour(colour);
171 }
172
SetRect(const wxRect & rect)173 void wxAuiTabContainer::SetRect(const wxRect& rect)
174 {
175 m_rect = rect;
176
177 if (m_art)
178 {
179 m_art->SetSizingInfo(rect.GetSize(), m_pages.GetCount());
180 }
181 }
182
AddPage(wxWindow * page,const wxAuiNotebookPage & info)183 bool wxAuiTabContainer::AddPage(wxWindow* page,
184 const wxAuiNotebookPage& info)
185 {
186 wxAuiNotebookPage page_info;
187 page_info = info;
188 page_info.window = page;
189
190 m_pages.Add(page_info);
191
192 // let the art provider know how many pages we have
193 if (m_art)
194 {
195 m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
196 }
197
198 return true;
199 }
200
InsertPage(wxWindow * page,const wxAuiNotebookPage & info,size_t idx)201 bool wxAuiTabContainer::InsertPage(wxWindow* page,
202 const wxAuiNotebookPage& info,
203 size_t idx)
204 {
205 wxAuiNotebookPage page_info;
206 page_info = info;
207 page_info.window = page;
208
209 if (idx >= m_pages.GetCount())
210 m_pages.Add(page_info);
211 else
212 m_pages.Insert(page_info, idx);
213
214 // let the art provider know how many pages we have
215 if (m_art)
216 {
217 m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
218 }
219
220 return true;
221 }
222
MovePage(wxWindow * page,size_t new_idx)223 bool wxAuiTabContainer::MovePage(wxWindow* page,
224 size_t new_idx)
225 {
226 int idx = GetIdxFromWindow(page);
227 if (idx == -1)
228 return false;
229
230 // get page entry, make a copy of it
231 wxAuiNotebookPage p = GetPage(idx);
232
233 // remove old page entry
234 RemovePage(page);
235
236 // insert page where it should be
237 InsertPage(page, p, new_idx);
238
239 return true;
240 }
241
RemovePage(wxWindow * wnd)242 bool wxAuiTabContainer::RemovePage(wxWindow* wnd)
243 {
244 size_t i, page_count = m_pages.GetCount();
245 for (i = 0; i < page_count; ++i)
246 {
247 wxAuiNotebookPage& page = m_pages.Item(i);
248 if (page.window == wnd)
249 {
250 m_pages.RemoveAt(i);
251
252 // let the art provider know how many pages we have
253 if (m_art)
254 {
255 m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
256 }
257
258 return true;
259 }
260 }
261
262 return false;
263 }
264
SetActivePage(wxWindow * wnd)265 bool wxAuiTabContainer::SetActivePage(wxWindow* wnd)
266 {
267 bool found = false;
268
269 size_t i, page_count = m_pages.GetCount();
270 for (i = 0; i < page_count; ++i)
271 {
272 wxAuiNotebookPage& page = m_pages.Item(i);
273 if (page.window == wnd)
274 {
275 page.active = true;
276 found = true;
277 }
278 else
279 {
280 page.active = false;
281 }
282 }
283
284 return found;
285 }
286
SetNoneActive()287 void wxAuiTabContainer::SetNoneActive()
288 {
289 size_t i, page_count = m_pages.GetCount();
290 for (i = 0; i < page_count; ++i)
291 {
292 wxAuiNotebookPage& page = m_pages.Item(i);
293 page.active = false;
294 }
295 }
296
SetActivePage(size_t page)297 bool wxAuiTabContainer::SetActivePage(size_t page)
298 {
299 if (page >= m_pages.GetCount())
300 return false;
301
302 return SetActivePage(m_pages.Item(page).window);
303 }
304
GetActivePage() const305 int wxAuiTabContainer::GetActivePage() const
306 {
307 size_t i, page_count = m_pages.GetCount();
308 for (i = 0; i < page_count; ++i)
309 {
310 wxAuiNotebookPage& page = m_pages.Item(i);
311 if (page.active)
312 return i;
313 }
314
315 return -1;
316 }
317
GetWindowFromIdx(size_t idx) const318 wxWindow* wxAuiTabContainer::GetWindowFromIdx(size_t idx) const
319 {
320 if (idx >= m_pages.GetCount())
321 return NULL;
322
323 return m_pages[idx].window;
324 }
325
GetIdxFromWindow(wxWindow * wnd) const326 int wxAuiTabContainer::GetIdxFromWindow(wxWindow* wnd) const
327 {
328 const size_t page_count = m_pages.GetCount();
329 for ( size_t i = 0; i < page_count; ++i )
330 {
331 wxAuiNotebookPage& page = m_pages.Item(i);
332 if (page.window == wnd)
333 return i;
334 }
335 return wxNOT_FOUND;
336 }
337
GetPage(size_t idx)338 wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx)
339 {
340 wxASSERT_MSG(idx < m_pages.GetCount(), wxT("Invalid Page index"));
341
342 return m_pages[idx];
343 }
344
GetPage(size_t idx) const345 const wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx) const
346 {
347 wxASSERT_MSG(idx < m_pages.GetCount(), wxT("Invalid Page index"));
348
349 return m_pages[idx];
350 }
351
GetPages()352 wxAuiNotebookPageArray& wxAuiTabContainer::GetPages()
353 {
354 return m_pages;
355 }
356
GetPageCount() const357 size_t wxAuiTabContainer::GetPageCount() const
358 {
359 return m_pages.GetCount();
360 }
361
AddButton(int id,int location,const wxBitmap & normalBitmap,const wxBitmap & disabledBitmap)362 void wxAuiTabContainer::AddButton(int id,
363 int location,
364 const wxBitmap& normalBitmap,
365 const wxBitmap& disabledBitmap)
366 {
367 wxAuiTabContainerButton button;
368 button.id = id;
369 button.bitmap = normalBitmap;
370 button.disBitmap = disabledBitmap;
371 button.location = location;
372 button.curState = wxAUI_BUTTON_STATE_NORMAL;
373
374 m_buttons.Add(button);
375 }
376
RemoveButton(int id)377 void wxAuiTabContainer::RemoveButton(int id)
378 {
379 size_t i, button_count = m_buttons.GetCount();
380
381 for (i = 0; i < button_count; ++i)
382 {
383 if (m_buttons.Item(i).id == id)
384 {
385 m_buttons.RemoveAt(i);
386 return;
387 }
388 }
389 }
390
391
392
GetTabOffset() const393 size_t wxAuiTabContainer::GetTabOffset() const
394 {
395 return m_tabOffset;
396 }
397
SetTabOffset(size_t offset)398 void wxAuiTabContainer::SetTabOffset(size_t offset)
399 {
400 m_tabOffset = offset;
401 }
402
403
404
405
406 // Render() renders the tab catalog to the specified DC
407 // It is a virtual function and can be overridden to
408 // provide custom drawing capabilities
Render(wxDC * raw_dc,wxWindow * wnd)409 void wxAuiTabContainer::Render(wxDC* raw_dc, wxWindow* wnd)
410 {
411 if (!raw_dc || !raw_dc->IsOk())
412 return;
413
414 wxMemoryDC dc;
415
416 // use the same layout direction as the window DC uses to ensure that the
417 // text is rendered correctly
418 dc.SetLayoutDirection(raw_dc->GetLayoutDirection());
419
420 wxBitmap bmp;
421 size_t i;
422 size_t page_count = m_pages.GetCount();
423 size_t button_count = m_buttons.GetCount();
424
425 // create off-screen bitmap
426 bmp.Create(m_rect.GetWidth(), m_rect.GetHeight(),*raw_dc);
427 dc.SelectObject(bmp);
428
429 if (!dc.IsOk())
430 return;
431
432 // find out if size of tabs is larger than can be
433 // afforded on screen
434 int total_width = 0;
435 int visible_width = 0;
436 for (i = 0; i < page_count; ++i)
437 {
438 wxAuiNotebookPage& page = m_pages.Item(i);
439
440 // determine if a close button is on this tab
441 bool close_button = false;
442 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
443 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
444 {
445 close_button = true;
446 }
447
448
449 int x_extent = 0;
450 wxSize size = m_art->GetTabSize(dc,
451 wnd,
452 page.caption,
453 page.bitmap,
454 page.active,
455 close_button ?
456 wxAUI_BUTTON_STATE_NORMAL :
457 wxAUI_BUTTON_STATE_HIDDEN,
458 &x_extent);
459
460 if (i+1 < page_count)
461 total_width += x_extent;
462 else
463 total_width += size.x;
464
465 if (i >= m_tabOffset)
466 {
467 if (i+1 < page_count)
468 visible_width += x_extent;
469 else
470 visible_width += size.x;
471 }
472 }
473
474 if (total_width > m_rect.GetWidth() || m_tabOffset != 0)
475 {
476 // show left/right buttons
477 for (i = 0; i < button_count; ++i)
478 {
479 wxAuiTabContainerButton& button = m_buttons.Item(i);
480 if (button.id == wxAUI_BUTTON_LEFT ||
481 button.id == wxAUI_BUTTON_RIGHT)
482 {
483 button.curState &= ~wxAUI_BUTTON_STATE_HIDDEN;
484 }
485 }
486 }
487 else
488 {
489 // hide left/right buttons
490 for (i = 0; i < button_count; ++i)
491 {
492 wxAuiTabContainerButton& button = m_buttons.Item(i);
493 if (button.id == wxAUI_BUTTON_LEFT ||
494 button.id == wxAUI_BUTTON_RIGHT)
495 {
496 button.curState |= wxAUI_BUTTON_STATE_HIDDEN;
497 }
498 }
499 }
500
501 // determine whether left button should be enabled
502 for (i = 0; i < button_count; ++i)
503 {
504 wxAuiTabContainerButton& button = m_buttons.Item(i);
505 if (button.id == wxAUI_BUTTON_LEFT)
506 {
507 if (m_tabOffset == 0)
508 button.curState |= wxAUI_BUTTON_STATE_DISABLED;
509 else
510 button.curState &= ~wxAUI_BUTTON_STATE_DISABLED;
511 }
512 if (button.id == wxAUI_BUTTON_RIGHT)
513 {
514 if (visible_width < m_rect.GetWidth() - ((int)button_count*16))
515 button.curState |= wxAUI_BUTTON_STATE_DISABLED;
516 else
517 button.curState &= ~wxAUI_BUTTON_STATE_DISABLED;
518 }
519 }
520
521
522
523 // draw background
524 m_art->DrawBackground(dc, wnd, m_rect);
525
526 // draw buttons
527 int left_buttons_width = 0;
528 int right_buttons_width = 0;
529
530 // draw the buttons on the right side
531 int offset = m_rect.x + m_rect.width;
532 for (i = 0; i < button_count; ++i)
533 {
534 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
535
536 if (button.location != wxRIGHT)
537 continue;
538 if (button.curState & wxAUI_BUTTON_STATE_HIDDEN)
539 continue;
540
541 wxRect button_rect = m_rect;
542 button_rect.SetY(1);
543 button_rect.SetWidth(offset);
544
545 m_art->DrawButton(dc,
546 wnd,
547 button_rect,
548 button.id,
549 button.curState,
550 wxRIGHT,
551 &button.rect);
552
553 offset -= button.rect.GetWidth();
554 right_buttons_width += button.rect.GetWidth();
555 }
556
557
558
559 offset = 0;
560
561 // draw the buttons on the left side
562
563 for (i = 0; i < button_count; ++i)
564 {
565 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
566
567 if (button.location != wxLEFT)
568 continue;
569 if (button.curState & wxAUI_BUTTON_STATE_HIDDEN)
570 continue;
571
572 wxRect button_rect(offset, 1, 1000, m_rect.height);
573
574 m_art->DrawButton(dc,
575 wnd,
576 button_rect,
577 button.id,
578 button.curState,
579 wxLEFT,
580 &button.rect);
581
582 offset += button.rect.GetWidth();
583 left_buttons_width += button.rect.GetWidth();
584 }
585
586 offset = left_buttons_width;
587
588 if (offset == 0)
589 offset += m_art->GetIndentSize();
590
591
592 // prepare the tab-close-button array
593 // make sure tab button entries which aren't used are marked as hidden
594 for (i = page_count; i < m_tabCloseButtons.GetCount(); ++i)
595 m_tabCloseButtons.Item(i).curState = wxAUI_BUTTON_STATE_HIDDEN;
596
597 // make sure there are enough tab button entries to accommodate all tabs
598 while (m_tabCloseButtons.GetCount() < page_count)
599 {
600 wxAuiTabContainerButton tempbtn;
601 tempbtn.id = wxAUI_BUTTON_CLOSE;
602 tempbtn.location = wxCENTER;
603 tempbtn.curState = wxAUI_BUTTON_STATE_HIDDEN;
604 m_tabCloseButtons.Add(tempbtn);
605 }
606
607
608 // buttons before the tab offset must be set to hidden
609 for (i = 0; i < m_tabOffset; ++i)
610 {
611 m_tabCloseButtons.Item(i).curState = wxAUI_BUTTON_STATE_HIDDEN;
612 }
613
614
615 // draw the tabs
616
617 size_t active = 999;
618 int active_offset = 0;
619 wxRect active_rect;
620
621 int x_extent = 0;
622 wxRect rect = m_rect;
623 rect.y = 0;
624 rect.height = m_rect.height;
625
626 for (i = m_tabOffset; i < page_count; ++i)
627 {
628 wxAuiNotebookPage& page = m_pages.Item(i);
629 wxAuiTabContainerButton& tab_button = m_tabCloseButtons.Item(i);
630
631 // determine if a close button is on this tab
632 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
633 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
634 {
635 if (tab_button.curState == wxAUI_BUTTON_STATE_HIDDEN)
636 {
637 tab_button.id = wxAUI_BUTTON_CLOSE;
638 tab_button.curState = wxAUI_BUTTON_STATE_NORMAL;
639 tab_button.location = wxCENTER;
640 }
641 }
642 else
643 {
644 tab_button.curState = wxAUI_BUTTON_STATE_HIDDEN;
645 }
646
647 rect.x = offset;
648 rect.width = m_rect.width - right_buttons_width - offset - 2;
649
650 if (rect.width <= 0)
651 break;
652
653 m_art->DrawTab(dc,
654 wnd,
655 page,
656 rect,
657 tab_button.curState,
658 &page.rect,
659 &tab_button.rect,
660 &x_extent);
661
662 if (page.active)
663 {
664 active = i;
665 active_offset = offset;
666 active_rect = rect;
667 }
668
669 offset += x_extent;
670 }
671
672
673 // make sure to deactivate buttons which are off the screen to the right
674 for (++i; i < m_tabCloseButtons.GetCount(); ++i)
675 {
676 m_tabCloseButtons.Item(i).curState = wxAUI_BUTTON_STATE_HIDDEN;
677 }
678
679
680 // draw the active tab again so it stands in the foreground
681 if (active >= m_tabOffset && active < m_pages.GetCount())
682 {
683 wxAuiNotebookPage& page = m_pages.Item(active);
684
685 wxAuiTabContainerButton& tab_button = m_tabCloseButtons.Item(active);
686
687 rect.x = active_offset;
688 m_art->DrawTab(dc,
689 wnd,
690 page,
691 active_rect,
692 tab_button.curState,
693 &page.rect,
694 &tab_button.rect,
695 &x_extent);
696 }
697
698
699 raw_dc->Blit(m_rect.x, m_rect.y,
700 m_rect.GetWidth(), m_rect.GetHeight(),
701 &dc, 0, 0);
702 }
703
704 // Is the tab visible?
IsTabVisible(int tabPage,int tabOffset,wxDC * dc,wxWindow * wnd)705 bool wxAuiTabContainer::IsTabVisible(int tabPage, int tabOffset, wxDC* dc, wxWindow* wnd)
706 {
707 if (!dc || !dc->IsOk())
708 return false;
709
710 size_t i;
711 size_t page_count = m_pages.GetCount();
712 size_t button_count = m_buttons.GetCount();
713
714 // Hasn't been rendered yet; assume it's visible
715 if (m_tabCloseButtons.GetCount() < page_count)
716 return true;
717
718 // First check if both buttons are disabled - if so, there's no need to
719 // check further for visibility.
720 int arrowButtonVisibleCount = 0;
721 for (i = 0; i < button_count; ++i)
722 {
723 wxAuiTabContainerButton& button = m_buttons.Item(i);
724 if (button.id == wxAUI_BUTTON_LEFT ||
725 button.id == wxAUI_BUTTON_RIGHT)
726 {
727 if ((button.curState & wxAUI_BUTTON_STATE_HIDDEN) == 0)
728 arrowButtonVisibleCount ++;
729 }
730 }
731
732 // Tab must be visible
733 if (arrowButtonVisibleCount == 0)
734 return true;
735
736 // If tab is less than the given offset, it must be invisible by definition
737 if (tabPage < tabOffset)
738 return false;
739
740 // draw buttons
741 int left_buttons_width = 0;
742 int right_buttons_width = 0;
743
744 // calculate size of the buttons on the right side
745 int offset = m_rect.x + m_rect.width;
746 for (i = 0; i < button_count; ++i)
747 {
748 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
749
750 if (button.location != wxRIGHT)
751 continue;
752 if (button.curState & wxAUI_BUTTON_STATE_HIDDEN)
753 continue;
754
755 offset -= button.rect.GetWidth();
756 right_buttons_width += button.rect.GetWidth();
757 }
758
759 offset = 0;
760
761 // calculate size of the buttons on the left side
762 for (i = 0; i < button_count; ++i)
763 {
764 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
765
766 if (button.location != wxLEFT)
767 continue;
768 if (button.curState & wxAUI_BUTTON_STATE_HIDDEN)
769 continue;
770
771 offset += button.rect.GetWidth();
772 left_buttons_width += button.rect.GetWidth();
773 }
774
775 offset = left_buttons_width;
776
777 if (offset == 0)
778 offset += m_art->GetIndentSize();
779
780 wxRect active_rect;
781
782 wxRect rect = m_rect;
783 rect.y = 0;
784 rect.height = m_rect.height;
785
786 // See if the given page is visible at the given tab offset (effectively scroll position)
787 for (i = tabOffset; i < page_count; ++i)
788 {
789 wxAuiNotebookPage& page = m_pages.Item(i);
790 wxAuiTabContainerButton& tab_button = m_tabCloseButtons.Item(i);
791
792 rect.x = offset;
793 rect.width = m_rect.width - right_buttons_width - offset - 2;
794
795 if (rect.width <= 0)
796 return false; // haven't found the tab, and we've run out of space, so return false
797
798 int x_extent = 0;
799 m_art->GetTabSize(*dc,
800 wnd,
801 page.caption,
802 page.bitmap,
803 page.active,
804 tab_button.curState,
805 &x_extent);
806
807 offset += x_extent;
808
809 if (i == (size_t) tabPage)
810 {
811 // If not all of the tab is visible, and supposing there's space to display it all,
812 // we could do better so we return false.
813 if (((m_rect.width - right_buttons_width - offset - 2) <= 0) && ((m_rect.width - right_buttons_width - left_buttons_width) > x_extent))
814 return false;
815 else
816 return true;
817 }
818 }
819
820 // Shouldn't really get here, but if it does, assume the tab is visible to prevent
821 // further looping in calling code.
822 return true;
823 }
824
825 // Make the tab visible if it wasn't already
MakeTabVisible(int tabPage,wxWindow * win)826 void wxAuiTabContainer::MakeTabVisible(int tabPage, wxWindow* win)
827 {
828 wxClientDC dc(win);
829 if (!IsTabVisible(tabPage, GetTabOffset(), & dc, win))
830 {
831 int i;
832 for (i = 0; i < (int) m_pages.GetCount(); i++)
833 {
834 if (IsTabVisible(tabPage, i, & dc, win))
835 {
836 SetTabOffset(i);
837 win->Refresh();
838 return;
839 }
840 }
841 }
842 }
843
844 // TabHitTest() tests if a tab was hit, passing the window pointer
845 // back if that condition was fulfilled. The function returns
846 // true if a tab was hit, otherwise false
TabHitTest(int x,int y,wxWindow ** hit) const847 bool wxAuiTabContainer::TabHitTest(int x, int y, wxWindow** hit) const
848 {
849 if (!m_rect.Contains(x,y))
850 return false;
851
852 wxAuiTabContainerButton* btn = NULL;
853 if (ButtonHitTest(x, y, &btn) && !(btn->curState & wxAUI_BUTTON_STATE_DISABLED))
854 {
855 if (m_buttons.Index(*btn) != wxNOT_FOUND)
856 return false;
857 }
858
859 size_t i, page_count = m_pages.GetCount();
860
861 for (i = m_tabOffset; i < page_count; ++i)
862 {
863 wxAuiNotebookPage& page = m_pages.Item(i);
864 if (page.rect.Contains(x,y))
865 {
866 if (hit)
867 *hit = page.window;
868 return true;
869 }
870 }
871
872 return false;
873 }
874
875 // ButtonHitTest() tests if a button was hit. The function returns
876 // true if a button was hit, otherwise false
ButtonHitTest(int x,int y,wxAuiTabContainerButton ** hit) const877 bool wxAuiTabContainer::ButtonHitTest(int x, int y,
878 wxAuiTabContainerButton** hit) const
879 {
880 if (!m_rect.Contains(x,y))
881 return false;
882
883 size_t i, button_count;
884
885
886 button_count = m_buttons.GetCount();
887 for (i = 0; i < button_count; ++i)
888 {
889 wxAuiTabContainerButton& button = m_buttons.Item(i);
890 if (button.rect.Contains(x,y) &&
891 !(button.curState & wxAUI_BUTTON_STATE_HIDDEN ))
892 {
893 if (hit)
894 *hit = &button;
895 return true;
896 }
897 }
898
899 button_count = m_tabCloseButtons.GetCount();
900 for (i = 0; i < button_count; ++i)
901 {
902 wxAuiTabContainerButton& button = m_tabCloseButtons.Item(i);
903 if (button.rect.Contains(x,y) &&
904 !(button.curState & (wxAUI_BUTTON_STATE_HIDDEN |
905 wxAUI_BUTTON_STATE_DISABLED)))
906 {
907 if (hit)
908 *hit = &button;
909 return true;
910 }
911 }
912
913 return false;
914 }
915
916
917
918 // the utility function ShowWnd() is the same as show,
919 // except it handles wxAuiMDIChildFrame windows as well,
920 // as the Show() method on this class is "unplugged"
ShowWnd(wxWindow * wnd,bool show)921 static void ShowWnd(wxWindow* wnd, bool show)
922 {
923 #if wxUSE_MDI
924 if (wxDynamicCast(wnd, wxAuiMDIChildFrame))
925 {
926 wxAuiMDIChildFrame* cf = (wxAuiMDIChildFrame*)wnd;
927 cf->DoShow(show);
928 }
929 else
930 #endif
931 {
932 wnd->Show(show);
933 }
934 }
935
936
937 // DoShowHide() this function shows the active window, then
938 // hides all of the other windows (in that order)
DoShowHide()939 void wxAuiTabContainer::DoShowHide()
940 {
941 wxAuiNotebookPageArray& pages = GetPages();
942 size_t i, page_count = pages.GetCount();
943
944 // show new active page first
945 for (i = 0; i < page_count; ++i)
946 {
947 wxAuiNotebookPage& page = pages.Item(i);
948 if (page.active)
949 {
950 ShowWnd(page.window, true);
951 break;
952 }
953 }
954
955 // hide all other pages
956 for (i = 0; i < page_count; ++i)
957 {
958 wxAuiNotebookPage& page = pages.Item(i);
959 if (!page.active)
960 ShowWnd(page.window, false);
961 }
962 }
963
964
965
966
967
968
969 // -- wxAuiTabCtrl class implementation --
970
971
972
BEGIN_EVENT_TABLE(wxAuiTabCtrl,wxControl)973 BEGIN_EVENT_TABLE(wxAuiTabCtrl, wxControl)
974 EVT_PAINT(wxAuiTabCtrl::OnPaint)
975 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground)
976 EVT_SIZE(wxAuiTabCtrl::OnSize)
977 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown)
978 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDClick)
979 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp)
980 EVT_MIDDLE_DOWN(wxAuiTabCtrl::OnMiddleDown)
981 EVT_MIDDLE_UP(wxAuiTabCtrl::OnMiddleUp)
982 EVT_RIGHT_DOWN(wxAuiTabCtrl::OnRightDown)
983 EVT_RIGHT_UP(wxAuiTabCtrl::OnRightUp)
984 EVT_MOTION(wxAuiTabCtrl::OnMotion)
985 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow)
986 EVT_AUINOTEBOOK_BUTTON(wxID_ANY, wxAuiTabCtrl::OnButton)
987 EVT_SET_FOCUS(wxAuiTabCtrl::OnSetFocus)
988 EVT_KILL_FOCUS(wxAuiTabCtrl::OnKillFocus)
989 EVT_CHAR(wxAuiTabCtrl::OnChar)
990 EVT_MOUSE_CAPTURE_LOST(wxAuiTabCtrl::OnCaptureLost)
991 END_EVENT_TABLE()
992
993
994 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow* parent,
995 wxWindowID id,
996 const wxPoint& pos,
997 const wxSize& size,
998 long style) : wxControl(parent, id, pos, size, style)
999 {
1000 SetName(wxT("wxAuiTabCtrl"));
1001 m_clickPt = wxDefaultPosition;
1002 m_isDragging = false;
1003 m_hoverButton = NULL;
1004 m_pressedButton = NULL;
1005 }
1006
~wxAuiTabCtrl()1007 wxAuiTabCtrl::~wxAuiTabCtrl()
1008 {
1009 }
1010
OnPaint(wxPaintEvent &)1011 void wxAuiTabCtrl::OnPaint(wxPaintEvent&)
1012 {
1013 wxPaintDC dc(this);
1014
1015 dc.SetFont(GetFont());
1016
1017 if (GetPageCount() > 0)
1018 Render(&dc, this);
1019 }
1020
OnEraseBackground(wxEraseEvent & WXUNUSED (evt))1021 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
1022 {
1023 }
1024
OnSize(wxSizeEvent & evt)1025 void wxAuiTabCtrl::OnSize(wxSizeEvent& evt)
1026 {
1027 wxSize s = evt.GetSize();
1028 wxRect r(0, 0, s.GetWidth(), s.GetHeight());
1029 SetRect(r);
1030 }
1031
OnLeftDown(wxMouseEvent & evt)1032 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt)
1033 {
1034 CaptureMouse();
1035 m_clickPt = wxDefaultPosition;
1036 m_isDragging = false;
1037 m_clickTab = NULL;
1038 m_pressedButton = NULL;
1039
1040
1041 wxWindow* wnd;
1042 if (TabHitTest(evt.m_x, evt.m_y, &wnd))
1043 {
1044 int new_selection = GetIdxFromWindow(wnd);
1045
1046 // wxAuiNotebooks always want to receive this event
1047 // even if the tab is already active, because they may
1048 // have multiple tab controls
1049 if ((new_selection != GetActivePage() ||
1050 wxDynamicCast(GetParent(), wxAuiNotebook)) && !m_hoverButton)
1051 {
1052 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1053 e.SetSelection(new_selection);
1054 e.SetOldSelection(GetActivePage());
1055 e.SetEventObject(this);
1056 GetEventHandler()->ProcessEvent(e);
1057 }
1058
1059 m_clickPt.x = evt.m_x;
1060 m_clickPt.y = evt.m_y;
1061 m_clickTab = wnd;
1062 }
1063
1064 if (m_hoverButton)
1065 {
1066 m_pressedButton = m_hoverButton;
1067 m_pressedButton->curState = wxAUI_BUTTON_STATE_PRESSED;
1068 Refresh();
1069 Update();
1070 }
1071 }
1072
OnCaptureLost(wxMouseCaptureLostEvent & WXUNUSED (event))1073 void wxAuiTabCtrl::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
1074 {
1075 if (m_isDragging)
1076 {
1077 m_isDragging = false;
1078
1079 wxAuiNotebookEvent evt(wxEVT_AUINOTEBOOK_CANCEL_DRAG, m_windowId);
1080 evt.SetSelection(GetIdxFromWindow(m_clickTab));
1081 evt.SetOldSelection(evt.GetSelection());
1082 evt.SetEventObject(this);
1083 GetEventHandler()->ProcessEvent(evt);
1084 }
1085 }
1086
OnLeftUp(wxMouseEvent & evt)1087 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent& evt)
1088 {
1089 if (GetCapture() == this)
1090 ReleaseMouse();
1091
1092 if (m_isDragging)
1093 {
1094 m_isDragging = false;
1095
1096 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_END_DRAG, m_windowId);
1097 e.SetSelection(GetIdxFromWindow(m_clickTab));
1098 e.SetOldSelection(e.GetSelection());
1099 e.SetEventObject(this);
1100 GetEventHandler()->ProcessEvent(e);
1101
1102 return;
1103 }
1104
1105 if (m_pressedButton)
1106 {
1107 // make sure we're still clicking the button
1108 wxAuiTabContainerButton* button = NULL;
1109 if (!ButtonHitTest(evt.m_x, evt.m_y, &button) ||
1110 button->curState & wxAUI_BUTTON_STATE_DISABLED)
1111 return;
1112
1113 if (button != m_pressedButton)
1114 {
1115 m_pressedButton = NULL;
1116 return;
1117 }
1118
1119 Refresh();
1120 Update();
1121
1122 if (!(m_pressedButton->curState & wxAUI_BUTTON_STATE_DISABLED))
1123 {
1124 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_BUTTON, m_windowId);
1125 e.SetSelection(GetIdxFromWindow(m_clickTab));
1126 e.SetInt(m_pressedButton->id);
1127 e.SetEventObject(this);
1128 GetEventHandler()->ProcessEvent(e);
1129 }
1130
1131 m_pressedButton = NULL;
1132 }
1133
1134 m_clickPt = wxDefaultPosition;
1135 m_isDragging = false;
1136 m_clickTab = NULL;
1137 }
1138
OnMiddleUp(wxMouseEvent & evt)1139 void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent& evt)
1140 {
1141 wxWindow* wnd = NULL;
1142 if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
1143 return;
1144
1145 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_MIDDLE_UP, m_windowId);
1146 e.SetEventObject(this);
1147 e.SetSelection(GetIdxFromWindow(wnd));
1148 GetEventHandler()->ProcessEvent(e);
1149 }
1150
OnMiddleDown(wxMouseEvent & evt)1151 void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent& evt)
1152 {
1153 wxWindow* wnd = NULL;
1154 if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
1155 return;
1156
1157 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_MIDDLE_DOWN, m_windowId);
1158 e.SetEventObject(this);
1159 e.SetSelection(GetIdxFromWindow(wnd));
1160 GetEventHandler()->ProcessEvent(e);
1161 }
1162
OnRightUp(wxMouseEvent & evt)1163 void wxAuiTabCtrl::OnRightUp(wxMouseEvent& evt)
1164 {
1165 wxWindow* wnd = NULL;
1166 if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
1167 return;
1168
1169 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_RIGHT_UP, m_windowId);
1170 e.SetEventObject(this);
1171 e.SetSelection(GetIdxFromWindow(wnd));
1172 GetEventHandler()->ProcessEvent(e);
1173 }
1174
OnRightDown(wxMouseEvent & evt)1175 void wxAuiTabCtrl::OnRightDown(wxMouseEvent& evt)
1176 {
1177 wxWindow* wnd = NULL;
1178 if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
1179 return;
1180
1181 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN, m_windowId);
1182 e.SetEventObject(this);
1183 e.SetSelection(GetIdxFromWindow(wnd));
1184 GetEventHandler()->ProcessEvent(e);
1185 }
1186
OnLeftDClick(wxMouseEvent & evt)1187 void wxAuiTabCtrl::OnLeftDClick(wxMouseEvent& evt)
1188 {
1189 wxWindow* wnd;
1190 wxAuiTabContainerButton* button;
1191 if (!TabHitTest(evt.m_x, evt.m_y, &wnd) && !ButtonHitTest(evt.m_x, evt.m_y, &button))
1192 {
1193 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_BG_DCLICK, m_windowId);
1194 e.SetEventObject(this);
1195 GetEventHandler()->ProcessEvent(e);
1196 }
1197 }
1198
OnMotion(wxMouseEvent & evt)1199 void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt)
1200 {
1201 wxPoint pos = evt.GetPosition();
1202
1203 // check if the mouse is hovering above a button
1204 wxAuiTabContainerButton* button;
1205 if (ButtonHitTest(pos.x, pos.y, &button) && !(button->curState & wxAUI_BUTTON_STATE_DISABLED))
1206 {
1207 if (m_hoverButton && button != m_hoverButton)
1208 {
1209 m_hoverButton->curState = wxAUI_BUTTON_STATE_NORMAL;
1210 m_hoverButton = NULL;
1211 Refresh();
1212 Update();
1213 }
1214
1215 if (button->curState != wxAUI_BUTTON_STATE_HOVER)
1216 {
1217 button->curState = wxAUI_BUTTON_STATE_HOVER;
1218 Refresh();
1219 Update();
1220
1221 m_hoverButton = button;
1222 return;
1223 }
1224 }
1225 else
1226 {
1227 if (m_hoverButton)
1228 {
1229 m_hoverButton->curState = wxAUI_BUTTON_STATE_NORMAL;
1230 m_hoverButton = NULL;
1231 Refresh();
1232 Update();
1233 }
1234 }
1235
1236 #if wxUSE_TOOLTIPS
1237 wxWindow* wnd = NULL;
1238 if (evt.Moving() && TabHitTest(evt.m_x, evt.m_y, &wnd))
1239 {
1240 wxString tooltip(m_pages[GetIdxFromWindow(wnd)].tooltip);
1241
1242 // If the text changes, set it else, keep old, to avoid
1243 // 'moving tooltip' effect
1244 if (GetToolTipText() != tooltip)
1245 SetToolTip(tooltip);
1246 }
1247 else
1248 UnsetToolTip();
1249 #endif // wxUSE_TOOLTIPS
1250
1251 if (!evt.LeftIsDown() || m_clickPt == wxDefaultPosition)
1252 return;
1253
1254 if (m_isDragging)
1255 {
1256 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_DRAG_MOTION, m_windowId);
1257 e.SetSelection(GetIdxFromWindow(m_clickTab));
1258 e.SetOldSelection(e.GetSelection());
1259 e.SetEventObject(this);
1260 GetEventHandler()->ProcessEvent(e);
1261 return;
1262 }
1263
1264
1265 int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
1266 int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
1267
1268 if (abs(pos.x - m_clickPt.x) > drag_x_threshold ||
1269 abs(pos.y - m_clickPt.y) > drag_y_threshold)
1270 {
1271 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_BEGIN_DRAG, m_windowId);
1272 e.SetSelection(GetIdxFromWindow(m_clickTab));
1273 e.SetOldSelection(e.GetSelection());
1274 e.SetEventObject(this);
1275 GetEventHandler()->ProcessEvent(e);
1276
1277 m_isDragging = true;
1278 }
1279 }
1280
OnLeaveWindow(wxMouseEvent & WXUNUSED (event))1281 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event))
1282 {
1283 if (m_hoverButton)
1284 {
1285 m_hoverButton->curState = wxAUI_BUTTON_STATE_NORMAL;
1286 m_hoverButton = NULL;
1287 Refresh();
1288 Update();
1289 }
1290 }
1291
OnButton(wxAuiNotebookEvent & event)1292 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent& event)
1293 {
1294 int button = event.GetInt();
1295
1296 if (button == wxAUI_BUTTON_LEFT || button == wxAUI_BUTTON_RIGHT)
1297 {
1298 if (button == wxAUI_BUTTON_LEFT)
1299 {
1300 if (GetTabOffset() > 0)
1301 {
1302 SetTabOffset(GetTabOffset()-1);
1303 Refresh();
1304 Update();
1305 }
1306 }
1307 else
1308 {
1309 SetTabOffset(GetTabOffset()+1);
1310 Refresh();
1311 Update();
1312 }
1313 }
1314 else if (button == wxAUI_BUTTON_WINDOWLIST)
1315 {
1316 int idx = GetArtProvider()->ShowDropDown(this, m_pages, GetActivePage());
1317
1318 if (idx != -1)
1319 {
1320 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1321 e.SetSelection(idx);
1322 e.SetOldSelection(GetActivePage());
1323 e.SetEventObject(this);
1324 GetEventHandler()->ProcessEvent(e);
1325 }
1326 }
1327 else
1328 {
1329 event.Skip();
1330 }
1331 }
1332
OnSetFocus(wxFocusEvent & WXUNUSED (event))1333 void wxAuiTabCtrl::OnSetFocus(wxFocusEvent& WXUNUSED(event))
1334 {
1335 Refresh();
1336 }
1337
OnKillFocus(wxFocusEvent & WXUNUSED (event))1338 void wxAuiTabCtrl::OnKillFocus(wxFocusEvent& WXUNUSED(event))
1339 {
1340 Refresh();
1341 }
1342
OnChar(wxKeyEvent & event)1343 void wxAuiTabCtrl::OnChar(wxKeyEvent& event)
1344 {
1345 if (GetActivePage() == -1)
1346 {
1347 event.Skip();
1348 return;
1349 }
1350
1351 // We can't leave tab processing to the system; on Windows, tabs and keys
1352 // get eaten by the system and not processed properly if we specify both
1353 // wxTAB_TRAVERSAL and wxWANTS_CHARS. And if we specify just wxTAB_TRAVERSAL,
1354 // we don't key arrow key events.
1355
1356 int key = event.GetKeyCode();
1357
1358 if (key == WXK_NUMPAD_PAGEUP)
1359 key = WXK_PAGEUP;
1360 if (key == WXK_NUMPAD_PAGEDOWN)
1361 key = WXK_PAGEDOWN;
1362 if (key == WXK_NUMPAD_HOME)
1363 key = WXK_HOME;
1364 if (key == WXK_NUMPAD_END)
1365 key = WXK_END;
1366 if (key == WXK_NUMPAD_LEFT)
1367 key = WXK_LEFT;
1368 if (key == WXK_NUMPAD_RIGHT)
1369 key = WXK_RIGHT;
1370
1371 if (key == WXK_TAB || key == WXK_PAGEUP || key == WXK_PAGEDOWN)
1372 {
1373 bool bCtrlDown = event.ControlDown();
1374 bool bShiftDown = event.ShiftDown();
1375
1376 bool bForward = (key == WXK_TAB && !bShiftDown) || (key == WXK_PAGEDOWN);
1377 bool bWindowChange = (key == WXK_PAGEUP) || (key == WXK_PAGEDOWN) || bCtrlDown;
1378 bool bFromTab = (key == WXK_TAB);
1379
1380 if (bFromTab && !bWindowChange)
1381 {
1382 // Handle ordinary tabs via Navigate. This is needed at least for wxGTK to tab properly.
1383 Navigate(bForward ? wxNavigationKeyEvent::IsForward : wxNavigationKeyEvent::IsBackward);
1384 return;
1385 }
1386
1387 wxAuiNotebook* nb = wxDynamicCast(GetParent(), wxAuiNotebook);
1388 if (!nb)
1389 {
1390 event.Skip();
1391 return;
1392 }
1393
1394 wxNavigationKeyEvent keyEvent;
1395 keyEvent.SetDirection(bForward);
1396 keyEvent.SetWindowChange(bWindowChange);
1397 keyEvent.SetFromTab(bFromTab);
1398 keyEvent.SetEventObject(nb);
1399
1400 if (!nb->GetEventHandler()->ProcessEvent(keyEvent))
1401 {
1402 // Not processed? Do an explicit tab into the page.
1403 wxWindow* win = GetWindowFromIdx(GetActivePage());
1404 if (win)
1405 win->SetFocus();
1406 }
1407 return;
1408 }
1409
1410 if (m_pages.GetCount() < 2)
1411 {
1412 event.Skip();
1413 return;
1414 }
1415
1416 int newPage = -1;
1417
1418 int forwardKey, backwardKey;
1419 if (GetLayoutDirection() == wxLayout_RightToLeft)
1420 {
1421 forwardKey = WXK_LEFT;
1422 backwardKey = WXK_RIGHT;
1423 }
1424 else
1425 {
1426 forwardKey = WXK_RIGHT;
1427 backwardKey = WXK_LEFT;
1428 }
1429
1430 if (key == forwardKey)
1431 {
1432 if (m_pages.GetCount() > 1)
1433 {
1434 if (GetActivePage() == -1)
1435 newPage = 0;
1436 else if (GetActivePage() < (int) (m_pages.GetCount() - 1))
1437 newPage = GetActivePage() + 1;
1438 }
1439 }
1440 else if (key == backwardKey)
1441 {
1442 if (m_pages.GetCount() > 1)
1443 {
1444 if (GetActivePage() == -1)
1445 newPage = (int) (m_pages.GetCount() - 1);
1446 else if (GetActivePage() > 0)
1447 newPage = GetActivePage() - 1;
1448 }
1449 }
1450 else if (key == WXK_HOME)
1451 {
1452 newPage = 0;
1453 }
1454 else if (key == WXK_END)
1455 {
1456 newPage = (int) (m_pages.GetCount() - 1);
1457 }
1458 else
1459 event.Skip();
1460
1461 if (newPage != -1)
1462 {
1463 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1464 e.SetSelection(newPage);
1465 e.SetOldSelection(newPage);
1466 e.SetEventObject(this);
1467 this->GetEventHandler()->ProcessEvent(e);
1468 }
1469 else
1470 event.Skip();
1471 }
1472
1473 // wxTabFrame is an interesting case. It's important that all child pages
1474 // of the multi-notebook control are all actually children of that control
1475 // (and not grandchildren). wxTabFrame facilitates this. There is one
1476 // instance of wxTabFrame for each tab control inside the multi-notebook.
1477 // It's important to know that wxTabFrame is not a real window, but it merely
1478 // used to capture the dimensions/positioning of the internal tab control and
1479 // it's managed page windows
1480
1481 class wxTabFrame : public wxWindow
1482 {
1483 public:
1484
wxTabFrame()1485 wxTabFrame()
1486 {
1487 m_tabs = NULL;
1488 m_rect = wxRect(0,0,200,200);
1489 m_tabCtrlHeight = 20;
1490 }
1491
~wxTabFrame()1492 ~wxTabFrame()
1493 {
1494 wxDELETE(m_tabs);
1495 }
1496
SetTabCtrlHeight(int h)1497 void SetTabCtrlHeight(int h)
1498 {
1499 m_tabCtrlHeight = h;
1500 }
1501
1502 protected:
DoSetSize(int x,int y,int width,int height,int WXUNUSED (sizeFlags=wxSIZE_AUTO))1503 void DoSetSize(int x, int y,
1504 int width, int height,
1505 int WXUNUSED(sizeFlags = wxSIZE_AUTO))
1506 {
1507 m_rect = wxRect(x, y, width, height);
1508 DoSizing();
1509 }
1510
DoGetClientSize(int * x,int * y) const1511 void DoGetClientSize(int* x, int* y) const
1512 {
1513 *x = m_rect.width;
1514 *y = m_rect.height;
1515 }
1516
1517 public:
Show(bool WXUNUSED (show=true))1518 bool Show( bool WXUNUSED(show = true) ) { return false; }
1519
DoSizing()1520 void DoSizing()
1521 {
1522 if (!m_tabs)
1523 return;
1524
1525 if (m_tabs->IsFrozen() || m_tabs->GetParent()->IsFrozen())
1526 return;
1527
1528 m_tab_rect = wxRect(m_rect.x, m_rect.y, m_rect.width, m_tabCtrlHeight);
1529 if (m_tabs->GetFlags() & wxAUI_NB_BOTTOM)
1530 {
1531 m_tab_rect = wxRect (m_rect.x, m_rect.y + m_rect.height - m_tabCtrlHeight, m_rect.width, m_tabCtrlHeight);
1532 m_tabs->SetSize (m_rect.x, m_rect.y + m_rect.height - m_tabCtrlHeight, m_rect.width, m_tabCtrlHeight);
1533 m_tabs->SetRect (wxRect(0, 0, m_rect.width, m_tabCtrlHeight));
1534 }
1535 else //TODO: if (GetFlags() & wxAUI_NB_TOP)
1536 {
1537 m_tab_rect = wxRect (m_rect.x, m_rect.y, m_rect.width, m_tabCtrlHeight);
1538 m_tabs->SetSize (m_rect.x, m_rect.y, m_rect.width, m_tabCtrlHeight);
1539 m_tabs->SetRect (wxRect(0, 0, m_rect.width, m_tabCtrlHeight));
1540 }
1541 // TODO: else if (GetFlags() & wxAUI_NB_LEFT){}
1542 // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){}
1543
1544 m_tabs->Refresh();
1545 m_tabs->Update();
1546
1547 wxAuiNotebookPageArray& pages = m_tabs->GetPages();
1548 size_t i, page_count = pages.GetCount();
1549
1550 for (i = 0; i < page_count; ++i)
1551 {
1552 wxAuiNotebookPage& page = pages.Item(i);
1553 int border_space = m_tabs->GetArtProvider()->GetAdditionalBorderSpace(page.window);
1554
1555 int height = m_rect.height - m_tabCtrlHeight - border_space;
1556 if ( height < 0 )
1557 {
1558 // avoid passing negative height to wxWindow::SetSize(), this
1559 // results in assert failures/GTK+ warnings
1560 height = 0;
1561 }
1562 int width = m_rect.width - 2 * border_space;
1563 if (width < 0)
1564 width = 0;
1565
1566 if (m_tabs->GetFlags() & wxAUI_NB_BOTTOM)
1567 {
1568 page.window->SetSize(m_rect.x + border_space,
1569 m_rect.y + border_space,
1570 width,
1571 height);
1572 }
1573 else //TODO: if (GetFlags() & wxAUI_NB_TOP)
1574 {
1575 page.window->SetSize(m_rect.x + border_space,
1576 m_rect.y + m_tabCtrlHeight,
1577 width,
1578 height);
1579 }
1580 // TODO: else if (GetFlags() & wxAUI_NB_LEFT){}
1581 // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){}
1582
1583 #if wxUSE_MDI
1584 if (wxDynamicCast(page.window, wxAuiMDIChildFrame))
1585 {
1586 wxAuiMDIChildFrame* wnd = (wxAuiMDIChildFrame*)page.window;
1587 wnd->ApplyMDIChildFrameRect();
1588 }
1589 #endif
1590 }
1591 }
1592
1593 protected:
DoGetSize(int * x,int * y) const1594 void DoGetSize(int* x, int* y) const
1595 {
1596 if (x)
1597 *x = m_rect.GetWidth();
1598 if (y)
1599 *y = m_rect.GetHeight();
1600 }
1601
1602 public:
Update()1603 void Update()
1604 {
1605 // does nothing
1606 }
1607
1608 wxRect m_rect;
1609 wxRect m_tab_rect;
1610 wxAuiTabCtrl* m_tabs;
1611 int m_tabCtrlHeight;
1612 };
1613
1614
1615 const int wxAuiBaseTabCtrlId = 5380;
1616
1617
1618 // -- wxAuiNotebook class implementation --
1619
1620 #define EVT_AUI_RANGE(id1, id2, event, func) \
1621 wx__DECLARE_EVT2(event, id1, id2, wxAuiNotebookEventHandler(func))
1622
BEGIN_EVENT_TABLE(wxAuiNotebook,wxControl)1623 BEGIN_EVENT_TABLE(wxAuiNotebook, wxControl)
1624 EVT_SIZE(wxAuiNotebook::OnSize)
1625 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocusNotebook)
1626 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
1627 wxEVT_AUINOTEBOOK_PAGE_CHANGING,
1628 wxAuiNotebook::OnTabClicked)
1629 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
1630 wxEVT_AUINOTEBOOK_BEGIN_DRAG,
1631 wxAuiNotebook::OnTabBeginDrag)
1632 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
1633 wxEVT_AUINOTEBOOK_END_DRAG,
1634 wxAuiNotebook::OnTabEndDrag)
1635 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
1636 wxEVT_AUINOTEBOOK_CANCEL_DRAG,
1637 wxAuiNotebook::OnTabCancelDrag)
1638 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
1639 wxEVT_AUINOTEBOOK_DRAG_MOTION,
1640 wxAuiNotebook::OnTabDragMotion)
1641 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
1642 wxEVT_AUINOTEBOOK_BUTTON,
1643 wxAuiNotebook::OnTabButton)
1644 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
1645 wxEVT_AUINOTEBOOK_TAB_MIDDLE_DOWN,
1646 wxAuiNotebook::OnTabMiddleDown)
1647 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
1648 wxEVT_AUINOTEBOOK_TAB_MIDDLE_UP,
1649 wxAuiNotebook::OnTabMiddleUp)
1650 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
1651 wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN,
1652 wxAuiNotebook::OnTabRightDown)
1653 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
1654 wxEVT_AUINOTEBOOK_TAB_RIGHT_UP,
1655 wxAuiNotebook::OnTabRightUp)
1656 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
1657 wxEVT_AUINOTEBOOK_BG_DCLICK,
1658 wxAuiNotebook::OnTabBgDClick)
1659 EVT_NAVIGATION_KEY(wxAuiNotebook::OnNavigationKeyNotebook)
1660 END_EVENT_TABLE()
1661
1662 void wxAuiNotebook::Init()
1663 {
1664 m_curPage = -1;
1665 m_tabIdCounter = wxAuiBaseTabCtrlId;
1666 m_dummyWnd = NULL;
1667 m_tabCtrlHeight = 20;
1668 m_requestedBmpSize = wxDefaultSize;
1669 m_requestedTabCtrlHeight = -1;
1670 }
1671
Create(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style)1672 bool wxAuiNotebook::Create(wxWindow* parent,
1673 wxWindowID id,
1674 const wxPoint& pos,
1675 const wxSize& size,
1676 long style)
1677 {
1678 if (!wxControl::Create(parent, id, pos, size, style))
1679 return false;
1680
1681 InitNotebook(style);
1682
1683 return true;
1684 }
1685
1686 // InitNotebook() contains common initialization
1687 // code called by all constructors
InitNotebook(long style)1688 void wxAuiNotebook::InitNotebook(long style)
1689 {
1690 SetName(wxT("wxAuiNotebook"));
1691 m_curPage = -1;
1692 m_tabIdCounter = wxAuiBaseTabCtrlId;
1693 m_dummyWnd = NULL;
1694 m_flags = (unsigned int)style;
1695 m_tabCtrlHeight = 20;
1696
1697 m_normalFont = *wxNORMAL_FONT;
1698 m_selectedFont = *wxNORMAL_FONT;
1699 m_selectedFont.SetWeight(wxBOLD);
1700
1701 SetArtProvider(new wxAuiDefaultTabArt);
1702
1703 m_dummyWnd = new wxWindow(this, wxID_ANY, wxPoint(0,0), wxSize(0,0));
1704 m_dummyWnd->SetSize(200, 200);
1705 m_dummyWnd->Show(false);
1706
1707 m_mgr.SetManagedWindow(this);
1708 m_mgr.SetFlags(wxAUI_MGR_DEFAULT);
1709 m_mgr.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
1710
1711 m_mgr.AddPane(m_dummyWnd,
1712 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
1713
1714 m_mgr.Update();
1715 }
1716
~wxAuiNotebook()1717 wxAuiNotebook::~wxAuiNotebook()
1718 {
1719 // Indicate we're deleting pages
1720 SendDestroyEvent();
1721
1722 while ( GetPageCount() > 0 )
1723 DeletePage(0);
1724
1725 m_mgr.UnInit();
1726 }
1727
SetArtProvider(wxAuiTabArt * art)1728 void wxAuiNotebook::SetArtProvider(wxAuiTabArt* art)
1729 {
1730 m_tabs.SetArtProvider(art);
1731
1732 // Update the height and do nothing else if it did something but otherwise
1733 // (i.e. if the new art provider uses the same height as the old one) we
1734 // need to manually set the art provider for all tabs ourselves.
1735 if ( !UpdateTabCtrlHeight() )
1736 {
1737 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1738 const size_t pane_count = all_panes.GetCount();
1739 for (size_t i = 0; i < pane_count; ++i)
1740 {
1741 wxAuiPaneInfo& pane = all_panes.Item(i);
1742 if (pane.name == wxT("dummy"))
1743 continue;
1744 wxTabFrame* tab_frame = (wxTabFrame*)pane.window;
1745 wxAuiTabCtrl* tabctrl = tab_frame->m_tabs;
1746 tabctrl->SetArtProvider(art->Clone());
1747 }
1748 }
1749 }
1750
1751 // SetTabCtrlHeight() is the highest-level override of the
1752 // tab height. A call to this function effectively enforces a
1753 // specified tab ctrl height, overriding all other considerations,
1754 // such as text or bitmap height. It overrides any call to
1755 // SetUniformBitmapSize(). Specifying a height of -1 reverts
1756 // any previous call and returns to the default behaviour
1757
SetTabCtrlHeight(int height)1758 void wxAuiNotebook::SetTabCtrlHeight(int height)
1759 {
1760 m_requestedTabCtrlHeight = height;
1761
1762 // if window is already initialized, recalculate the tab height
1763 if (m_dummyWnd)
1764 {
1765 UpdateTabCtrlHeight();
1766 }
1767 }
1768
1769
1770 // SetUniformBitmapSize() ensures that all tabs will have
1771 // the same height, even if some tabs don't have bitmaps
1772 // Passing wxDefaultSize to this function will instruct
1773 // the control to use dynamic tab height-- so when a tab
1774 // with a large bitmap is added, the tab ctrl's height will
1775 // automatically increase to accommodate the bitmap
1776
SetUniformBitmapSize(const wxSize & size)1777 void wxAuiNotebook::SetUniformBitmapSize(const wxSize& size)
1778 {
1779 m_requestedBmpSize = size;
1780
1781 // if window is already initialized, recalculate the tab height
1782 if (m_dummyWnd)
1783 {
1784 UpdateTabCtrlHeight();
1785 }
1786 }
1787
1788 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
1789 // to be used internally
UpdateTabCtrlHeight()1790 bool wxAuiNotebook::UpdateTabCtrlHeight()
1791 {
1792 // get the tab ctrl height we will use
1793 int height = CalculateTabCtrlHeight();
1794
1795 // if the tab control height needs to change, update
1796 // all of our tab controls with the new height
1797 if (m_tabCtrlHeight == height)
1798 return false;
1799
1800 wxAuiTabArt* art = m_tabs.GetArtProvider();
1801
1802 m_tabCtrlHeight = height;
1803
1804 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1805 size_t i, pane_count = all_panes.GetCount();
1806 for (i = 0; i < pane_count; ++i)
1807 {
1808 wxAuiPaneInfo& pane = all_panes.Item(i);
1809 if (pane.name == wxT("dummy"))
1810 continue;
1811 wxTabFrame* tab_frame = (wxTabFrame*)pane.window;
1812 wxAuiTabCtrl* tabctrl = tab_frame->m_tabs;
1813 tab_frame->SetTabCtrlHeight(m_tabCtrlHeight);
1814 tabctrl->SetArtProvider(art->Clone());
1815 tab_frame->DoSizing();
1816 }
1817
1818 return true;
1819 }
1820
UpdateHintWindowSize()1821 void wxAuiNotebook::UpdateHintWindowSize()
1822 {
1823 wxSize size = CalculateNewSplitSize();
1824
1825 // the placeholder hint window should be set to this size
1826 wxAuiPaneInfo& info = m_mgr.GetPane(wxT("dummy"));
1827 if (info.IsOk())
1828 {
1829 info.MinSize(size);
1830 info.BestSize(size);
1831 m_dummyWnd->SetSize(size);
1832 }
1833 }
1834
1835
1836 // calculates the size of the new split
CalculateNewSplitSize()1837 wxSize wxAuiNotebook::CalculateNewSplitSize()
1838 {
1839 // count number of tab controls
1840 int tab_ctrl_count = 0;
1841 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1842 size_t i, pane_count = all_panes.GetCount();
1843 for (i = 0; i < pane_count; ++i)
1844 {
1845 wxAuiPaneInfo& pane = all_panes.Item(i);
1846 if (pane.name == wxT("dummy"))
1847 continue;
1848 tab_ctrl_count++;
1849 }
1850
1851 wxSize new_split_size;
1852
1853 // if there is only one tab control, the first split
1854 // should happen around the middle
1855 if (tab_ctrl_count < 2)
1856 {
1857 new_split_size = GetClientSize();
1858 new_split_size.x /= 2;
1859 new_split_size.y /= 2;
1860 }
1861 else
1862 {
1863 // this is in place of a more complicated calculation
1864 // that needs to be implemented
1865 new_split_size = wxSize(180,180);
1866 }
1867
1868 return new_split_size;
1869 }
1870
CalculateTabCtrlHeight()1871 int wxAuiNotebook::CalculateTabCtrlHeight()
1872 {
1873 // if a fixed tab ctrl height is specified,
1874 // just return that instead of calculating a
1875 // tab height
1876 if (m_requestedTabCtrlHeight != -1)
1877 return m_requestedTabCtrlHeight;
1878
1879 // find out new best tab height
1880 wxAuiTabArt* art = m_tabs.GetArtProvider();
1881
1882 return art->GetBestTabCtrlSize(this,
1883 m_tabs.GetPages(),
1884 m_requestedBmpSize);
1885 }
1886
1887
GetArtProvider() const1888 wxAuiTabArt* wxAuiNotebook::GetArtProvider() const
1889 {
1890 return m_tabs.GetArtProvider();
1891 }
1892
SetWindowStyleFlag(long style)1893 void wxAuiNotebook::SetWindowStyleFlag(long style)
1894 {
1895 wxControl::SetWindowStyleFlag(style);
1896
1897 m_flags = (unsigned int)style;
1898
1899 // if the control is already initialized
1900 if (m_mgr.GetManagedWindow() == (wxWindow*)this)
1901 {
1902 // let all of the tab children know about the new style
1903
1904 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1905 size_t i, pane_count = all_panes.GetCount();
1906 for (i = 0; i < pane_count; ++i)
1907 {
1908 wxAuiPaneInfo& pane = all_panes.Item(i);
1909 if (pane.name == wxT("dummy"))
1910 continue;
1911 wxTabFrame* tabframe = (wxTabFrame*)pane.window;
1912 wxAuiTabCtrl* tabctrl = tabframe->m_tabs;
1913 tabctrl->SetFlags(m_flags);
1914 tabframe->DoSizing();
1915 tabctrl->Refresh();
1916 tabctrl->Update();
1917 }
1918 }
1919 }
1920
1921
AddPage(wxWindow * page,const wxString & caption,bool select,const wxBitmap & bitmap)1922 bool wxAuiNotebook::AddPage(wxWindow* page,
1923 const wxString& caption,
1924 bool select,
1925 const wxBitmap& bitmap)
1926 {
1927 return InsertPage(GetPageCount(), page, caption, select, bitmap);
1928 }
1929
InsertPage(size_t page_idx,wxWindow * page,const wxString & caption,bool select,const wxBitmap & bitmap)1930 bool wxAuiNotebook::InsertPage(size_t page_idx,
1931 wxWindow* page,
1932 const wxString& caption,
1933 bool select,
1934 const wxBitmap& bitmap)
1935 {
1936 wxASSERT_MSG(page, wxT("page pointer must be non-NULL"));
1937 if (!page)
1938 return false;
1939
1940 page->Reparent(this);
1941
1942 wxAuiNotebookPage info;
1943 info.window = page;
1944 info.caption = caption;
1945 info.bitmap = bitmap;
1946 info.active = false;
1947
1948 // if there are currently no tabs, the first added
1949 // tab must be active
1950 if (m_tabs.GetPageCount() == 0)
1951 info.active = true;
1952
1953 m_tabs.InsertPage(page, info, page_idx);
1954
1955 // if that was the first page added, even if
1956 // select is false, it must become the "current page"
1957 // (though no select events will be fired)
1958 if (!select && m_tabs.GetPageCount() == 1)
1959 select = true;
1960 //m_curPage = GetPageIndex(page);
1961
1962 wxAuiTabCtrl* active_tabctrl = GetActiveTabCtrl();
1963 if (page_idx >= active_tabctrl->GetPageCount())
1964 active_tabctrl->AddPage(page, info);
1965 else
1966 active_tabctrl->InsertPage(page, info, page_idx);
1967
1968 UpdateTabCtrlHeight();
1969 DoSizing();
1970 active_tabctrl->DoShowHide();
1971
1972 // adjust selected index
1973 if(m_curPage >= (int) page_idx)
1974 m_curPage++;
1975
1976 if (select)
1977 {
1978 SetSelectionToWindow(page);
1979 }
1980
1981 return true;
1982 }
1983
1984
1985 // DeletePage() removes a tab from the multi-notebook,
1986 // and destroys the window as well
DeletePage(size_t page_idx)1987 bool wxAuiNotebook::DeletePage(size_t page_idx)
1988 {
1989 if (page_idx >= m_tabs.GetPageCount())
1990 return false;
1991
1992 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
1993
1994 // hide the window in advance, as this will
1995 // prevent flicker
1996 ShowWnd(wnd, false);
1997
1998 if (!RemovePage(page_idx))
1999 return false;
2000
2001 #if wxUSE_MDI
2002 // actually destroy the window now
2003 if (wxDynamicCast(wnd, wxAuiMDIChildFrame))
2004 {
2005 // delete the child frame with pending delete, as is
2006 // customary with frame windows
2007 if (!wxPendingDelete.Member(wnd))
2008 wxPendingDelete.Append(wnd);
2009 }
2010 else
2011 #endif
2012 {
2013 wnd->Destroy();
2014 }
2015
2016 return true;
2017 }
2018
2019
2020
2021 // RemovePage() removes a tab from the multi-notebook,
2022 // but does not destroy the window
RemovePage(size_t page_idx)2023 bool wxAuiNotebook::RemovePage(size_t page_idx)
2024 {
2025 // save active window pointer
2026 wxWindow* active_wnd = NULL;
2027 if (m_curPage >= 0)
2028 active_wnd = m_tabs.GetWindowFromIdx(m_curPage);
2029
2030 // save pointer of window being deleted
2031 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
2032 wxWindow* new_active = NULL;
2033
2034 // make sure we found the page
2035 if (!wnd)
2036 return false;
2037
2038 // find out which onscreen tab ctrl owns this tab
2039 wxAuiTabCtrl* ctrl;
2040 int ctrl_idx;
2041 if (!FindTab(wnd, &ctrl, &ctrl_idx))
2042 return false;
2043
2044 bool is_curpage = (m_curPage == (int)page_idx);
2045 bool is_active_in_split = ctrl->GetPage(ctrl_idx).active;
2046
2047
2048 // remove the tab from main catalog
2049 if (!m_tabs.RemovePage(wnd))
2050 return false;
2051
2052 // remove the tab from the onscreen tab ctrl
2053 ctrl->RemovePage(wnd);
2054
2055 if (is_active_in_split)
2056 {
2057 int ctrl_new_page_count = (int)ctrl->GetPageCount();
2058
2059 if (ctrl_idx >= ctrl_new_page_count)
2060 ctrl_idx = ctrl_new_page_count-1;
2061
2062 if (ctrl_idx >= 0 && ctrl_idx < (int)ctrl->GetPageCount())
2063 {
2064 // set new page as active in the tab split
2065 ctrl->SetActivePage(ctrl_idx);
2066
2067 // if the page deleted was the current page for the
2068 // entire tab control, then record the window
2069 // pointer of the new active page for activation
2070 if (is_curpage)
2071 {
2072 new_active = ctrl->GetWindowFromIdx(ctrl_idx);
2073 }
2074 }
2075 }
2076 else
2077 {
2078 // we are not deleting the active page, so keep it the same
2079 new_active = active_wnd;
2080 }
2081
2082
2083 if (!new_active)
2084 {
2085 // we haven't yet found a new page to active,
2086 // so select the next page from the main tab
2087 // catalogue
2088
2089 if (page_idx < m_tabs.GetPageCount())
2090 {
2091 new_active = m_tabs.GetPage(page_idx).window;
2092 }
2093
2094 if (!new_active && m_tabs.GetPageCount() > 0)
2095 {
2096 new_active = m_tabs.GetPage(0).window;
2097 }
2098 }
2099
2100
2101 RemoveEmptyTabFrames();
2102
2103 m_curPage = wxNOT_FOUND;
2104
2105 // set new active pane unless we're being destroyed anyhow
2106 if (new_active && !m_isBeingDeleted)
2107 SetSelectionToWindow(new_active);
2108
2109 return true;
2110 }
2111
2112 // GetPageIndex() returns the index of the page, or -1 if the
2113 // page could not be located in the notebook
GetPageIndex(wxWindow * page_wnd) const2114 int wxAuiNotebook::GetPageIndex(wxWindow* page_wnd) const
2115 {
2116 return m_tabs.GetIdxFromWindow(page_wnd);
2117 }
2118
2119
2120
2121 // SetPageText() changes the tab caption of the specified page
SetPageText(size_t page_idx,const wxString & text)2122 bool wxAuiNotebook::SetPageText(size_t page_idx, const wxString& text)
2123 {
2124 if (page_idx >= m_tabs.GetPageCount())
2125 return false;
2126
2127 // update our own tab catalog
2128 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
2129 page_info.caption = text;
2130
2131 // update what's on screen
2132 wxAuiTabCtrl* ctrl;
2133 int ctrl_idx;
2134 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
2135 {
2136 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
2137 info.caption = text;
2138 ctrl->Refresh();
2139 ctrl->Update();
2140 }
2141
2142 return true;
2143 }
2144
2145 // returns the page caption
GetPageText(size_t page_idx) const2146 wxString wxAuiNotebook::GetPageText(size_t page_idx) const
2147 {
2148 if (page_idx >= m_tabs.GetPageCount())
2149 return wxEmptyString;
2150
2151 // update our own tab catalog
2152 const wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
2153 return page_info.caption;
2154 }
2155
SetPageToolTip(size_t page_idx,const wxString & text)2156 bool wxAuiNotebook::SetPageToolTip(size_t page_idx, const wxString& text)
2157 {
2158 if (page_idx >= m_tabs.GetPageCount())
2159 return false;
2160
2161 // update our own tab catalog
2162 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
2163 page_info.tooltip = text;
2164
2165 wxAuiTabCtrl* ctrl;
2166 int ctrl_idx;
2167 if (!FindTab(page_info.window, &ctrl, &ctrl_idx))
2168 return false;
2169
2170 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
2171 info.tooltip = text;
2172
2173 // NB: we don't update the tooltip if it is already being displayed, it
2174 // typically never happens, no need to code that
2175 return true;
2176 }
2177
GetPageToolTip(size_t page_idx) const2178 wxString wxAuiNotebook::GetPageToolTip(size_t page_idx) const
2179 {
2180 if (page_idx >= m_tabs.GetPageCount())
2181 return wxString();
2182
2183 const wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
2184 return page_info.tooltip;
2185 }
2186
SetPageBitmap(size_t page_idx,const wxBitmap & bitmap)2187 bool wxAuiNotebook::SetPageBitmap(size_t page_idx, const wxBitmap& bitmap)
2188 {
2189 if (page_idx >= m_tabs.GetPageCount())
2190 return false;
2191
2192 // update our own tab catalog
2193 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
2194 page_info.bitmap = bitmap;
2195
2196 // tab height might have changed
2197 UpdateTabCtrlHeight();
2198
2199 // update what's on screen
2200 wxAuiTabCtrl* ctrl;
2201 int ctrl_idx;
2202 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
2203 {
2204 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
2205 info.bitmap = bitmap;
2206 ctrl->Refresh();
2207 ctrl->Update();
2208 }
2209
2210 return true;
2211 }
2212
2213 // returns the page bitmap
GetPageBitmap(size_t page_idx) const2214 wxBitmap wxAuiNotebook::GetPageBitmap(size_t page_idx) const
2215 {
2216 if (page_idx >= m_tabs.GetPageCount())
2217 return wxBitmap();
2218
2219 // update our own tab catalog
2220 const wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
2221 return page_info.bitmap;
2222 }
2223
2224 // GetSelection() returns the index of the currently active page
GetSelection() const2225 int wxAuiNotebook::GetSelection() const
2226 {
2227 return m_curPage;
2228 }
2229
2230 // SetSelection() sets the currently active page
SetSelection(size_t new_page)2231 int wxAuiNotebook::SetSelection(size_t new_page)
2232 {
2233 return DoModifySelection(new_page, true);
2234 }
2235
SetSelectionToWindow(wxWindow * win)2236 void wxAuiNotebook::SetSelectionToWindow(wxWindow *win)
2237 {
2238 const int idx = m_tabs.GetIdxFromWindow(win);
2239 wxCHECK_RET( idx != wxNOT_FOUND, wxT("invalid notebook page") );
2240
2241
2242 // since a tab was clicked, let the parent know that we received
2243 // the focus, even if we will assign that focus immediately
2244 // to the child tab in the SetSelection call below
2245 // (the child focus event will also let wxAuiManager, if any,
2246 // know that the notebook control has been activated)
2247
2248 wxWindow* parent = GetParent();
2249 if (parent)
2250 {
2251 wxChildFocusEvent eventFocus(this);
2252 parent->GetEventHandler()->ProcessEvent(eventFocus);
2253 }
2254
2255
2256 SetSelection(idx);
2257 }
2258
2259 // GetPageCount() returns the total number of
2260 // pages managed by the multi-notebook
GetPageCount() const2261 size_t wxAuiNotebook::GetPageCount() const
2262 {
2263 return m_tabs.GetPageCount();
2264 }
2265
2266 // GetPage() returns the wxWindow pointer of the
2267 // specified page
GetPage(size_t page_idx) const2268 wxWindow* wxAuiNotebook::GetPage(size_t page_idx) const
2269 {
2270 wxASSERT(page_idx < m_tabs.GetPageCount());
2271
2272 return m_tabs.GetWindowFromIdx(page_idx);
2273 }
2274
2275 // DoSizing() performs all sizing operations in each tab control
DoSizing()2276 void wxAuiNotebook::DoSizing()
2277 {
2278 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
2279 size_t i, pane_count = all_panes.GetCount();
2280 for (i = 0; i < pane_count; ++i)
2281 {
2282 if (all_panes.Item(i).name == wxT("dummy"))
2283 continue;
2284
2285 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
2286 tabframe->DoSizing();
2287 }
2288 }
2289
2290 // GetActiveTabCtrl() returns the active tab control. It is
2291 // called to determine which control gets new windows being added
GetActiveTabCtrl()2292 wxAuiTabCtrl* wxAuiNotebook::GetActiveTabCtrl()
2293 {
2294 if (m_curPage >= 0 && m_curPage < (int)m_tabs.GetPageCount())
2295 {
2296 wxAuiTabCtrl* ctrl;
2297 int idx;
2298
2299 // find the tab ctrl with the current page
2300 if (FindTab(m_tabs.GetPage(m_curPage).window,
2301 &ctrl, &idx))
2302 {
2303 return ctrl;
2304 }
2305 }
2306
2307 // no current page, just find the first tab ctrl
2308 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
2309 size_t i, pane_count = all_panes.GetCount();
2310 for (i = 0; i < pane_count; ++i)
2311 {
2312 if (all_panes.Item(i).name == wxT("dummy"))
2313 continue;
2314
2315 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
2316 return tabframe->m_tabs;
2317 }
2318
2319 // If there is no tabframe at all, create one
2320 wxTabFrame* tabframe = new wxTabFrame;
2321 tabframe->SetTabCtrlHeight(m_tabCtrlHeight);
2322 tabframe->m_tabs = new wxAuiTabCtrl(this,
2323 m_tabIdCounter++,
2324 wxDefaultPosition,
2325 wxDefaultSize,
2326 wxNO_BORDER|wxWANTS_CHARS);
2327 tabframe->m_tabs->SetFlags(m_flags);
2328 tabframe->m_tabs->SetArtProvider(m_tabs.GetArtProvider()->Clone());
2329 m_mgr.AddPane(tabframe,
2330 wxAuiPaneInfo().Center().CaptionVisible(false));
2331
2332 m_mgr.Update();
2333
2334 return tabframe->m_tabs;
2335 }
2336
2337 // FindTab() finds the tab control that currently contains the window as well
2338 // as the index of the window in the tab control. It returns true if the
2339 // window was found, otherwise false.
FindTab(wxWindow * page,wxAuiTabCtrl ** ctrl,int * idx)2340 bool wxAuiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx)
2341 {
2342 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
2343 size_t i, pane_count = all_panes.GetCount();
2344 for (i = 0; i < pane_count; ++i)
2345 {
2346 if (all_panes.Item(i).name == wxT("dummy"))
2347 continue;
2348
2349 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
2350
2351 int page_idx = tabframe->m_tabs->GetIdxFromWindow(page);
2352 if (page_idx != -1)
2353 {
2354 *ctrl = tabframe->m_tabs;
2355 *idx = page_idx;
2356 return true;
2357 }
2358 }
2359
2360 return false;
2361 }
2362
Split(size_t page,int direction)2363 void wxAuiNotebook::Split(size_t page, int direction)
2364 {
2365 wxSize cli_size = GetClientSize();
2366
2367 // get the page's window pointer
2368 wxWindow* wnd = GetPage(page);
2369 if (!wnd)
2370 return;
2371
2372 // notebooks with 1 or less pages can't be split
2373 if (GetPageCount() < 2)
2374 return;
2375
2376 // find out which tab control the page currently belongs to
2377 wxAuiTabCtrl *src_tabs, *dest_tabs;
2378 int src_idx = -1;
2379 src_tabs = NULL;
2380 if (!FindTab(wnd, &src_tabs, &src_idx))
2381 return;
2382 if (!src_tabs || src_idx == -1)
2383 return;
2384
2385 // choose a split size
2386 wxSize split_size;
2387 if (GetPageCount() > 2)
2388 {
2389 split_size = CalculateNewSplitSize();
2390 }
2391 else
2392 {
2393 // because there are two panes, always split them
2394 // equally
2395 split_size = GetClientSize();
2396 split_size.x /= 2;
2397 split_size.y /= 2;
2398 }
2399
2400
2401 // create a new tab frame
2402 wxTabFrame* new_tabs = new wxTabFrame;
2403 new_tabs->m_rect = wxRect(wxPoint(0,0), split_size);
2404 new_tabs->SetTabCtrlHeight(m_tabCtrlHeight);
2405 new_tabs->m_tabs = new wxAuiTabCtrl(this,
2406 m_tabIdCounter++,
2407 wxDefaultPosition,
2408 wxDefaultSize,
2409 wxNO_BORDER|wxWANTS_CHARS);
2410 new_tabs->m_tabs->SetArtProvider(m_tabs.GetArtProvider()->Clone());
2411 new_tabs->m_tabs->SetFlags(m_flags);
2412 dest_tabs = new_tabs->m_tabs;
2413
2414 // create a pane info structure with the information
2415 // about where the pane should be added
2416 wxAuiPaneInfo paneInfo = wxAuiPaneInfo().Bottom().CaptionVisible(false);
2417 wxPoint mouse_pt;
2418
2419 if (direction == wxLEFT)
2420 {
2421 paneInfo.Left();
2422 mouse_pt = wxPoint(0, cli_size.y/2);
2423 }
2424 else if (direction == wxRIGHT)
2425 {
2426 paneInfo.Right();
2427 mouse_pt = wxPoint(cli_size.x, cli_size.y/2);
2428 }
2429 else if (direction == wxTOP)
2430 {
2431 paneInfo.Top();
2432 mouse_pt = wxPoint(cli_size.x/2, 0);
2433 }
2434 else if (direction == wxBOTTOM)
2435 {
2436 paneInfo.Bottom();
2437 mouse_pt = wxPoint(cli_size.x/2, cli_size.y);
2438 }
2439
2440 m_mgr.AddPane(new_tabs, paneInfo, mouse_pt);
2441 m_mgr.Update();
2442
2443 // remove the page from the source tabs
2444 wxAuiNotebookPage page_info = src_tabs->GetPage(src_idx);
2445 page_info.active = false;
2446 src_tabs->RemovePage(page_info.window);
2447 if (src_tabs->GetPageCount() > 0)
2448 {
2449 src_tabs->SetActivePage((size_t)0);
2450 src_tabs->DoShowHide();
2451 src_tabs->Refresh();
2452 }
2453
2454
2455 // add the page to the destination tabs
2456 dest_tabs->InsertPage(page_info.window, page_info, 0);
2457
2458 if (src_tabs->GetPageCount() == 0)
2459 {
2460 RemoveEmptyTabFrames();
2461 }
2462
2463 DoSizing();
2464 dest_tabs->DoShowHide();
2465 dest_tabs->Refresh();
2466
2467 // force the set selection function reset the selection
2468 m_curPage = -1;
2469
2470 // set the active page to the one we just split off
2471 SetSelectionToPage(page_info);
2472
2473 UpdateHintWindowSize();
2474 }
2475
2476
OnSize(wxSizeEvent & evt)2477 void wxAuiNotebook::OnSize(wxSizeEvent& evt)
2478 {
2479 UpdateHintWindowSize();
2480
2481 evt.Skip();
2482 }
2483
OnTabClicked(wxAuiNotebookEvent & evt)2484 void wxAuiNotebook::OnTabClicked(wxAuiNotebookEvent& evt)
2485 {
2486 wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject();
2487 wxASSERT(ctrl != NULL);
2488
2489 wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection());
2490 wxASSERT(wnd != NULL);
2491
2492 SetSelectionToWindow(wnd);
2493 }
2494
OnTabBgDClick(wxAuiNotebookEvent & evt)2495 void wxAuiNotebook::OnTabBgDClick(wxAuiNotebookEvent& evt)
2496 {
2497 // select the tab ctrl which received the db click
2498 int selection;
2499 wxWindow* wnd;
2500 wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject();
2501 if ( (ctrl != NULL)
2502 && ((selection = ctrl->GetActivePage()) != wxNOT_FOUND)
2503 && ((wnd = ctrl->GetWindowFromIdx(selection)) != NULL))
2504 {
2505 SetSelectionToWindow(wnd);
2506 }
2507
2508 // notify owner that the tabbar background has been double-clicked
2509 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_BG_DCLICK, m_windowId);
2510 e.SetEventObject(this);
2511 GetEventHandler()->ProcessEvent(e);
2512 }
2513
OnTabBeginDrag(wxAuiNotebookEvent &)2514 void wxAuiNotebook::OnTabBeginDrag(wxAuiNotebookEvent&)
2515 {
2516 m_lastDragX = 0;
2517 }
2518
OnTabDragMotion(wxAuiNotebookEvent & evt)2519 void wxAuiNotebook::OnTabDragMotion(wxAuiNotebookEvent& evt)
2520 {
2521 wxPoint screen_pt = ::wxGetMousePosition();
2522 wxPoint client_pt = ScreenToClient(screen_pt);
2523 wxPoint zero(0,0);
2524
2525 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
2526 wxAuiTabCtrl* dest_tabs = GetTabCtrlFromPoint(client_pt);
2527
2528 if (dest_tabs == src_tabs)
2529 {
2530 if (src_tabs)
2531 {
2532 src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
2533 }
2534
2535 // always hide the hint for inner-tabctrl drag
2536 m_mgr.HideHint();
2537
2538 // if tab moving is not allowed, leave
2539 if (!(m_flags & wxAUI_NB_TAB_MOVE))
2540 {
2541 return;
2542 }
2543
2544 wxPoint pt = dest_tabs->ScreenToClient(screen_pt);
2545 wxWindow* dest_location_tab;
2546
2547 // this is an inner-tab drag/reposition
2548 if (dest_tabs->TabHitTest(pt.x, pt.y, &dest_location_tab))
2549 {
2550 int src_idx = evt.GetSelection();
2551 int dest_idx = dest_tabs->GetIdxFromWindow(dest_location_tab);
2552
2553 // prevent jumpy drag
2554 if ((src_idx == dest_idx) || dest_idx == -1 ||
2555 (src_idx > dest_idx && m_lastDragX <= pt.x) ||
2556 (src_idx < dest_idx && m_lastDragX >= pt.x))
2557 {
2558 m_lastDragX = pt.x;
2559 return;
2560 }
2561
2562
2563 wxWindow* src_tab = dest_tabs->GetWindowFromIdx(src_idx);
2564 dest_tabs->MovePage(src_tab, dest_idx);
2565 m_tabs.MovePage(m_tabs.GetPage(src_idx).window, dest_idx);
2566 dest_tabs->SetActivePage((size_t)dest_idx);
2567 dest_tabs->DoShowHide();
2568 dest_tabs->Refresh();
2569 m_lastDragX = pt.x;
2570
2571 }
2572
2573 return;
2574 }
2575
2576
2577 // if external drag is allowed, check if the tab is being dragged
2578 // over a different wxAuiNotebook control
2579 if (m_flags & wxAUI_NB_TAB_EXTERNAL_MOVE)
2580 {
2581 wxWindow* tab_ctrl = ::wxFindWindowAtPoint(screen_pt);
2582
2583 // if we aren't over any window, stop here
2584 if (!tab_ctrl)
2585 return;
2586
2587 // make sure we are not over the hint window
2588 if (!wxDynamicCast(tab_ctrl, wxFrame))
2589 {
2590 while (tab_ctrl)
2591 {
2592 if (wxDynamicCast(tab_ctrl, wxAuiTabCtrl))
2593 break;
2594 tab_ctrl = tab_ctrl->GetParent();
2595 }
2596
2597 if (tab_ctrl)
2598 {
2599 wxAuiNotebook* nb = (wxAuiNotebook*)tab_ctrl->GetParent();
2600
2601 if (nb != this)
2602 {
2603 wxRect hint_rect = tab_ctrl->GetClientRect();
2604 tab_ctrl->ClientToScreen(&hint_rect.x, &hint_rect.y);
2605 m_mgr.ShowHint(hint_rect);
2606 return;
2607 }
2608 }
2609 }
2610 else
2611 {
2612 if (!dest_tabs)
2613 {
2614 // we are either over a hint window, or not over a tab
2615 // window, and there is no where to drag to, so exit
2616 return;
2617 }
2618 }
2619 }
2620
2621
2622 // if there are less than two panes, split can't happen, so leave
2623 if (m_tabs.GetPageCount() < 2)
2624 return;
2625
2626 // if tab moving is not allowed, leave
2627 if (!(m_flags & wxAUI_NB_TAB_SPLIT))
2628 return;
2629
2630
2631 if (src_tabs)
2632 {
2633 src_tabs->SetCursor(wxCursor(wxCURSOR_SIZING));
2634 }
2635
2636
2637 if (dest_tabs)
2638 {
2639 wxRect hint_rect = dest_tabs->GetRect();
2640 ClientToScreen(&hint_rect.x, &hint_rect.y);
2641 m_mgr.ShowHint(hint_rect);
2642 }
2643 else
2644 {
2645 m_mgr.DrawHintRect(m_dummyWnd, client_pt, zero);
2646 }
2647 }
2648
2649
2650
OnTabEndDrag(wxAuiNotebookEvent & evt)2651 void wxAuiNotebook::OnTabEndDrag(wxAuiNotebookEvent& evt)
2652 {
2653 m_mgr.HideHint();
2654
2655
2656 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
2657 wxCHECK_RET( src_tabs, wxT("no source object?") );
2658
2659 src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
2660
2661 // get the mouse position, which will be used to determine the drop point
2662 wxPoint mouse_screen_pt = ::wxGetMousePosition();
2663 wxPoint mouse_client_pt = ScreenToClient(mouse_screen_pt);
2664
2665
2666
2667 // check for an external move
2668 if (m_flags & wxAUI_NB_TAB_EXTERNAL_MOVE)
2669 {
2670 wxWindow* tab_ctrl = ::wxFindWindowAtPoint(mouse_screen_pt);
2671
2672 while (tab_ctrl)
2673 {
2674 if (wxDynamicCast(tab_ctrl, wxAuiTabCtrl))
2675 break;
2676 tab_ctrl = tab_ctrl->GetParent();
2677 }
2678
2679 if (tab_ctrl)
2680 {
2681 wxAuiNotebook* nb = (wxAuiNotebook*)tab_ctrl->GetParent();
2682
2683 if (nb != this)
2684 {
2685 // find out from the destination control
2686 // if it's ok to drop this tab here
2687 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_ALLOW_DND, m_windowId);
2688 e.SetSelection(evt.GetSelection());
2689 e.SetOldSelection(evt.GetSelection());
2690 e.SetEventObject(this);
2691 e.SetDragSource(this);
2692 e.Veto(); // dropping must be explicitly approved by control owner
2693
2694 nb->GetEventHandler()->ProcessEvent(e);
2695
2696 if (!e.IsAllowed())
2697 {
2698 // no answer or negative answer
2699 m_mgr.HideHint();
2700 return;
2701 }
2702
2703 // drop was allowed
2704 int src_idx = evt.GetSelection();
2705 wxWindow* src_page = src_tabs->GetWindowFromIdx(src_idx);
2706
2707 // Check that it's not an impossible parent relationship
2708 wxWindow* p = nb;
2709 while (p && !p->IsTopLevel())
2710 {
2711 if (p == src_page)
2712 {
2713 return;
2714 }
2715 p = p->GetParent();
2716 }
2717
2718 // get main index of the page
2719 int main_idx = m_tabs.GetIdxFromWindow(src_page);
2720 wxCHECK_RET( main_idx != wxNOT_FOUND, wxT("no source page?") );
2721
2722
2723 // make a copy of the page info
2724 wxAuiNotebookPage page_info = m_tabs.GetPage(main_idx);
2725
2726 // remove the page from the source notebook
2727 RemovePage(main_idx);
2728
2729 // reparent the page
2730 src_page->Reparent(nb);
2731
2732
2733 // found out the insert idx
2734 wxAuiTabCtrl* dest_tabs = (wxAuiTabCtrl*)tab_ctrl;
2735 wxPoint pt = dest_tabs->ScreenToClient(mouse_screen_pt);
2736
2737 wxWindow* target = NULL;
2738 int insert_idx = -1;
2739 dest_tabs->TabHitTest(pt.x, pt.y, &target);
2740 if (target)
2741 {
2742 insert_idx = dest_tabs->GetIdxFromWindow(target);
2743 }
2744
2745
2746 // add the page to the new notebook
2747 if (insert_idx == -1)
2748 insert_idx = dest_tabs->GetPageCount();
2749 dest_tabs->InsertPage(page_info.window, page_info, insert_idx);
2750 nb->m_tabs.InsertPage(page_info.window, page_info, insert_idx);
2751
2752 nb->DoSizing();
2753 dest_tabs->SetActivePage(insert_idx);
2754 dest_tabs->DoShowHide();
2755 dest_tabs->Refresh();
2756
2757 // set the selection in the destination tab control
2758 nb->DoModifySelection(insert_idx, false);
2759
2760 // notify owner that the tab has been dragged
2761 wxAuiNotebookEvent e2(wxEVT_AUINOTEBOOK_DRAG_DONE, m_windowId);
2762 e2.SetSelection(evt.GetSelection());
2763 e2.SetOldSelection(evt.GetSelection());
2764 e2.SetEventObject(this);
2765 GetEventHandler()->ProcessEvent(e2);
2766
2767 return;
2768 }
2769 }
2770 }
2771
2772
2773
2774
2775 // only perform a tab split if it's allowed
2776 wxAuiTabCtrl* dest_tabs = NULL;
2777
2778 if ((m_flags & wxAUI_NB_TAB_SPLIT) && m_tabs.GetPageCount() >= 2)
2779 {
2780 // If the pointer is in an existing tab frame, do a tab insert
2781 wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt);
2782 wxTabFrame* tab_frame = (wxTabFrame*)GetTabFrameFromTabCtrl(hit_wnd);
2783 int insert_idx = -1;
2784 if (tab_frame)
2785 {
2786 dest_tabs = tab_frame->m_tabs;
2787
2788 if (dest_tabs == src_tabs)
2789 {
2790 m_curPage = evt.GetSelection();
2791 return;
2792 }
2793
2794 wxPoint pt = dest_tabs->ScreenToClient(mouse_screen_pt);
2795 wxWindow* target = NULL;
2796 dest_tabs->TabHitTest(pt.x, pt.y, &target);
2797 if (target)
2798 {
2799 insert_idx = dest_tabs->GetIdxFromWindow(target);
2800 }
2801 }
2802 else
2803 {
2804 wxPoint zero(0,0);
2805 wxRect rect = m_mgr.CalculateHintRect(m_dummyWnd,
2806 mouse_client_pt,
2807 zero);
2808 if (rect.IsEmpty())
2809 {
2810 // there is no suitable drop location here, exit out
2811 return;
2812 }
2813
2814 // If there is no tabframe at all, create one
2815 wxTabFrame* new_tabs = new wxTabFrame;
2816 new_tabs->m_rect = wxRect(wxPoint(0,0), CalculateNewSplitSize());
2817 new_tabs->SetTabCtrlHeight(m_tabCtrlHeight);
2818 new_tabs->m_tabs = new wxAuiTabCtrl(this,
2819 m_tabIdCounter++,
2820 wxDefaultPosition,
2821 wxDefaultSize,
2822 wxNO_BORDER|wxWANTS_CHARS);
2823 new_tabs->m_tabs->SetArtProvider(m_tabs.GetArtProvider()->Clone());
2824 new_tabs->m_tabs->SetFlags(m_flags);
2825
2826 m_mgr.AddPane(new_tabs,
2827 wxAuiPaneInfo().Bottom().CaptionVisible(false),
2828 mouse_client_pt);
2829 m_mgr.Update();
2830 dest_tabs = new_tabs->m_tabs;
2831 }
2832
2833
2834
2835 // remove the page from the source tabs
2836 wxAuiNotebookPage page_info = src_tabs->GetPage(evt.GetSelection());
2837 page_info.active = false;
2838 src_tabs->RemovePage(page_info.window);
2839 if (src_tabs->GetPageCount() > 0)
2840 {
2841 src_tabs->SetActivePage((size_t)0);
2842 src_tabs->DoShowHide();
2843 src_tabs->Refresh();
2844 }
2845
2846
2847
2848 // add the page to the destination tabs
2849 if (insert_idx == -1)
2850 insert_idx = dest_tabs->GetPageCount();
2851 dest_tabs->InsertPage(page_info.window, page_info, insert_idx);
2852
2853 if (src_tabs->GetPageCount() == 0)
2854 {
2855 RemoveEmptyTabFrames();
2856 }
2857
2858 DoSizing();
2859 dest_tabs->DoShowHide();
2860 dest_tabs->Refresh();
2861
2862 // force the set selection function reset the selection
2863 m_curPage = -1;
2864
2865 // set the active page to the one we just split off
2866 SetSelectionToPage(page_info);
2867
2868 UpdateHintWindowSize();
2869 }
2870
2871 // notify owner that the tab has been dragged
2872 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_DRAG_DONE, m_windowId);
2873 e.SetSelection(evt.GetSelection());
2874 e.SetOldSelection(evt.GetSelection());
2875 e.SetEventObject(this);
2876 GetEventHandler()->ProcessEvent(e);
2877 }
2878
2879
2880
OnTabCancelDrag(wxAuiNotebookEvent & command_evt)2881 void wxAuiNotebook::OnTabCancelDrag(wxAuiNotebookEvent& command_evt)
2882 {
2883 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
2884
2885 m_mgr.HideHint();
2886
2887 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
2888 wxCHECK_RET( src_tabs, wxT("no source object?") );
2889
2890 src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
2891 }
2892
GetTabCtrlFromPoint(const wxPoint & pt)2893 wxAuiTabCtrl* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint& pt)
2894 {
2895 // if we've just removed the last tab from the source
2896 // tab set, the remove the tab control completely
2897 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
2898 size_t i, pane_count = all_panes.GetCount();
2899 for (i = 0; i < pane_count; ++i)
2900 {
2901 if (all_panes.Item(i).name == wxT("dummy"))
2902 continue;
2903
2904 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
2905 if (tabframe->m_tab_rect.Contains(pt))
2906 return tabframe->m_tabs;
2907 }
2908
2909 return NULL;
2910 }
2911
GetTabFrameFromTabCtrl(wxWindow * tab_ctrl)2912 wxWindow* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow* tab_ctrl)
2913 {
2914 // if we've just removed the last tab from the source
2915 // tab set, the remove the tab control completely
2916 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
2917 size_t i, pane_count = all_panes.GetCount();
2918 for (i = 0; i < pane_count; ++i)
2919 {
2920 if (all_panes.Item(i).name == wxT("dummy"))
2921 continue;
2922
2923 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
2924 if (tabframe->m_tabs == tab_ctrl)
2925 {
2926 return tabframe;
2927 }
2928 }
2929
2930 return NULL;
2931 }
2932
RemoveEmptyTabFrames()2933 void wxAuiNotebook::RemoveEmptyTabFrames()
2934 {
2935 // if we've just removed the last tab from the source
2936 // tab set, the remove the tab control completely
2937 wxAuiPaneInfoArray all_panes = m_mgr.GetAllPanes();
2938 size_t i, pane_count = all_panes.GetCount();
2939 for (i = 0; i < pane_count; ++i)
2940 {
2941 if (all_panes.Item(i).name == wxT("dummy"))
2942 continue;
2943
2944 wxTabFrame* tab_frame = (wxTabFrame*)all_panes.Item(i).window;
2945 if (tab_frame->m_tabs->GetPageCount() == 0)
2946 {
2947 m_mgr.DetachPane(tab_frame);
2948
2949 // use pending delete because sometimes during
2950 // window closing, refreshs are pending
2951 if (!wxPendingDelete.Member(tab_frame->m_tabs))
2952 wxPendingDelete.Append(tab_frame->m_tabs);
2953
2954 tab_frame->m_tabs = NULL;
2955
2956 delete tab_frame;
2957 }
2958 }
2959
2960
2961 // check to see if there is still a center pane;
2962 // if there isn't, make a frame the center pane
2963 wxAuiPaneInfoArray panes = m_mgr.GetAllPanes();
2964 pane_count = panes.GetCount();
2965 wxWindow* first_good = NULL;
2966 bool center_found = false;
2967 for (i = 0; i < pane_count; ++i)
2968 {
2969 if (panes.Item(i).name == wxT("dummy"))
2970 continue;
2971 if (panes.Item(i).dock_direction == wxAUI_DOCK_CENTRE)
2972 center_found = true;
2973 if (!first_good)
2974 first_good = panes.Item(i).window;
2975 }
2976
2977 if (!center_found && first_good)
2978 {
2979 m_mgr.GetPane(first_good).Centre();
2980 }
2981
2982 if (!m_isBeingDeleted)
2983 m_mgr.Update();
2984 }
2985
OnChildFocusNotebook(wxChildFocusEvent & evt)2986 void wxAuiNotebook::OnChildFocusNotebook(wxChildFocusEvent& evt)
2987 {
2988 evt.Skip();
2989
2990 // if we're dragging a tab, don't change the current selection.
2991 // This code prevents a bug that used to happen when the hint window
2992 // was hidden. In the bug, the focus would return to the notebook
2993 // child, which would then enter this handler and call
2994 // SetSelection, which is not desired turn tab dragging.
2995
2996 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
2997 size_t i, pane_count = all_panes.GetCount();
2998 for (i = 0; i < pane_count; ++i)
2999 {
3000 wxAuiPaneInfo& pane = all_panes.Item(i);
3001 if (pane.name == wxT("dummy"))
3002 continue;
3003 wxTabFrame* tabframe = (wxTabFrame*)pane.window;
3004 if (tabframe->m_tabs->IsDragging())
3005 return;
3006 }
3007
3008
3009 // find the page containing the focused child
3010 wxWindow* win = evt.GetWindow();
3011 while ( win )
3012 {
3013 // pages have the notebook as the parent, so stop when we reach one
3014 // (and also stop in the impossible case of no parent at all)
3015 wxWindow* const parent = win->GetParent();
3016 if ( !parent || parent == this )
3017 break;
3018
3019 win = parent;
3020 }
3021
3022 // change the tab selection to this page
3023 int idx = m_tabs.GetIdxFromWindow(win);
3024 if (idx != -1 && idx != m_curPage)
3025 {
3026 SetSelection(idx);
3027 }
3028 }
3029
OnNavigationKeyNotebook(wxNavigationKeyEvent & event)3030 void wxAuiNotebook::OnNavigationKeyNotebook(wxNavigationKeyEvent& event)
3031 {
3032 if ( event.IsWindowChange() ) {
3033 // change pages
3034 // FIXME: the problem with this is that if we have a split notebook,
3035 // we selection may go all over the place.
3036 AdvanceSelection(event.GetDirection());
3037 }
3038 else {
3039 // we get this event in 3 cases
3040 //
3041 // a) one of our pages might have generated it because the user TABbed
3042 // out from it in which case we should propagate the event upwards and
3043 // our parent will take care of setting the focus to prev/next sibling
3044 //
3045 // or
3046 //
3047 // b) the parent panel wants to give the focus to us so that we
3048 // forward it to our selected page. We can't deal with this in
3049 // OnSetFocus() because we don't know which direction the focus came
3050 // from in this case and so can't choose between setting the focus to
3051 // first or last panel child
3052 //
3053 // or
3054 //
3055 // c) we ourselves (see MSWTranslateMessage) generated the event
3056 //
3057 wxWindow * const parent = GetParent();
3058
3059 // the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
3060 const bool isFromParent = event.GetEventObject() == (wxObject*) parent;
3061 const bool isFromSelf = event.GetEventObject() == (wxObject*) this;
3062
3063 if ( isFromParent || isFromSelf )
3064 {
3065 // no, it doesn't come from child, case (b) or (c): forward to a
3066 // page but only if direction is backwards (TAB) or from ourselves,
3067 if ( GetSelection() != wxNOT_FOUND &&
3068 (!event.GetDirection() || isFromSelf) )
3069 {
3070 // so that the page knows that the event comes from it's parent
3071 // and is being propagated downwards
3072 event.SetEventObject(this);
3073
3074 wxWindow *page = GetPage(GetSelection());
3075 if ( !page->GetEventHandler()->ProcessEvent(event) )
3076 {
3077 page->SetFocus();
3078 }
3079 //else: page manages focus inside it itself
3080 }
3081 else // otherwise set the focus to the notebook itself
3082 {
3083 SetFocus();
3084 }
3085 }
3086 else
3087 {
3088 // it comes from our child, case (a), pass to the parent, but only
3089 // if the direction is forwards. Otherwise set the focus to the
3090 // notebook itself. The notebook is always the 'first' control of a
3091 // page.
3092 if ( !event.GetDirection() )
3093 {
3094 SetFocus();
3095 }
3096 else if ( parent )
3097 {
3098 event.SetCurrentFocus(this);
3099 parent->GetEventHandler()->ProcessEvent(event);
3100 }
3101 }
3102 }
3103 }
3104
OnTabButton(wxAuiNotebookEvent & evt)3105 void wxAuiNotebook::OnTabButton(wxAuiNotebookEvent& evt)
3106 {
3107 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
3108
3109 int button_id = evt.GetInt();
3110
3111 if (button_id == wxAUI_BUTTON_CLOSE)
3112 {
3113 int selection = evt.GetSelection();
3114
3115 if (selection == -1)
3116 {
3117 // if the close button is to the right, use the active
3118 // page selection to determine which page to close
3119 selection = tabs->GetActivePage();
3120 }
3121
3122 if (selection != -1)
3123 {
3124 wxWindow* close_wnd = tabs->GetWindowFromIdx(selection);
3125
3126 // ask owner if it's ok to close the tab
3127 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_PAGE_CLOSE, m_windowId);
3128 e.SetSelection(m_tabs.GetIdxFromWindow(close_wnd));
3129 const int idx = m_tabs.GetIdxFromWindow(close_wnd);
3130 e.SetSelection(idx);
3131 e.SetOldSelection(evt.GetSelection());
3132 e.SetEventObject(this);
3133 GetEventHandler()->ProcessEvent(e);
3134 if (!e.IsAllowed())
3135 return;
3136
3137
3138 #if wxUSE_MDI
3139 if (wxDynamicCast(close_wnd, wxAuiMDIChildFrame))
3140 {
3141 close_wnd->Close();
3142 }
3143 else
3144 #endif
3145 {
3146 int main_idx = m_tabs.GetIdxFromWindow(close_wnd);
3147 wxCHECK_RET( main_idx != wxNOT_FOUND, wxT("no page to delete?") );
3148
3149 DeletePage(main_idx);
3150 }
3151
3152 // notify owner that the tab has been closed
3153 wxAuiNotebookEvent e2(wxEVT_AUINOTEBOOK_PAGE_CLOSED, m_windowId);
3154 e2.SetSelection(idx);
3155 e2.SetEventObject(this);
3156 GetEventHandler()->ProcessEvent(e2);
3157 }
3158 }
3159 }
3160
3161
OnTabMiddleDown(wxAuiNotebookEvent & evt)3162 void wxAuiNotebook::OnTabMiddleDown(wxAuiNotebookEvent& evt)
3163 {
3164 // patch event through to owner
3165 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
3166 wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
3167
3168 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_MIDDLE_DOWN, m_windowId);
3169 e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
3170 e.SetEventObject(this);
3171 GetEventHandler()->ProcessEvent(e);
3172 }
3173
OnTabMiddleUp(wxAuiNotebookEvent & evt)3174 void wxAuiNotebook::OnTabMiddleUp(wxAuiNotebookEvent& evt)
3175 {
3176 // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
3177 // click should act like a tab close action. However, first
3178 // give the owner an opportunity to handle the middle up event
3179 // for custom action
3180
3181 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
3182 wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
3183
3184 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_MIDDLE_UP, m_windowId);
3185 e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
3186 e.SetEventObject(this);
3187 if (GetEventHandler()->ProcessEvent(e))
3188 return;
3189 if (!e.IsAllowed())
3190 return;
3191
3192 // check if we are supposed to close on middle-up
3193 if ((m_flags & wxAUI_NB_MIDDLE_CLICK_CLOSE) == 0)
3194 return;
3195
3196 // simulate the user pressing the close button on the tab
3197 evt.SetInt(wxAUI_BUTTON_CLOSE);
3198 OnTabButton(evt);
3199 }
3200
OnTabRightDown(wxAuiNotebookEvent & evt)3201 void wxAuiNotebook::OnTabRightDown(wxAuiNotebookEvent& evt)
3202 {
3203 // patch event through to owner
3204 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
3205 wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
3206
3207 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN, m_windowId);
3208 e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
3209 e.SetEventObject(this);
3210 GetEventHandler()->ProcessEvent(e);
3211 }
3212
OnTabRightUp(wxAuiNotebookEvent & evt)3213 void wxAuiNotebook::OnTabRightUp(wxAuiNotebookEvent& evt)
3214 {
3215 // patch event through to owner
3216 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
3217 wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
3218
3219 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_RIGHT_UP, m_windowId);
3220 e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
3221 e.SetEventObject(this);
3222 GetEventHandler()->ProcessEvent(e);
3223 }
3224
3225 // Sets the normal font
SetNormalFont(const wxFont & font)3226 void wxAuiNotebook::SetNormalFont(const wxFont& font)
3227 {
3228 m_normalFont = font;
3229 GetArtProvider()->SetNormalFont(font);
3230 }
3231
3232 // Sets the selected tab font
SetSelectedFont(const wxFont & font)3233 void wxAuiNotebook::SetSelectedFont(const wxFont& font)
3234 {
3235 m_selectedFont = font;
3236 GetArtProvider()->SetSelectedFont(font);
3237 }
3238
3239 // Sets the measuring font
SetMeasuringFont(const wxFont & font)3240 void wxAuiNotebook::SetMeasuringFont(const wxFont& font)
3241 {
3242 GetArtProvider()->SetMeasuringFont(font);
3243 }
3244
3245 // Sets the tab font
SetFont(const wxFont & font)3246 bool wxAuiNotebook::SetFont(const wxFont& font)
3247 {
3248 wxControl::SetFont(font);
3249
3250 wxFont normalFont(font);
3251 wxFont selectedFont(normalFont);
3252 selectedFont.SetWeight(wxBOLD);
3253
3254 SetNormalFont(normalFont);
3255 SetSelectedFont(selectedFont);
3256 SetMeasuringFont(selectedFont);
3257
3258 return true;
3259 }
3260
3261 // Gets the tab control height
GetTabCtrlHeight() const3262 int wxAuiNotebook::GetTabCtrlHeight() const
3263 {
3264 return m_tabCtrlHeight;
3265 }
3266
3267 // Gets the height of the notebook for a given page height
GetHeightForPageHeight(int pageHeight)3268 int wxAuiNotebook::GetHeightForPageHeight(int pageHeight)
3269 {
3270 UpdateTabCtrlHeight();
3271
3272 int tabCtrlHeight = GetTabCtrlHeight();
3273 int decorHeight = 2;
3274 return tabCtrlHeight + pageHeight + decorHeight;
3275 }
3276
3277 // Shows the window menu
ShowWindowMenu()3278 bool wxAuiNotebook::ShowWindowMenu()
3279 {
3280 wxAuiTabCtrl* tabCtrl = GetActiveTabCtrl();
3281
3282 int idx = tabCtrl->GetArtProvider()->ShowDropDown(tabCtrl, tabCtrl->GetPages(), tabCtrl->GetActivePage());
3283
3284 if (idx != -1)
3285 {
3286 wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_PAGE_CHANGING, tabCtrl->GetId());
3287 e.SetSelection(idx);
3288 e.SetOldSelection(tabCtrl->GetActivePage());
3289 e.SetEventObject(tabCtrl);
3290 GetEventHandler()->ProcessEvent(e);
3291
3292 return true;
3293 }
3294 else
3295 return false;
3296 }
3297
DoThaw()3298 void wxAuiNotebook::DoThaw()
3299 {
3300 DoSizing();
3301
3302 wxBookCtrlBase::DoThaw();
3303 }
3304
SetPageSize(const wxSize & WXUNUSED (size))3305 void wxAuiNotebook::SetPageSize (const wxSize& WXUNUSED(size))
3306 {
3307 wxFAIL_MSG("Not implemented for wxAuiNotebook");
3308 }
3309
HitTest(const wxPoint & WXUNUSED (pt),long * WXUNUSED (flags)) const3310 int wxAuiNotebook::HitTest (const wxPoint& WXUNUSED(pt), long* WXUNUSED(flags)) const
3311 {
3312 wxFAIL_MSG("Not implemented for wxAuiNotebook");
3313 return wxNOT_FOUND;
3314 }
3315
GetPageImage(size_t WXUNUSED (n)) const3316 int wxAuiNotebook::GetPageImage(size_t WXUNUSED(n)) const
3317 {
3318 wxFAIL_MSG("Not implemented for wxAuiNotebook");
3319 return -1;
3320 }
3321
SetPageImage(size_t n,int imageId)3322 bool wxAuiNotebook::SetPageImage(size_t n, int imageId)
3323 {
3324 return SetPageBitmap(n, GetImageList()->GetBitmap(imageId));
3325 }
3326
ChangeSelection(size_t n)3327 int wxAuiNotebook::ChangeSelection(size_t n)
3328 {
3329 return DoModifySelection(n, false);
3330 }
3331
AddPage(wxWindow * page,const wxString & text,bool select,int imageId)3332 bool wxAuiNotebook::AddPage(wxWindow *page, const wxString &text, bool select,
3333 int imageId)
3334 {
3335 if(HasImageList())
3336 {
3337 return AddPage(page, text, select, GetImageList()->GetBitmap(imageId));
3338 }
3339 else
3340 {
3341 return AddPage(page, text, select, wxNullBitmap);
3342 }
3343 }
3344
DeleteAllPages()3345 bool wxAuiNotebook::DeleteAllPages()
3346 {
3347 size_t count = GetPageCount();
3348 for(size_t i = 0; i < count; i++)
3349 {
3350 DeletePage(0);
3351 }
3352 return true;
3353 }
3354
InsertPage(size_t index,wxWindow * page,const wxString & text,bool select,int imageId)3355 bool wxAuiNotebook::InsertPage(size_t index, wxWindow *page,
3356 const wxString &text, bool select,
3357 int imageId)
3358 {
3359 if(HasImageList())
3360 {
3361 return InsertPage(index, page, text, select,
3362 GetImageList()->GetBitmap(imageId));
3363 }
3364 else
3365 {
3366 return InsertPage(index, page, text, select, wxNullBitmap);
3367 }
3368 }
3369
DoModifySelection(size_t n,bool events)3370 int wxAuiNotebook::DoModifySelection(size_t n, bool events)
3371 {
3372 wxWindow* wnd = m_tabs.GetWindowFromIdx(n);
3373 if (!wnd)
3374 return m_curPage;
3375
3376 // don't change the page unless necessary;
3377 // however, clicking again on a tab should give it the focus.
3378 if ((int)n == m_curPage)
3379 {
3380 wxAuiTabCtrl* ctrl;
3381 int ctrl_idx;
3382 if (FindTab(wnd, &ctrl, &ctrl_idx))
3383 {
3384 if (FindFocus() != ctrl)
3385 ctrl->SetFocus();
3386 }
3387 return m_curPage;
3388 }
3389
3390 bool vetoed = false;
3391
3392 wxAuiNotebookEvent evt(wxEVT_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
3393
3394 if(events)
3395 {
3396 evt.SetSelection(n);
3397 evt.SetOldSelection(m_curPage);
3398 evt.SetEventObject(this);
3399 GetEventHandler()->ProcessEvent(evt);
3400 vetoed = !evt.IsAllowed();
3401 }
3402
3403 if (!vetoed)
3404 {
3405 int old_curpage = m_curPage;
3406 m_curPage = n;
3407
3408 // program allows the page change
3409 if(events)
3410 {
3411 evt.SetEventType(wxEVT_AUINOTEBOOK_PAGE_CHANGED);
3412 (void)GetEventHandler()->ProcessEvent(evt);
3413 }
3414
3415
3416 wxAuiTabCtrl* ctrl;
3417 int ctrl_idx;
3418 if (FindTab(wnd, &ctrl, &ctrl_idx))
3419 {
3420 m_tabs.SetActivePage(wnd);
3421
3422 ctrl->SetActivePage(ctrl_idx);
3423 DoSizing();
3424 ctrl->DoShowHide();
3425
3426 ctrl->MakeTabVisible(ctrl_idx, ctrl);
3427
3428 // set fonts
3429 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
3430 size_t i, pane_count = all_panes.GetCount();
3431 for (i = 0; i < pane_count; ++i)
3432 {
3433 wxAuiPaneInfo& pane = all_panes.Item(i);
3434 if (pane.name == wxT("dummy"))
3435 continue;
3436 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
3437 if (tabctrl != ctrl)
3438 tabctrl->SetSelectedFont(m_normalFont);
3439 else
3440 tabctrl->SetSelectedFont(m_selectedFont);
3441 tabctrl->Refresh();
3442 }
3443
3444 // Set the focus to the page if we're not currently focused on the tab.
3445 // This is Firefox-like behaviour.
3446 if (wnd->IsShownOnScreen() && FindFocus() != ctrl)
3447 wnd->SetFocus();
3448
3449 return old_curpage;
3450 }
3451 }
3452
3453 return m_curPage;
3454 }
3455
3456
3457 #endif // wxUSE_AUI
3458