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