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