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