]> git.saurik.com Git - wxWidgets.git/blob - src/aui/auibook.cpp
Also need to override Show
[wxWidgets.git] / src / aui / auibook.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/aui/notebook.cpp
3 // Purpose: wxaui: wx advanced user interface - notebook
4 // Author: Benjamin I. Williams
5 // Modified by:
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/settings.h"
24 #include "wx/aui/auibook.h"
25 #include "wx/aui/tabmdi.h"
26 #include "wx/dcbuffer.h"
27
28 #ifndef WX_PRECOMP
29 #endif
30
31 #include "wx/arrimpl.cpp"
32 WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray)
33 WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray)
34
35 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING)
36 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED)
37 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON)
38 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG)
39 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG)
40 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION)
41
42
43
44 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent, wxEvent)
45
46 // -- wxAuiTabContainer class implementation --
47
48
49 // wxAuiTabContainer is a class which contains information about each
50 // tab. It also can render an entire tab control to a specified DC.
51 // It's not a window class itself, because this code will be used by
52 // the wxFrameMananger, where it is disadvantageous to have separate
53 // windows for each tab control in the case of "docked tabs"
54
55 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
56 // which can be used as a tab control in the normal sense.
57
58
59 // This functions are here for this proof of concept
60 // and will be factored out later. See dockart.cpp
61 static wxColor StepColour(const wxColor& c, int percent)
62 {
63 int r = c.Red(), g = c.Green(), b = c.Blue();
64 return wxColour((unsigned char)wxMin((r*percent)/100,255),
65 (unsigned char)wxMin((g*percent)/100,255),
66 (unsigned char)wxMin((b*percent)/100,255));
67 }
68
69 // This functions are here for this proof of concept
70 // and will be factored out later. See dockart.cpp
71 static wxBitmap BitmapFromBits(const unsigned char bits[], int w, int h,
72 const wxColour& color)
73 {
74 wxImage img = wxBitmap((const char*)bits, w, h).ConvertToImage();
75 img.Replace(255,255,255,123,123,123);
76 img.Replace(0,0,0,color.Red(),color.Green(),color.Blue());
77 img.SetMaskColour(123,123,123);
78 return wxBitmap(img);
79 }
80
81 static void DrawButton(wxDC& dc,
82 const wxRect& _rect,
83 const wxBitmap& bmp,
84 const wxColour& bkcolour,
85 int button_state)
86 {
87 wxRect rect = _rect;
88
89 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
90 {
91 rect.x++;
92 rect.y++;
93 }
94
95 if (button_state == wxAUI_BUTTON_STATE_HOVER ||
96 button_state == wxAUI_BUTTON_STATE_PRESSED)
97 {
98 dc.SetBrush(wxBrush(StepColour(bkcolour, 120)));
99 dc.SetPen(wxPen(StepColour(bkcolour, 70)));
100
101 // draw the background behind the button
102 dc.DrawRectangle(rect.x, rect.y, 15, 15);
103 }
104
105 // draw the button itself
106 dc.DrawBitmap(bmp, rect.x, rect.y, true);
107 }
108
109
110
111
112 wxAuiTabContainer::wxAuiTabContainer()
113 {
114 m_normal_font = *wxNORMAL_FONT;
115 m_selected_font = *wxNORMAL_FONT;
116 m_selected_font.SetWeight(wxBOLD);
117 m_measuring_font = m_selected_font;
118
119 wxColour base_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
120
121 wxColour background_colour = StepColour(base_colour, 95);
122 wxColour normaltab_colour = base_colour;
123 wxColour selectedtab_colour = *wxWHITE;
124
125 m_bkbrush = wxBrush(background_colour);
126 m_normal_bkbrush = wxBrush(normaltab_colour);
127 m_normal_bkpen = wxPen(normaltab_colour);
128 m_selected_bkbrush = wxBrush(selectedtab_colour);
129 m_selected_bkpen = wxPen(selectedtab_colour);
130 }
131
132 wxAuiTabContainer::~wxAuiTabContainer()
133 {
134 }
135
136 void wxAuiTabContainer::SetNormalFont(const wxFont& font)
137 {
138 m_normal_font = font;
139 }
140
141 void wxAuiTabContainer::SetSelectedFont(const wxFont& font)
142 {
143 m_selected_font = font;
144 }
145
146 void wxAuiTabContainer::SetMeasuringFont(const wxFont& font)
147 {
148 m_measuring_font = font;
149 }
150
151 void wxAuiTabContainer::SetRect(const wxRect& rect)
152 {
153 m_rect = rect;
154 }
155
156 bool wxAuiTabContainer::AddPage(wxWindow* page,
157 const wxAuiNotebookPage& info)
158 {
159 wxAuiNotebookPage page_info;
160 page_info = info;
161 page_info.window = page;
162
163 m_pages.Add(page_info);
164
165 return true;
166 }
167
168 bool wxAuiTabContainer::InsertPage(wxWindow* page,
169 const wxAuiNotebookPage& info,
170 size_t idx)
171 {
172 wxAuiNotebookPage page_info;
173 page_info = info;
174 page_info.window = page;
175
176 if (idx >= m_pages.GetCount())
177 m_pages.Add(page_info);
178 else
179 m_pages.Insert(page_info, idx);
180
181 return true;
182 }
183
184 bool wxAuiTabContainer::RemovePage(wxWindow* wnd)
185 {
186 size_t i, page_count = m_pages.GetCount();
187 for (i = 0; i < page_count; ++i)
188 {
189 wxAuiNotebookPage& page = m_pages.Item(i);
190 if (page.window == wnd)
191 {
192 m_pages.RemoveAt(i);
193 return true;
194 }
195 }
196
197 return false;
198 }
199
200 bool wxAuiTabContainer::SetActivePage(wxWindow* wnd)
201 {
202 bool found = false;
203
204 size_t i, page_count = m_pages.GetCount();
205 for (i = 0; i < page_count; ++i)
206 {
207 wxAuiNotebookPage& page = m_pages.Item(i);
208 if (page.window == wnd)
209 {
210 page.active = true;
211 found = true;
212 }
213 else
214 {
215 page.active = false;
216 }
217 }
218
219 return found;
220 }
221
222 void wxAuiTabContainer::SetNoneActive()
223 {
224 size_t i, page_count = m_pages.GetCount();
225 for (i = 0; i < page_count; ++i)
226 {
227 wxAuiNotebookPage& page = m_pages.Item(i);
228 page.active = false;
229 }
230 }
231
232 bool wxAuiTabContainer::SetActivePage(size_t page)
233 {
234 if (page >= m_pages.GetCount())
235 return false;
236
237 return SetActivePage(m_pages.Item(page).window);
238 }
239
240 int wxAuiTabContainer::GetActivePage() const
241 {
242 size_t i, page_count = m_pages.GetCount();
243 for (i = 0; i < page_count; ++i)
244 {
245 wxAuiNotebookPage& page = m_pages.Item(i);
246 if (page.active)
247 return i;
248 }
249
250 return -1;
251 }
252
253 wxWindow* wxAuiTabContainer::GetWindowFromIdx(size_t idx) const
254 {
255 if (idx >= m_pages.GetCount())
256 return NULL;
257
258 return m_pages[idx].window;
259 }
260
261 int wxAuiTabContainer::GetIdxFromWindow(wxWindow* wnd) const
262 {
263 size_t i, page_count = m_pages.GetCount();
264 for (i = 0; i < page_count; ++i)
265 {
266 wxAuiNotebookPage& page = m_pages.Item(i);
267 if (page.window == wnd)
268 return i;
269 }
270 return -1;
271 }
272
273 wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx)
274 {
275 wxASSERT_MSG(idx < m_pages.GetCount(), wxT("Invalid Page index"));
276
277 return m_pages[idx];
278 }
279
280 wxAuiNotebookPageArray& wxAuiTabContainer::GetPages()
281 {
282 return m_pages;
283 }
284
285 size_t wxAuiTabContainer::GetPageCount() const
286 {
287 return m_pages.GetCount();
288 }
289
290 void wxAuiTabContainer::AddButton(int id, const wxBitmap& bmp)
291 {
292 wxAuiTabContainerButton button;
293 button.id = id;
294 button.bitmap = bmp;
295 button.cur_state = wxAUI_BUTTON_STATE_NORMAL;
296
297 m_buttons.Add(button);
298 }
299
300
301
302 // DrawTab() draws an individual tab.
303 // As it is virtual it may be overridden.
304 //
305 // dc - output dc
306 // in_rect - rectangle the tab should be confined to
307 // caption - tab's caption
308 // active - whether or not the tab is active
309 // out_rect - actual output rectangle
310 // x_extent - the advance x; where the next tab should start
311
312 void wxAuiTabContainer::DrawTab(wxDC* dc,
313 const wxRect& in_rect,
314 const wxString& caption,
315 bool active,
316 wxRect* out_rect,
317 int* x_extent)
318 {
319 wxCoord normal_textx, normal_texty;
320 wxCoord selected_textx, selected_texty;
321 wxCoord measured_textx, measured_texty;
322 wxCoord textx, texty;
323
324
325 // measure text
326 dc->SetFont(m_measuring_font);
327 dc->GetTextExtent(caption, &measured_textx, &measured_texty);
328
329 dc->SetFont(m_selected_font);
330 dc->GetTextExtent(caption, &selected_textx, &selected_texty);
331
332 dc->SetFont(m_normal_font);
333 dc->GetTextExtent(caption, &normal_textx, &normal_texty);
334
335
336 wxCoord tab_height = measured_texty + 4;
337 wxCoord tab_width = measured_textx + tab_height + 5;
338 wxCoord tab_x = in_rect.x;
339 wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
340
341
342 // select pen, brush and font for the tab to be drawn
343
344 if (active)
345 {
346 dc->SetPen(m_selected_bkpen);
347 dc->SetBrush(m_selected_bkbrush);
348 dc->SetFont(m_selected_font);
349 textx = selected_textx;
350 texty = selected_texty;
351 }
352 else
353 {
354 dc->SetPen(m_normal_bkpen);
355 dc->SetBrush(m_normal_bkbrush);
356 dc->SetFont(m_normal_font);
357 textx = normal_textx;
358 texty = normal_texty;
359 }
360
361
362 // -- draw line --
363
364 wxPoint points[7];
365 points[0].x = tab_x;
366 points[0].y = tab_y + tab_height - 1;
367 points[1].x = tab_x + tab_height - 3;
368 points[1].y = tab_y + 2;
369 points[2].x = tab_x + tab_height + 3;
370 points[2].y = tab_y;
371 points[3].x = tab_x + tab_width - 2;
372 points[3].y = tab_y;
373 points[4].x = tab_x + tab_width;
374 points[4].y = tab_y + 2;
375 points[5].x = tab_x + tab_width;
376 points[5].y = tab_y + tab_height - 1;
377 points[6] = points[0];
378
379
380 dc->DrawPolygon(6, points);
381
382 dc->SetPen(*wxGREY_PEN);
383
384 //dc->DrawLines(active ? 6 : 7, points);
385 dc->DrawLines(7, points);
386
387 // -- draw text --
388
389 dc->DrawText(caption,
390 tab_x + (tab_height/3) + (tab_width/2) - (textx/2),
391 tab_y + tab_height - texty - 2);
392
393 *out_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
394 *x_extent = tab_width - (tab_height/2) - 1;
395 }
396
397
398 // Render() renders the tab catalog to the specified DC
399 // It is a virtual function and can be overridden to
400 // provide custom drawing capabilities
401 void wxAuiTabContainer::Render(wxDC* raw_dc)
402 {
403 wxMemoryDC dc;
404 wxBitmap bmp;
405 bmp.Create(m_rect.GetWidth(), m_rect.GetHeight());
406 dc.SelectObject(bmp);
407
408 // draw background
409 dc.SetBrush(m_bkbrush);
410 dc.SetPen(*wxTRANSPARENT_PEN);
411 dc.DrawRectangle(-1, -1, m_rect.GetWidth()+2, m_rect.GetHeight()+2);
412
413 // draw base line
414 dc.SetPen(*wxGREY_PEN);
415 dc.DrawLine(0, m_rect.GetHeight()-1, m_rect.GetWidth(), m_rect.GetHeight()-1);
416
417
418 size_t i, page_count = m_pages.GetCount();
419 int offset = 0;
420
421 size_t active = 999;
422 int active_offset = 0;
423
424 int x_extent = 0;
425 wxRect rect = m_rect;
426 rect.y = 0;
427 rect.width = 1000;
428 rect.height = m_rect.height;
429
430 for (i = 0; i < page_count; ++i)
431 {
432 wxAuiNotebookPage& page = m_pages.Item(i);
433
434 rect.x = offset;
435
436 DrawTab(&dc,
437 rect,
438 page.caption,
439 page.active,
440 &page.rect,
441 &x_extent);
442
443 if (page.active)
444 {
445 active = i;
446 active_offset = offset;
447 }
448
449 offset += x_extent;
450 }
451
452 // draw the active tab again so it stands in the foreground
453 if (active < m_pages.GetCount())
454 {
455 wxAuiNotebookPage& page = m_pages.Item(active);
456
457 rect.x = active_offset;
458 DrawTab(&dc,
459 rect,
460 page.caption,
461 page.active,
462 &page.rect,
463 &x_extent);
464 }
465
466 // draw the buttons
467 offset = m_rect.x + m_rect.width;
468 size_t button_count = m_buttons.GetCount();
469 for (i = 0; i < button_count; ++i)
470 {
471 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
472
473 wxRect button_rect(offset - button.bitmap.GetWidth(), 1,
474 button.bitmap.GetWidth(), button.bitmap.GetHeight());
475
476 button.rect = button_rect;
477
478 DrawButton(dc, button.rect, button.bitmap,
479 m_bkbrush.GetColour(),
480 button.cur_state);
481
482 offset -= button.bitmap.GetWidth();
483 }
484
485
486 raw_dc->Blit(m_rect.x, m_rect.y, m_rect.GetWidth(), m_rect.GetHeight(), &dc, 0, 0);
487 }
488
489
490 // TabHitTest() tests if a tab was hit, passing the window pointer
491 // back if that condition was fulfilled. The function returns
492 // true if a tab was hit, otherwise false
493 bool wxAuiTabContainer::TabHitTest(int x, int y, wxWindow** hit) const
494 {
495 if (!m_rect.Inside(x,y))
496 return false;
497
498 size_t i, page_count = m_pages.GetCount();
499
500 for (i = 0; i < page_count; ++i)
501 {
502 wxAuiNotebookPage& page = m_pages.Item(i);
503 if (page.rect.Inside(x,y))
504 {
505 *hit = page.window;
506 return true;
507 }
508 }
509
510 return false;
511 }
512
513 // ButtonHitTest() tests if a button was hit. The function returns
514 // true if a button was hit, otherwise false
515 bool wxAuiTabContainer::ButtonHitTest(int x, int y,
516 wxAuiTabContainerButton** hit) const
517 {
518 if (!m_rect.Inside(x,y))
519 return false;
520
521 size_t i, button_count = m_buttons.GetCount();
522
523 for (i = 0; i < button_count; ++i)
524 {
525 wxAuiTabContainerButton& button = m_buttons.Item(i);
526 if (button.rect.Inside(x,y))
527 {
528 *hit = &button;
529 return true;
530 }
531 }
532
533 return false;
534 }
535
536
537
538 // the utility function ShowWnd() is the same as show,
539 // except it handles wxTabMDIChildFrame windows as well,
540 // as the Show() method on this class is "unplugged"
541 static void ShowWnd(wxWindow* wnd, bool show)
542 {
543 if (wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
544 {
545 wxTabMDIChildFrame* cf = (wxTabMDIChildFrame*)wnd;
546 cf->DoShow(show);
547 }
548 else
549 {
550 wnd->Show(show);
551 }
552 }
553
554
555 // DoShowHide() this function shows the active window, then
556 // hides all of the other windows (in that order)
557 void wxAuiTabContainer::DoShowHide()
558 {
559 wxAuiNotebookPageArray& pages = GetPages();
560 size_t i, page_count = pages.GetCount();
561
562 // show new active page first
563 for (i = 0; i < page_count; ++i)
564 {
565 wxAuiNotebookPage& page = pages.Item(i);
566 if (page.active)
567 {
568 ShowWnd(page.window, true);
569 break;
570 }
571 }
572
573 // hide all other pages
574 for (i = 0; i < page_count; ++i)
575 {
576 wxAuiNotebookPage& page = pages.Item(i);
577 ShowWnd(page.window, page.active);
578 }
579 }
580
581
582
583
584
585
586 // -- wxAuiTabCtrl class implementation --
587
588
589 const int wxAuiButtonClose = 101;
590
591 BEGIN_EVENT_TABLE(wxAuiTabCtrl, wxControl)
592 EVT_PAINT(wxAuiTabCtrl::OnPaint)
593 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground)
594 EVT_SIZE(wxAuiTabCtrl::OnSize)
595 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown)
596 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp)
597 EVT_MOTION(wxAuiTabCtrl::OnMotion)
598 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow)
599 END_EVENT_TABLE()
600
601
602 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow* parent,
603 wxWindowID id,
604 const wxPoint& pos,
605 const wxSize& size,
606 long style) : wxControl(parent, id, pos, size, style)
607 {
608 m_click_pt = wxDefaultPosition;
609 m_is_dragging = false;
610 m_hover_button = NULL;
611
612 // copied from dockart-- needs to put in a common place
613 static unsigned char close_bits[]={
614 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
615 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
616 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
617
618 AddButton(101, BitmapFromBits(close_bits, 16, 16, *wxBLACK));
619 }
620
621
622 void wxAuiTabCtrl::OnPaint(wxPaintEvent&)
623 {
624 wxPaintDC dc(this);
625
626 dc.SetFont(GetFont());
627
628 if (GetPageCount() > 0)
629 Render(&dc);
630 }
631
632 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
633 {
634 }
635
636 void wxAuiTabCtrl::OnSize(wxSizeEvent& evt)
637 {
638 wxSize s = evt.GetSize();
639 wxRect r(0, 0, s.GetWidth(), s.GetHeight());
640 SetRect(r);
641 }
642
643 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt)
644 {
645 CaptureMouse();
646 m_click_pt = wxDefaultPosition;
647 m_is_dragging = false;
648 m_click_tab = -1;
649
650 wxWindow* wnd;
651 if (TabHitTest(evt.m_x, evt.m_y, &wnd))
652 {
653 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
654 e.SetSelection(GetIdxFromWindow(wnd));
655 e.SetOldSelection(GetActivePage());
656 e.SetEventObject(this);
657 GetEventHandler()->ProcessEvent(e);
658
659 m_click_pt.x = evt.m_x;
660 m_click_pt.y = evt.m_y;
661 m_click_tab = e.GetSelection();
662 }
663
664 if (m_hover_button)
665 {
666 m_hover_button->cur_state = wxAUI_BUTTON_STATE_PRESSED;
667 Refresh();
668 Update();
669 }
670 }
671
672 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent&)
673 {
674 if (GetCapture() == this)
675 ReleaseMouse();
676
677 if (m_is_dragging)
678 {
679 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, m_windowId);
680 evt.SetSelection(m_click_tab);
681 evt.SetOldSelection(m_click_tab);
682 evt.SetEventObject(this);
683 GetEventHandler()->ProcessEvent(evt);
684 return;
685 }
686
687 if (m_hover_button)
688 {
689 m_hover_button->cur_state = wxAUI_BUTTON_STATE_HOVER;
690 Refresh();
691 Update();
692
693 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_windowId);
694 evt.SetInt(m_hover_button->id);
695 evt.SetEventObject(this);
696 GetEventHandler()->ProcessEvent(evt);
697 }
698
699 m_click_pt = wxDefaultPosition;
700 m_is_dragging = false;
701 m_click_tab = -1;
702 }
703
704 void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt)
705 {
706 wxPoint pos = evt.GetPosition();
707
708 // check if the mouse is hovering above a button
709 wxAuiTabContainerButton* button;
710 if (ButtonHitTest(pos.x, pos.y, &button))
711 {
712 if (button->cur_state != wxAUI_BUTTON_STATE_HOVER)
713 {
714 button->cur_state = wxAUI_BUTTON_STATE_HOVER;
715 Refresh();
716 Update();
717 m_hover_button = button;
718 return;
719 }
720 }
721 else
722 {
723 if (m_hover_button)
724 {
725 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
726 m_hover_button = NULL;
727 Refresh();
728 Update();
729 }
730 }
731
732
733 if (!evt.LeftIsDown() || m_click_pt == wxDefaultPosition)
734 return;
735
736 if (m_is_dragging)
737 {
738 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, m_windowId);
739 evt.SetSelection(m_click_tab);
740 evt.SetOldSelection(m_click_tab);
741 evt.SetEventObject(this);
742 GetEventHandler()->ProcessEvent(evt);
743 return;
744 }
745
746
747 int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
748 int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
749
750 if (abs(pos.x - m_click_pt.x) > drag_x_threshold ||
751 abs(pos.y - m_click_pt.y) > drag_y_threshold)
752 {
753 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, m_windowId);
754 evt.SetSelection(m_click_tab);
755 evt.SetOldSelection(m_click_tab);
756 evt.SetEventObject(this);
757 GetEventHandler()->ProcessEvent(evt);
758
759 m_is_dragging = true;
760 }
761 }
762
763 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event))
764 {
765 if (m_hover_button)
766 {
767 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
768 m_hover_button = NULL;
769 Refresh();
770 Update();
771 }
772 }
773
774
775 // wxTabFrame is an interesting case. It's important that all child pages
776 // of the multi-notebook control are all actually children of that control
777 // (and not grandchildren). wxTabFrame facilitates this. There is one
778 // instance of wxTabFrame for each tab control inside the multi-notebook.
779 // It's important to know that wxTabFrame is not a real window, but it merely
780 // used to capture the dimensions/positioning of the internal tab control and
781 // it's managed page windows
782
783 class wxTabFrame : public wxWindow
784 {
785 public:
786
787 wxTabFrame()
788 {
789 m_tabs = NULL;
790 m_rect = wxRect(0,0,200,200);
791 m_tab_ctrl_height = 20;
792 }
793
794 void SetTabCtrlHeight(int h)
795 {
796 m_tab_ctrl_height = h;
797 }
798
799 void DoSetSize(int x, int y,
800 int width, int height,
801 int WXUNUSED(sizeFlags = wxSIZE_AUTO))
802 {
803 m_rect = wxRect(x, y, width, height);
804 DoSizing();
805 }
806
807 void DoGetClientSize(int* x, int* y) const
808 {
809 *x = m_rect.width;
810 *y = m_rect.height;
811 }
812
813 bool Show( bool WXUNUSED(show = true) ) { return false; }
814
815 void DoSizing()
816 {
817 if (!m_tabs)
818 return;
819
820 int tab_height = wxMin(m_rect.height, m_tab_ctrl_height);
821 m_tab_rect = wxRect(m_rect.x, m_rect.y, m_rect.width, tab_height);
822 m_tabs->SetSize(m_rect.x, m_rect.y, m_rect.width, tab_height);
823 m_tabs->SetRect(wxRect(0, 0, m_rect.width, tab_height));
824 m_tabs->Refresh();
825
826 wxAuiNotebookPageArray& pages = m_tabs->GetPages();
827 size_t i, page_count = pages.GetCount();
828
829 for (i = 0; i < page_count; ++i)
830 {
831 wxAuiNotebookPage& page = pages.Item(i);
832 page.window->SetSize(m_rect.x, m_rect.y+tab_height, m_rect.width, m_rect.height-tab_height);
833
834 if (page.window->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
835 {
836 wxTabMDIChildFrame* wnd = (wxTabMDIChildFrame*)page.window;
837 wnd->ApplyMDIChildFrameRect();
838 }
839 }
840 }
841
842 void DoGetSize(int* x, int* y) const
843 {
844 if (x)
845 *x = m_rect.GetWidth();
846 if (y)
847 *y = m_rect.GetHeight();
848 }
849
850 void Update()
851 {
852 // does nothing
853 }
854
855 public:
856
857 wxRect m_rect;
858 wxRect m_tab_rect;
859 wxAuiTabCtrl* m_tabs;
860 int m_tab_ctrl_height;
861 };
862
863
864
865
866
867 // -- wxAuiMultiNotebook class implementation --
868
869 BEGIN_EVENT_TABLE(wxAuiMultiNotebook, wxControl)
870 //EVT_ERASE_BACKGROUND(wxAuiMultiNotebook::OnEraseBackground)
871 //EVT_SIZE(wxAuiMultiNotebook::OnSize)
872 //EVT_LEFT_DOWN(wxAuiMultiNotebook::OnLeftDown)
873 EVT_CHILD_FOCUS(wxAuiMultiNotebook::OnChildFocus)
874 EVT_COMMAND_RANGE(10000, 10100,
875 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING,
876 wxAuiMultiNotebook::OnTabClicked)
877 EVT_COMMAND_RANGE(10000, 10100,
878 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG,
879 wxAuiMultiNotebook::OnTabBeginDrag)
880 EVT_COMMAND_RANGE(10000, 10100,
881 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG,
882 wxAuiMultiNotebook::OnTabEndDrag)
883 EVT_COMMAND_RANGE(10000, 10100,
884 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION,
885 wxAuiMultiNotebook::OnTabDragMotion)
886 EVT_COMMAND_RANGE(10000, 10100,
887 wxEVT_COMMAND_AUINOTEBOOK_BUTTON,
888 wxAuiMultiNotebook::OnTabButton)
889 END_EVENT_TABLE()
890
891 wxAuiMultiNotebook::wxAuiMultiNotebook()
892 {
893 m_curpage = -1;
894 m_tab_id_counter = 10000;
895 m_dummy_wnd = NULL;
896 m_tab_ctrl_height = 20;
897 }
898
899 wxAuiMultiNotebook::wxAuiMultiNotebook(wxWindow *parent,
900 wxWindowID id,
901 const wxPoint& pos,
902 const wxSize& size,
903 long style) : wxControl(parent, id, pos, size, style)
904 {
905 InitNotebook();
906 }
907
908 bool wxAuiMultiNotebook::Create(wxWindow* parent,
909 wxWindowID id,
910 const wxPoint& pos,
911 const wxSize& size,
912 long style)
913 {
914 if (!wxControl::Create(parent, id, pos, size, style))
915 return false;
916
917 InitNotebook();
918
919 return true;
920 }
921
922 // InitNotebook() contains common initialization
923 // code called by all constructors
924 void wxAuiMultiNotebook::InitNotebook()
925 {
926 m_curpage = -1;
927 m_tab_id_counter = 10000;
928 m_dummy_wnd = NULL;
929 m_tab_ctrl_height = 20;
930
931 m_normal_font = *wxNORMAL_FONT;
932 m_selected_font = *wxNORMAL_FONT;
933 m_selected_font.SetWeight(wxBOLD);
934
935 // choose a default for the tab height
936 wxClientDC dc(this);
937 int tx, ty;
938 dc.SetFont(m_selected_font);
939 dc.GetTextExtent(wxT("ABCDEFGHhijklm"), &tx, &ty);
940 m_tab_ctrl_height = (ty*150)/100;
941
942 m_dummy_wnd = new wxWindow(this, -1, wxPoint(0,0), wxSize(0,0));
943 m_dummy_wnd->SetSize(200, 200);
944 m_dummy_wnd->Show(false);
945
946 m_mgr.SetManagedWindow(this);
947
948 m_mgr.AddPane(m_dummy_wnd,
949 wxPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
950
951 m_mgr.Update();
952 }
953
954 wxAuiMultiNotebook::~wxAuiMultiNotebook()
955 {
956 m_mgr.UnInit();
957 }
958
959 bool wxAuiMultiNotebook::AddPage(wxWindow* page,
960 const wxString& caption,
961 bool select,
962 const wxBitmap& bitmap)
963 {
964 return InsertPage(GetPageCount(), page, caption, select, bitmap);
965 }
966
967 bool wxAuiMultiNotebook::InsertPage(size_t page_idx,
968 wxWindow* page,
969 const wxString& caption,
970 bool select,
971 const wxBitmap& bitmap)
972 {
973 wxAuiNotebookPage info;
974 info.window = page;
975 info.caption = caption;
976 info.bitmap = bitmap;
977 info.active = false;
978
979 // if there are currently no tabs, the first added
980 // tab must be active
981 if (m_tabs.GetPageCount() == 0)
982 info.active = true;
983
984 m_tabs.InsertPage(page, info, page_idx);
985
986 wxAuiTabCtrl* active_tabctrl = GetActiveTabCtrl();
987 if (page_idx >= active_tabctrl->GetPageCount())
988 active_tabctrl->AddPage(page, info);
989 else
990 active_tabctrl->InsertPage(page, info, page_idx);
991
992 DoSizing();
993 active_tabctrl->DoShowHide();
994
995 if (select)
996 {
997 int idx = m_tabs.GetIdxFromWindow(page);
998 wxASSERT_MSG(idx != -1, wxT("Invalid Page index returned on wxAuiMultiNotebook::InsertPage()"));
999
1000 SetSelection(idx);
1001 }
1002
1003 return true;
1004 }
1005
1006
1007 // DeletePage() removes a tab from the multi-notebook,
1008 // and destroys the window as well
1009 bool wxAuiMultiNotebook::DeletePage(size_t page_idx)
1010 {
1011 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
1012
1013
1014 // find out which onscreen tab ctrl owns this tab
1015 wxAuiTabCtrl* ctrl;
1016 int ctrl_idx;
1017 if (!FindTab(wnd, &ctrl, &ctrl_idx))
1018 return false;
1019
1020 // find a new page and set it as active
1021 int new_idx = ctrl_idx+1;
1022 if (new_idx >= (int)ctrl->GetPageCount())
1023 new_idx = ctrl_idx-1;
1024
1025 if (new_idx >= 0 && new_idx < (int)ctrl->GetPageCount())
1026 {
1027 wxWindow* new_wnd = ctrl->GetWindowFromIdx(new_idx);
1028 int main_idx = m_tabs.GetIdxFromWindow(new_wnd);
1029 wxASSERT(main_idx != -1);
1030 SetSelection(main_idx);
1031 }
1032 else
1033 {
1034 // set the active page to the first page that
1035 // isn't the one being deleted
1036 bool found = false;
1037 size_t i, page_count = m_tabs.GetPageCount();
1038 for (i = 0; i < page_count; ++i)
1039 {
1040 wxWindow* w = m_tabs.GetWindowFromIdx(i);
1041 if (wnd != w)
1042 {
1043 found = true;
1044 SetSelection(i);
1045 break;
1046 }
1047 }
1048
1049 if (!found)
1050 m_curpage = -1;
1051 }
1052
1053
1054 // remove the tab from main catalog
1055 if (!m_tabs.RemovePage(wnd))
1056 return false;
1057
1058 // remove the tab from the onscreen tab ctrl
1059 ctrl->RemovePage(wnd);
1060
1061 // actually destroy the window now
1062 if (wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
1063 {
1064 // delete the child frame with pending delete, as is
1065 // customary with frame windows
1066 if (!wxPendingDelete.Member(wnd))
1067 wxPendingDelete.Append(wnd);
1068 }
1069 else
1070 {
1071 wnd->Destroy();
1072 }
1073
1074 RemoveEmptyTabFrames();
1075
1076 return true;
1077 }
1078
1079
1080
1081 // RemovePage() removes a tab from the multi-notebook,
1082 // but does not destroy the window
1083 bool wxAuiMultiNotebook::RemovePage(size_t page_idx)
1084 {
1085 // remove the tab from our own catalog
1086 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
1087 if (!m_tabs.RemovePage(wnd))
1088 return false;
1089
1090 // remove the tab from the onscreen tab ctrl
1091 wxAuiTabCtrl* ctrl;
1092 int ctrl_idx;
1093 if (FindTab(wnd, &ctrl, &ctrl_idx))
1094 {
1095 ctrl->RemovePage(wnd);
1096 return true;
1097 }
1098
1099 return false;
1100 }
1101
1102 // SetPageText() changes the tab caption of the specified page
1103 bool wxAuiMultiNotebook::SetPageText(size_t page_idx, const wxString& text)
1104 {
1105 if (page_idx >= m_tabs.GetPageCount())
1106 return false;
1107
1108 // update our own tab catalog
1109 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
1110 page_info.caption = text;
1111
1112 // update what's on screen
1113 wxAuiTabCtrl* ctrl;
1114 int ctrl_idx;
1115 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
1116 {
1117 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
1118 info.caption = text;
1119 ctrl->Refresh();
1120 }
1121
1122
1123 return true;
1124 }
1125
1126 // GetSelection() returns the index of the currently active page
1127 int wxAuiMultiNotebook::GetSelection() const
1128 {
1129 return m_curpage;
1130 }
1131
1132 // SetSelection() sets the currently active page
1133 size_t wxAuiMultiNotebook::SetSelection(size_t new_page)
1134 {
1135 wxWindow* wnd = m_tabs.GetWindowFromIdx(new_page);
1136 if (!wnd)
1137 return m_curpage;
1138
1139 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1140 evt.SetSelection(new_page);
1141 evt.SetOldSelection(m_curpage);
1142 evt.SetEventObject(this);
1143 if (!GetEventHandler()->ProcessEvent(evt) || evt.IsAllowed())
1144 {
1145 // program allows the page change
1146 evt.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED);
1147 (void)GetEventHandler()->ProcessEvent(evt);
1148
1149
1150
1151 wxAuiTabCtrl* ctrl;
1152 int ctrl_idx;
1153 if (FindTab(wnd, &ctrl, &ctrl_idx))
1154 {
1155 m_tabs.SetActivePage(wnd);
1156
1157 ctrl->SetActivePage(ctrl_idx);
1158 DoSizing();
1159 ctrl->DoShowHide();
1160
1161 int old_curpage = m_curpage;
1162 m_curpage = new_page;
1163
1164
1165 // set fonts
1166 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1167 size_t i, pane_count = all_panes.GetCount();
1168 for (i = 0; i < pane_count; ++i)
1169 {
1170 wxPaneInfo& pane = all_panes.Item(i);
1171 if (pane.name == wxT("dummy"))
1172 continue;
1173 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
1174 if (tabctrl != ctrl)
1175 tabctrl->SetSelectedFont(m_normal_font);
1176 else
1177 tabctrl->SetSelectedFont(m_selected_font);
1178 tabctrl->Refresh();
1179 }
1180
1181 wnd->SetFocus();
1182
1183 return old_curpage;
1184 }
1185 }
1186
1187 return m_curpage;
1188 }
1189
1190 // GetPageCount() returns the total number of
1191 // pages managed by the multi-notebook
1192 size_t wxAuiMultiNotebook::GetPageCount() const
1193 {
1194 return m_tabs.GetPageCount();
1195 }
1196
1197 // GetPage() returns the wxWindow pointer of the
1198 // specified page
1199 wxWindow* wxAuiMultiNotebook::GetPage(size_t page_idx) const
1200 {
1201 wxASSERT(page_idx < m_tabs.GetPageCount());
1202
1203 return m_tabs.GetWindowFromIdx(page_idx);
1204 }
1205
1206 // DoSizing() performs all sizing operations in each tab control
1207 void wxAuiMultiNotebook::DoSizing()
1208 {
1209 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1210 size_t i, pane_count = all_panes.GetCount();
1211 for (i = 0; i < pane_count; ++i)
1212 {
1213 if (all_panes.Item(i).name == wxT("dummy"))
1214 continue;
1215
1216 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1217 tabframe->DoSizing();
1218 }
1219 }
1220
1221 // GetActiveTabCtrl() returns the active tab control. It is
1222 // called to determine which control gets new windows being added
1223 wxAuiTabCtrl* wxAuiMultiNotebook::GetActiveTabCtrl()
1224 {
1225 if (m_curpage >= 0 && m_curpage < (int)m_tabs.GetPageCount())
1226 {
1227 wxAuiTabCtrl* ctrl;
1228 int idx;
1229
1230 // find the tab ctrl with the current page
1231 if (FindTab(m_tabs.GetPage(m_curpage).window,
1232 &ctrl, &idx))
1233 {
1234 return ctrl;
1235 }
1236 }
1237
1238 // no current page, just find the first tab ctrl
1239 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1240 size_t i, pane_count = all_panes.GetCount();
1241 for (i = 0; i < pane_count; ++i)
1242 {
1243 if (all_panes.Item(i).name == wxT("dummy"))
1244 continue;
1245
1246 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1247 return tabframe->m_tabs;
1248 }
1249
1250 // If there is no tabframe at all, create one
1251 wxTabFrame* tabframe = new wxTabFrame;
1252 tabframe->SetTabCtrlHeight(m_tab_ctrl_height);
1253 tabframe->m_tabs = new wxAuiTabCtrl(this,
1254 m_tab_id_counter++,
1255 wxDefaultPosition,
1256 wxDefaultSize,
1257 wxNO_BORDER);
1258 m_mgr.AddPane(tabframe,
1259 wxPaneInfo().Center().CaptionVisible(false));
1260
1261 m_mgr.Update();
1262
1263 return tabframe->m_tabs;
1264 }
1265
1266 // FindTab() finds the tab control that currently contains the window as well
1267 // as the index of the window in the tab control. It returns true if the
1268 // window was found, otherwise false.
1269 bool wxAuiMultiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx)
1270 {
1271 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1272 size_t i, pane_count = all_panes.GetCount();
1273 for (i = 0; i < pane_count; ++i)
1274 {
1275 if (all_panes.Item(i).name == wxT("dummy"))
1276 continue;
1277
1278 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1279
1280 int page_idx = tabframe->m_tabs->GetIdxFromWindow(page);
1281 if (page_idx != -1)
1282 {
1283 *ctrl = tabframe->m_tabs;
1284 *idx = page_idx;
1285 return true;
1286 }
1287 }
1288
1289 return false;
1290 }
1291
1292
1293 void wxAuiMultiNotebook::OnEraseBackground(wxEraseEvent&)
1294 {
1295 }
1296
1297 void wxAuiMultiNotebook::OnSize(wxSizeEvent&)
1298 {
1299 }
1300
1301 void wxAuiMultiNotebook::OnTabClicked(wxCommandEvent& command_evt)
1302 {
1303 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1304
1305 wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject();
1306 wxASSERT(ctrl != NULL);
1307
1308 wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection());
1309 wxASSERT(wnd != NULL);
1310
1311 int idx = m_tabs.GetIdxFromWindow(wnd);
1312 wxASSERT(idx != -1);
1313
1314 SetSelection(idx);
1315 }
1316
1317 void wxAuiMultiNotebook::OnTabBeginDrag(wxCommandEvent&)
1318 {
1319 }
1320
1321 void wxAuiMultiNotebook::OnTabDragMotion(wxCommandEvent& evt)
1322 {
1323 wxPoint screen_pt = ::wxGetMousePosition();
1324 wxPoint client_pt = ScreenToClient(screen_pt);
1325 wxPoint zero(0,0);
1326
1327 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1328
1329 wxAuiTabCtrl* tab_ctrl = GetTabCtrlFromPoint(client_pt);
1330 if (tab_ctrl == src_tabs)
1331 {
1332 // inner-tabctrl dragging is not yet implemented
1333 m_mgr.HideHint();
1334 return;
1335 }
1336
1337 if (tab_ctrl)
1338 {
1339 wxRect hint_rect = tab_ctrl->GetRect();
1340 ClientToScreen(&hint_rect.x, &hint_rect.y);
1341 m_mgr.ShowHint(hint_rect);
1342 }
1343 else
1344 {
1345 m_mgr.DrawHintRect(m_dummy_wnd, client_pt, zero);
1346 }
1347 }
1348
1349
1350
1351 void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
1352 {
1353 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1354
1355 m_mgr.HideHint();
1356
1357
1358 // get the mouse position, which will be used to determine the drop point
1359 wxPoint mouse_screen_pt = ::wxGetMousePosition();
1360 wxPoint mouse_client_pt = ScreenToClient(mouse_screen_pt);
1361
1362
1363 // the src tab control is the control that fired this event
1364 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1365 wxAuiTabCtrl* dest_tabs = NULL;
1366
1367
1368 // If the pointer is in an existing tab frame, do a tab insert
1369 wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt);
1370 wxTabFrame* tab_frame = (wxTabFrame*)GetTabFrameFromTabCtrl(hit_wnd);
1371 if (tab_frame)
1372 {
1373 dest_tabs = tab_frame->m_tabs;
1374
1375 if (dest_tabs == src_tabs)
1376 return;
1377 }
1378 else
1379 {
1380 // If there is no tabframe at all, create one
1381 wxTabFrame* new_tabs = new wxTabFrame;
1382 new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
1383 new_tabs->m_tabs = new wxAuiTabCtrl(this,
1384 m_tab_id_counter++,
1385 wxDefaultPosition,
1386 wxDefaultSize,
1387 wxNO_BORDER);
1388 m_mgr.AddPane(new_tabs,
1389 wxPaneInfo().Bottom().CaptionVisible(false),
1390 mouse_client_pt);
1391 m_mgr.Update();
1392 dest_tabs = new_tabs->m_tabs;
1393 }
1394
1395
1396
1397 // remove the page from the source tabs
1398 wxAuiNotebookPage page_info = src_tabs->GetPage(evt.GetSelection());
1399 page_info.active = false;
1400 src_tabs->RemovePage(page_info.window);
1401 if (src_tabs->GetPageCount() > 0)
1402 {
1403 src_tabs->SetActivePage((size_t)0);
1404 src_tabs->DoShowHide();
1405 src_tabs->Refresh();
1406 }
1407
1408
1409
1410 // add the page to the destination tabs
1411 dest_tabs->AddPage(page_info.window, page_info);
1412
1413 if (src_tabs->GetPageCount() == 0)
1414 {
1415 RemoveEmptyTabFrames();
1416 }
1417
1418 DoSizing();
1419 dest_tabs->DoShowHide();
1420 dest_tabs->Refresh();
1421
1422 SetSelection(m_tabs.GetIdxFromWindow(page_info.window));
1423 }
1424
1425 wxAuiTabCtrl* wxAuiMultiNotebook::GetTabCtrlFromPoint(const wxPoint& pt)
1426 {
1427 // if we've just removed the last tab from the source
1428 // tab set, the remove the tab control completely
1429 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1430 size_t i, pane_count = all_panes.GetCount();
1431 for (i = 0; i < pane_count; ++i)
1432 {
1433 if (all_panes.Item(i).name == wxT("dummy"))
1434 continue;
1435
1436 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1437 if (tabframe->m_tab_rect.Inside(pt))
1438 return tabframe->m_tabs;
1439 }
1440
1441 return NULL;
1442 }
1443
1444 wxWindow* wxAuiMultiNotebook::GetTabFrameFromTabCtrl(wxWindow* tab_ctrl)
1445 {
1446 // if we've just removed the last tab from the source
1447 // tab set, the remove the tab control completely
1448 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1449 size_t i, pane_count = all_panes.GetCount();
1450 for (i = 0; i < pane_count; ++i)
1451 {
1452 if (all_panes.Item(i).name == wxT("dummy"))
1453 continue;
1454
1455 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1456 if (tabframe->m_tabs == tab_ctrl)
1457 {
1458 return tabframe;
1459 }
1460 }
1461
1462 return NULL;
1463 }
1464
1465 void wxAuiMultiNotebook::RemoveEmptyTabFrames()
1466 {
1467 bool must_update = false;
1468
1469 // if we've just removed the last tab from the source
1470 // tab set, the remove the tab control completely
1471 wxPaneInfoArray all_panes = m_mgr.GetAllPanes();
1472 size_t i, pane_count = all_panes.GetCount();
1473 for (i = 0; i < pane_count; ++i)
1474 {
1475 if (all_panes.Item(i).name == wxT("dummy"))
1476 continue;
1477
1478 wxTabFrame* tab_frame = (wxTabFrame*)all_panes.Item(i).window;
1479 if (tab_frame->m_tabs->GetPageCount() == 0)
1480 {
1481 m_mgr.DetachPane(tab_frame);
1482
1483 // use pending delete because sometimes during
1484 // window closing, refreshs are pending
1485 if (!wxPendingDelete.Member(tab_frame->m_tabs))
1486 wxPendingDelete.Append(tab_frame->m_tabs);
1487 //tab_frame->m_tabs->Destroy();
1488
1489 delete tab_frame;
1490 must_update = true;
1491 }
1492 }
1493
1494
1495 // check to see if there is still a center pane;
1496 // if there isn't, make a frame the center pane
1497 wxPaneInfoArray panes = m_mgr.GetAllPanes();
1498 pane_count = panes.GetCount();
1499 wxWindow* first_good = NULL;
1500 bool center_found = false;
1501 for (i = 0; i < pane_count; ++i)
1502 {
1503 if (panes.Item(i).name == wxT("dummy"))
1504 continue;
1505 if (panes.Item(i).dock_direction == wxAUI_DOCK_CENTRE)
1506 center_found = true;
1507 if (!first_good)
1508 first_good = panes.Item(i).window;
1509 }
1510
1511 if (!center_found && first_good)
1512 {
1513 m_mgr.GetPane(first_good).Centre();
1514 must_update = true;
1515 }
1516
1517 m_mgr.Update();
1518 }
1519
1520 void wxAuiMultiNotebook::OnChildFocus(wxChildFocusEvent& evt)
1521 {
1522 int idx = m_tabs.GetIdxFromWindow(evt.GetWindow());
1523 if (idx != -1 && idx != m_curpage)
1524 {
1525 SetSelection(idx);
1526 }
1527 }
1528
1529
1530 void wxAuiMultiNotebook::OnTabButton(wxCommandEvent& command_evt)
1531 {
1532 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1533 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1534
1535 int button_id = evt.GetInt();
1536
1537 if (button_id == wxAuiButtonClose)
1538 {
1539 int selection = tabs->GetActivePage();
1540
1541 if (selection != -1)
1542 {
1543 wxWindow* close_wnd = tabs->GetWindowFromIdx(selection);
1544
1545 if (close_wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
1546 {
1547 close_wnd->Close();
1548 }
1549 else
1550 {
1551 int main_idx = m_tabs.GetIdxFromWindow(close_wnd);
1552 DeletePage(main_idx);
1553 }
1554 }
1555 }
1556 }
1557
1558
1559
1560
1561 #endif // wxUSE_AUI