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