]> git.saurik.com Git - wxWidgets.git/blob - src/aui/auibook.cpp
cef21576f02ebb5009dee7b59f745bd921e977c6
[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 }
792
793 void DoSetSize(int x, int y,
794 int width, int height,
795 int WXUNUSED(sizeFlags = wxSIZE_AUTO))
796 {
797 m_rect = wxRect(x, y, width, height);
798 DoSizing();
799 }
800
801 void DoGetClientSize(int* x, int* y) const
802 {
803 *x = m_rect.width;
804 *y = m_rect.height;
805 }
806
807 void DoSizing()
808 {
809 if (!m_tabs)
810 return;
811
812 int tab_height = wxMin(m_rect.height, 19);
813 m_tab_rect = wxRect(m_rect.x, m_rect.y, m_rect.width, tab_height);
814 m_tabs->SetSize(m_rect.x, m_rect.y, m_rect.width, tab_height);
815 m_tabs->SetRect(wxRect(0, 0, m_rect.width, tab_height));
816 m_tabs->Refresh();
817
818 wxAuiNotebookPageArray& pages = m_tabs->GetPages();
819 size_t i, page_count = pages.GetCount();
820
821 for (i = 0; i < page_count; ++i)
822 {
823 wxAuiNotebookPage& page = pages.Item(i);
824 page.window->SetSize(m_rect.x, m_rect.y+tab_height, m_rect.width, m_rect.height-tab_height);
825
826 if (page.window->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
827 {
828 wxTabMDIChildFrame* wnd = (wxTabMDIChildFrame*)page.window;
829 wnd->ApplyMDIChildFrameRect();
830 }
831 }
832 }
833
834 void DoGetSize(int* x, int* y) const
835 {
836 if (x)
837 *x = m_rect.GetWidth();
838 if (y)
839 *y = m_rect.GetHeight();
840 }
841
842 void Update()
843 {
844 // does nothing
845 }
846
847 public:
848
849 wxRect m_rect;
850 wxRect m_tab_rect;
851 wxAuiTabCtrl* m_tabs;
852 };
853
854
855
856
857
858 // -- wxAuiMultiNotebook class implementation --
859
860 BEGIN_EVENT_TABLE(wxAuiMultiNotebook, wxControl)
861 //EVT_ERASE_BACKGROUND(wxAuiMultiNotebook::OnEraseBackground)
862 //EVT_SIZE(wxAuiMultiNotebook::OnSize)
863 //EVT_LEFT_DOWN(wxAuiMultiNotebook::OnLeftDown)
864 EVT_CHILD_FOCUS(wxAuiMultiNotebook::OnChildFocus)
865 EVT_COMMAND_RANGE(10000, 10100,
866 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING,
867 wxAuiMultiNotebook::OnTabClicked)
868 EVT_COMMAND_RANGE(10000, 10100,
869 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG,
870 wxAuiMultiNotebook::OnTabBeginDrag)
871 EVT_COMMAND_RANGE(10000, 10100,
872 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG,
873 wxAuiMultiNotebook::OnTabEndDrag)
874 EVT_COMMAND_RANGE(10000, 10100,
875 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION,
876 wxAuiMultiNotebook::OnTabDragMotion)
877 EVT_COMMAND_RANGE(10000, 10100,
878 wxEVT_COMMAND_AUINOTEBOOK_BUTTON,
879 wxAuiMultiNotebook::OnTabButton)
880 END_EVENT_TABLE()
881
882 wxAuiMultiNotebook::wxAuiMultiNotebook()
883 {
884 m_curpage = -1;
885 m_tab_id_counter = 10000;
886 m_dummy_wnd = NULL;
887 }
888
889 wxAuiMultiNotebook::wxAuiMultiNotebook(wxWindow *parent,
890 wxWindowID id,
891 const wxPoint& pos,
892 const wxSize& size,
893 long style) : wxControl(parent, id, pos, size, style)
894 {
895 InitNotebook();
896 }
897
898 bool wxAuiMultiNotebook::Create(wxWindow* parent,
899 wxWindowID id,
900 const wxPoint& pos,
901 const wxSize& size,
902 long style)
903 {
904 if (!wxControl::Create(parent, id, pos, size, style))
905 return false;
906
907 InitNotebook();
908
909 return true;
910 }
911
912 // InitNotebook() contains common initialization
913 // code called by all constructors
914 void wxAuiMultiNotebook::InitNotebook()
915 {
916 m_normal_font = *wxNORMAL_FONT;
917 m_selected_font = *wxNORMAL_FONT;
918 m_selected_font.SetWeight(wxBOLD);
919
920
921 m_tab_id_counter = 10000;
922
923 m_dummy_wnd = new wxWindow(this, -1, wxPoint(0,0), wxSize(0,0));
924 m_dummy_wnd->SetSize(200, 200);
925 m_dummy_wnd->Show(false);
926
927 m_mgr.SetManagedWindow(this);
928
929 m_mgr.AddPane(m_dummy_wnd,
930 wxPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
931
932 m_mgr.Update();
933 }
934
935 wxAuiMultiNotebook::~wxAuiMultiNotebook()
936 {
937 m_mgr.UnInit();
938 }
939
940 bool wxAuiMultiNotebook::AddPage(wxWindow* page,
941 const wxString& caption,
942 bool select,
943 const wxBitmap& bitmap)
944 {
945 return InsertPage(GetPageCount(), page, caption, select, bitmap);
946 }
947
948 bool wxAuiMultiNotebook::InsertPage(size_t page_idx,
949 wxWindow* page,
950 const wxString& caption,
951 bool select,
952 const wxBitmap& bitmap)
953 {
954 wxAuiNotebookPage info;
955 info.window = page;
956 info.caption = caption;
957 info.bitmap = bitmap;
958 info.active = false;
959
960 // if there are currently no tabs, the first added
961 // tab must be active
962 if (m_tabs.GetPageCount() == 0)
963 info.active = true;
964
965 m_tabs.InsertPage(page, info, page_idx);
966
967 wxAuiTabCtrl* active_tabctrl = GetActiveTabCtrl();
968 if (page_idx >= active_tabctrl->GetPageCount())
969 active_tabctrl->AddPage(page, info);
970 else
971 active_tabctrl->InsertPage(page, info, page_idx);
972
973 DoSizing();
974 active_tabctrl->DoShowHide();
975
976 if (select)
977 {
978 int idx = m_tabs.GetIdxFromWindow(page);
979 wxASSERT_MSG(idx != -1, wxT("Invalid Page index returned on wxAuiMultiNotebook::InsertPage()"));
980
981 SetSelection(idx);
982 }
983
984 return true;
985 }
986
987
988 // DeletePage() removes a tab from the multi-notebook,
989 // and destroys the window as well
990 bool wxAuiMultiNotebook::DeletePage(size_t page_idx)
991 {
992 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
993
994
995 // find out which onscreen tab ctrl owns this tab
996 wxAuiTabCtrl* ctrl;
997 int ctrl_idx;
998 if (!FindTab(wnd, &ctrl, &ctrl_idx))
999 return false;
1000
1001 // find a new page and set it as active
1002 int new_idx = ctrl_idx+1;
1003 if (new_idx >= (int)ctrl->GetPageCount())
1004 new_idx = ctrl_idx-1;
1005
1006 if (new_idx >= 0 && new_idx < (int)ctrl->GetPageCount())
1007 {
1008 wxWindow* new_wnd = ctrl->GetWindowFromIdx(new_idx);
1009 int main_idx = m_tabs.GetIdxFromWindow(new_wnd);
1010 wxASSERT(main_idx != -1);
1011 SetSelection(main_idx);
1012 }
1013 else
1014 {
1015 // set the active page to the first page that
1016 // isn't the one being deleted
1017 bool found = false;
1018 size_t i, page_count = m_tabs.GetPageCount();
1019 for (i = 0; i < page_count; ++i)
1020 {
1021 wxWindow* w = m_tabs.GetWindowFromIdx(i);
1022 if (wnd != w)
1023 {
1024 found = true;
1025 SetSelection(i);
1026 break;
1027 }
1028 }
1029
1030 if (!found)
1031 m_curpage = -1;
1032 }
1033
1034
1035 // remove the tab from main catalog
1036 if (!m_tabs.RemovePage(wnd))
1037 return false;
1038
1039 // remove the tab from the onscreen tab ctrl
1040 ctrl->RemovePage(wnd);
1041
1042 // actually destroy the window now
1043 if (wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
1044 {
1045 // delete the child frame with pending delete, as is
1046 // customary with frame windows
1047 if (!wxPendingDelete.Member(wnd))
1048 wxPendingDelete.Append(wnd);
1049 }
1050 else
1051 {
1052 wnd->Destroy();
1053 }
1054
1055 RemoveEmptyTabFrames();
1056
1057 return true;
1058 }
1059
1060
1061
1062 // RemovePage() removes a tab from the multi-notebook,
1063 // but does not destroy the window
1064 bool wxAuiMultiNotebook::RemovePage(size_t page_idx)
1065 {
1066 // remove the tab from our own catalog
1067 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
1068 if (!m_tabs.RemovePage(wnd))
1069 return false;
1070
1071 // remove the tab from the onscreen tab ctrl
1072 wxAuiTabCtrl* ctrl;
1073 int ctrl_idx;
1074 if (FindTab(wnd, &ctrl, &ctrl_idx))
1075 {
1076 ctrl->RemovePage(wnd);
1077 return true;
1078 }
1079
1080 return false;
1081 }
1082
1083 // SetPageText() changes the tab caption of the specified page
1084 bool wxAuiMultiNotebook::SetPageText(size_t page_idx, const wxString& text)
1085 {
1086 if (page_idx >= m_tabs.GetPageCount())
1087 return false;
1088
1089 // update our own tab catalog
1090 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
1091 page_info.caption = text;
1092
1093 // update what's on screen
1094 wxAuiTabCtrl* ctrl;
1095 int ctrl_idx;
1096 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
1097 {
1098 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
1099 info.caption = text;
1100 ctrl->Refresh();
1101 }
1102
1103
1104 return true;
1105 }
1106
1107 // GetSelection() returns the index of the currently active page
1108 int wxAuiMultiNotebook::GetSelection() const
1109 {
1110 return m_curpage;
1111 }
1112
1113 // SetSelection() sets the currently active page
1114 size_t wxAuiMultiNotebook::SetSelection(size_t new_page)
1115 {
1116 wxWindow* wnd = m_tabs.GetWindowFromIdx(new_page);
1117 if (!wnd)
1118 return m_curpage;
1119
1120 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1121 evt.SetSelection(new_page);
1122 evt.SetOldSelection(m_curpage);
1123 evt.SetEventObject(this);
1124 if (!GetEventHandler()->ProcessEvent(evt) || evt.IsAllowed())
1125 {
1126 // program allows the page change
1127 evt.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED);
1128 (void)GetEventHandler()->ProcessEvent(evt);
1129
1130
1131
1132 wxAuiTabCtrl* ctrl;
1133 int ctrl_idx;
1134 if (FindTab(wnd, &ctrl, &ctrl_idx))
1135 {
1136 m_tabs.SetActivePage(wnd);
1137
1138 ctrl->SetActivePage(ctrl_idx);
1139 DoSizing();
1140 ctrl->DoShowHide();
1141
1142 int old_curpage = m_curpage;
1143 m_curpage = new_page;
1144
1145
1146 // set fonts
1147 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1148 size_t i, pane_count = all_panes.GetCount();
1149 for (i = 0; i < pane_count; ++i)
1150 {
1151 wxPaneInfo& pane = all_panes.Item(i);
1152 if (pane.name == wxT("dummy"))
1153 continue;
1154 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
1155 if (tabctrl != ctrl)
1156 tabctrl->SetSelectedFont(m_normal_font);
1157 else
1158 tabctrl->SetSelectedFont(m_selected_font);
1159 tabctrl->Refresh();
1160 }
1161
1162 wnd->SetFocus();
1163
1164 return old_curpage;
1165 }
1166 }
1167
1168 return m_curpage;
1169 }
1170
1171 // GetPageCount() returns the total number of
1172 // pages managed by the multi-notebook
1173 size_t wxAuiMultiNotebook::GetPageCount() const
1174 {
1175 return m_tabs.GetPageCount();
1176 }
1177
1178 // GetPage() returns the wxWindow pointer of the
1179 // specified page
1180 wxWindow* wxAuiMultiNotebook::GetPage(size_t page_idx) const
1181 {
1182 wxASSERT(page_idx < m_tabs.GetPageCount());
1183
1184 return m_tabs.GetWindowFromIdx(page_idx);
1185 }
1186
1187 // DoSizing() performs all sizing operations in each tab control
1188 void wxAuiMultiNotebook::DoSizing()
1189 {
1190 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1191 size_t i, pane_count = all_panes.GetCount();
1192 for (i = 0; i < pane_count; ++i)
1193 {
1194 if (all_panes.Item(i).name == wxT("dummy"))
1195 continue;
1196
1197 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1198 tabframe->DoSizing();
1199 }
1200 }
1201
1202 // GetActiveTabCtrl() returns the active tab control. It is
1203 // called to determine which control gets new windows being added
1204 wxAuiTabCtrl* wxAuiMultiNotebook::GetActiveTabCtrl()
1205 {
1206 if (m_curpage >= 0 && m_curpage < (int)m_tabs.GetPageCount())
1207 {
1208 wxAuiTabCtrl* ctrl;
1209 int idx;
1210
1211 // find the tab ctrl with the current page
1212 if (FindTab(m_tabs.GetPage(m_curpage).window,
1213 &ctrl, &idx))
1214 {
1215 return ctrl;
1216 }
1217 }
1218
1219 // no current page, just find the first tab ctrl
1220 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1221 size_t i, pane_count = all_panes.GetCount();
1222 for (i = 0; i < pane_count; ++i)
1223 {
1224 if (all_panes.Item(i).name == wxT("dummy"))
1225 continue;
1226
1227 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1228 return tabframe->m_tabs;
1229 }
1230
1231 // If there is no tabframe at all, create one
1232 wxTabFrame* tabframe = new wxTabFrame;
1233 tabframe->m_tabs = new wxAuiTabCtrl(this,
1234 m_tab_id_counter++,
1235 wxDefaultPosition,
1236 wxDefaultSize,
1237 wxNO_BORDER);
1238 m_mgr.AddPane(tabframe,
1239 wxPaneInfo().Center().CaptionVisible(false));
1240
1241 m_mgr.Update();
1242
1243 return tabframe->m_tabs;
1244 }
1245
1246 // FindTab() finds the tab control that currently contains the window as well
1247 // as the index of the window in the tab control. It returns true if the
1248 // window was found, otherwise false.
1249 bool wxAuiMultiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx)
1250 {
1251 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1252 size_t i, pane_count = all_panes.GetCount();
1253 for (i = 0; i < pane_count; ++i)
1254 {
1255 if (all_panes.Item(i).name == wxT("dummy"))
1256 continue;
1257
1258 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1259
1260 int page_idx = tabframe->m_tabs->GetIdxFromWindow(page);
1261 if (page_idx != -1)
1262 {
1263 *ctrl = tabframe->m_tabs;
1264 *idx = page_idx;
1265 return true;
1266 }
1267 }
1268
1269 return false;
1270 }
1271
1272
1273 void wxAuiMultiNotebook::OnEraseBackground(wxEraseEvent&)
1274 {
1275 }
1276
1277 void wxAuiMultiNotebook::OnSize(wxSizeEvent&)
1278 {
1279 }
1280
1281 void wxAuiMultiNotebook::OnTabClicked(wxCommandEvent& command_evt)
1282 {
1283 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1284
1285 wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject();
1286 wxASSERT(ctrl != NULL);
1287
1288 wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection());
1289 wxASSERT(wnd != NULL);
1290
1291 int idx = m_tabs.GetIdxFromWindow(wnd);
1292 wxASSERT(idx != -1);
1293
1294 SetSelection(idx);
1295 }
1296
1297 void wxAuiMultiNotebook::OnTabBeginDrag(wxCommandEvent&)
1298 {
1299 }
1300
1301 void wxAuiMultiNotebook::OnTabDragMotion(wxCommandEvent& evt)
1302 {
1303 wxPoint screen_pt = ::wxGetMousePosition();
1304 wxPoint client_pt = ScreenToClient(screen_pt);
1305 wxPoint zero(0,0);
1306
1307 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1308
1309 wxAuiTabCtrl* tab_ctrl = GetTabCtrlFromPoint(client_pt);
1310 if (tab_ctrl == src_tabs)
1311 {
1312 // inner-tabctrl dragging is not yet implemented
1313 m_mgr.HideHint();
1314 return;
1315 }
1316
1317 if (tab_ctrl)
1318 {
1319 wxRect hint_rect = tab_ctrl->GetRect();
1320 ClientToScreen(&hint_rect.x, &hint_rect.y);
1321 m_mgr.ShowHint(hint_rect);
1322 }
1323 else
1324 {
1325 m_mgr.DrawHintRect(m_dummy_wnd, client_pt, zero);
1326 }
1327 }
1328
1329
1330
1331 void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
1332 {
1333 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1334
1335 m_mgr.HideHint();
1336
1337
1338 // get the mouse position, which will be used to determine the drop point
1339 wxPoint mouse_screen_pt = ::wxGetMousePosition();
1340 wxPoint mouse_client_pt = ScreenToClient(mouse_screen_pt);
1341
1342
1343 // the src tab control is the control that fired this event
1344 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1345 wxAuiTabCtrl* dest_tabs = NULL;
1346
1347
1348 // If the pointer is in an existing tab frame, do a tab insert
1349 wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt);
1350 wxTabFrame* tab_frame = (wxTabFrame*)GetTabFrameFromTabCtrl(hit_wnd);
1351 if (tab_frame)
1352 {
1353 dest_tabs = tab_frame->m_tabs;
1354
1355 if (dest_tabs == src_tabs)
1356 return;
1357 }
1358 else
1359 {
1360 // If there is no tabframe at all, create one
1361 wxTabFrame* new_tabs = new wxTabFrame;
1362 new_tabs->m_tabs = new wxAuiTabCtrl(this,
1363 m_tab_id_counter++,
1364 wxDefaultPosition,
1365 wxDefaultSize,
1366 wxNO_BORDER);
1367 m_mgr.AddPane(new_tabs,
1368 wxPaneInfo().Bottom().CaptionVisible(false),
1369 mouse_client_pt);
1370 m_mgr.Update();
1371 dest_tabs = new_tabs->m_tabs;
1372 }
1373
1374
1375
1376 // remove the page from the source tabs
1377 wxAuiNotebookPage page_info = src_tabs->GetPage(evt.GetSelection());
1378 page_info.active = false;
1379 src_tabs->RemovePage(page_info.window);
1380 if (src_tabs->GetPageCount() > 0)
1381 {
1382 src_tabs->SetActivePage((size_t)0);
1383 src_tabs->DoShowHide();
1384 src_tabs->Refresh();
1385 }
1386
1387
1388
1389 // add the page to the destination tabs
1390 dest_tabs->AddPage(page_info.window, page_info);
1391
1392 if (src_tabs->GetPageCount() == 0)
1393 {
1394 RemoveEmptyTabFrames();
1395 }
1396
1397 DoSizing();
1398 dest_tabs->DoShowHide();
1399 dest_tabs->Refresh();
1400
1401 SetSelection(m_tabs.GetIdxFromWindow(page_info.window));
1402 }
1403
1404 wxAuiTabCtrl* wxAuiMultiNotebook::GetTabCtrlFromPoint(const wxPoint& pt)
1405 {
1406 // if we've just removed the last tab from the source
1407 // tab set, the remove the tab control completely
1408 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1409 size_t i, pane_count = all_panes.GetCount();
1410 for (i = 0; i < pane_count; ++i)
1411 {
1412 if (all_panes.Item(i).name == wxT("dummy"))
1413 continue;
1414
1415 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1416 if (tabframe->m_tab_rect.Inside(pt))
1417 return tabframe->m_tabs;
1418 }
1419
1420 return NULL;
1421 }
1422
1423 wxWindow* wxAuiMultiNotebook::GetTabFrameFromTabCtrl(wxWindow* tab_ctrl)
1424 {
1425 // if we've just removed the last tab from the source
1426 // tab set, the remove the tab control completely
1427 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1428 size_t i, pane_count = all_panes.GetCount();
1429 for (i = 0; i < pane_count; ++i)
1430 {
1431 if (all_panes.Item(i).name == wxT("dummy"))
1432 continue;
1433
1434 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1435 if (tabframe->m_tabs == tab_ctrl)
1436 {
1437 return tabframe;
1438 }
1439 }
1440
1441 return NULL;
1442 }
1443
1444 void wxAuiMultiNotebook::RemoveEmptyTabFrames()
1445 {
1446 bool must_update = false;
1447
1448 // if we've just removed the last tab from the source
1449 // tab set, the remove the tab control completely
1450 wxPaneInfoArray all_panes = m_mgr.GetAllPanes();
1451 size_t i, pane_count = all_panes.GetCount();
1452 for (i = 0; i < pane_count; ++i)
1453 {
1454 if (all_panes.Item(i).name == wxT("dummy"))
1455 continue;
1456
1457 wxTabFrame* tab_frame = (wxTabFrame*)all_panes.Item(i).window;
1458 if (tab_frame->m_tabs->GetPageCount() == 0)
1459 {
1460 m_mgr.DetachPane(tab_frame);
1461
1462 // use pending delete because sometimes during
1463 // window closing, refreshs are pending
1464 if (!wxPendingDelete.Member(tab_frame->m_tabs))
1465 wxPendingDelete.Append(tab_frame->m_tabs);
1466 //tab_frame->m_tabs->Destroy();
1467
1468 delete tab_frame;
1469 must_update = true;
1470 }
1471 }
1472
1473
1474 // check to see if there is still a center pane;
1475 // if there isn't, make a frame the center pane
1476 wxPaneInfoArray panes = m_mgr.GetAllPanes();
1477 pane_count = panes.GetCount();
1478 wxWindow* first_good = NULL;
1479 bool center_found = false;
1480 for (i = 0; i < pane_count; ++i)
1481 {
1482 if (panes.Item(i).name == wxT("dummy"))
1483 continue;
1484 if (panes.Item(i).dock_direction == wxAUI_DOCK_CENTRE)
1485 center_found = true;
1486 if (!first_good)
1487 first_good = panes.Item(i).window;
1488 }
1489
1490 if (!center_found && first_good)
1491 {
1492 m_mgr.GetPane(first_good).Centre();
1493 must_update = true;
1494 }
1495
1496 m_mgr.Update();
1497 }
1498
1499 void wxAuiMultiNotebook::OnChildFocus(wxChildFocusEvent& evt)
1500 {
1501 int idx = m_tabs.GetIdxFromWindow(evt.GetWindow());
1502 if (idx != -1 && idx != m_curpage)
1503 {
1504 SetSelection(idx);
1505 }
1506 }
1507
1508
1509 void wxAuiMultiNotebook::OnTabButton(wxCommandEvent& command_evt)
1510 {
1511 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1512 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1513
1514 int button_id = evt.GetInt();
1515
1516 if (button_id == wxAuiButtonClose)
1517 {
1518 int selection = tabs->GetActivePage();
1519
1520 if (selection != -1)
1521 {
1522 wxWindow* close_wnd = tabs->GetWindowFromIdx(selection);
1523
1524 if (close_wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
1525 {
1526 close_wnd->Close();
1527 }
1528 else
1529 {
1530 int main_idx = m_tabs.GetIdxFromWindow(close_wnd);
1531 DeletePage(main_idx);
1532 }
1533 }
1534 }
1535 }
1536
1537
1538
1539
1540 #endif // wxUSE_AUI