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