]> git.saurik.com Git - wxWidgets.git/blob - src/aui/auibook.cpp
fixed crash in multi notebook
[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(0,0,0,123,123,123);
78 img.Replace(255,255,255,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.Contains(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.Contains(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.Contains(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.Contains(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 #if defined( __WXMAC__ )
622 static unsigned char close_bits[]={
623 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
624 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
625 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
626 #elif defined( __WXGTK__)
627 static unsigned char close_bits[]={
628 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
629 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
630 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
631 #else
632 static unsigned char close_bits[]={
633 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
634 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
635 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
636 #endif
637
638 AddButton(101, BitmapFromBits(close_bits, 16, 16, *wxBLACK));
639 }
640
641
642 void wxAuiTabCtrl::OnPaint(wxPaintEvent&)
643 {
644 wxPaintDC dc(this);
645
646 dc.SetFont(GetFont());
647
648 if (GetPageCount() > 0)
649 Render(&dc);
650 }
651
652 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
653 {
654 }
655
656 void wxAuiTabCtrl::OnSize(wxSizeEvent& evt)
657 {
658 wxSize s = evt.GetSize();
659 wxRect r(0, 0, s.GetWidth(), s.GetHeight());
660 SetRect(r);
661 }
662
663 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt)
664 {
665 CaptureMouse();
666 m_click_pt = wxDefaultPosition;
667 m_is_dragging = false;
668 m_click_tab = -1;
669
670 wxWindow* wnd;
671 if (TabHitTest(evt.m_x, evt.m_y, &wnd))
672 {
673 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
674 e.SetSelection(GetIdxFromWindow(wnd));
675 e.SetOldSelection(GetActivePage());
676 e.SetEventObject(this);
677 GetEventHandler()->ProcessEvent(e);
678
679 m_click_pt.x = evt.m_x;
680 m_click_pt.y = evt.m_y;
681 m_click_tab = e.GetSelection();
682 }
683
684 if (m_hover_button)
685 {
686 m_hover_button->cur_state = wxAUI_BUTTON_STATE_PRESSED;
687 Refresh();
688 Update();
689 }
690 }
691
692 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent&)
693 {
694 if (GetCapture() == this)
695 ReleaseMouse();
696
697 if (m_is_dragging)
698 {
699 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, m_windowId);
700 evt.SetSelection(m_click_tab);
701 evt.SetOldSelection(m_click_tab);
702 evt.SetEventObject(this);
703 GetEventHandler()->ProcessEvent(evt);
704 return;
705 }
706
707 if (m_hover_button)
708 {
709 m_hover_button->cur_state = wxAUI_BUTTON_STATE_HOVER;
710 Refresh();
711 Update();
712
713 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_windowId);
714 evt.SetInt(m_hover_button->id);
715 evt.SetEventObject(this);
716 GetEventHandler()->ProcessEvent(evt);
717 }
718
719 m_click_pt = wxDefaultPosition;
720 m_is_dragging = false;
721 m_click_tab = -1;
722 }
723
724 void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt)
725 {
726 wxPoint pos = evt.GetPosition();
727
728 // check if the mouse is hovering above a button
729 wxAuiTabContainerButton* button;
730 if (ButtonHitTest(pos.x, pos.y, &button))
731 {
732 if (button->cur_state != wxAUI_BUTTON_STATE_HOVER)
733 {
734 button->cur_state = wxAUI_BUTTON_STATE_HOVER;
735 Refresh();
736 Update();
737 m_hover_button = button;
738 return;
739 }
740 }
741 else
742 {
743 if (m_hover_button)
744 {
745 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
746 m_hover_button = NULL;
747 Refresh();
748 Update();
749 }
750 }
751
752
753 if (!evt.LeftIsDown() || m_click_pt == wxDefaultPosition)
754 return;
755
756 if (m_is_dragging)
757 {
758 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, m_windowId);
759 evt.SetSelection(m_click_tab);
760 evt.SetOldSelection(m_click_tab);
761 evt.SetEventObject(this);
762 GetEventHandler()->ProcessEvent(evt);
763 return;
764 }
765
766
767 int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
768 int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
769
770 if (abs(pos.x - m_click_pt.x) > drag_x_threshold ||
771 abs(pos.y - m_click_pt.y) > drag_y_threshold)
772 {
773 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, m_windowId);
774 evt.SetSelection(m_click_tab);
775 evt.SetOldSelection(m_click_tab);
776 evt.SetEventObject(this);
777 GetEventHandler()->ProcessEvent(evt);
778
779 m_is_dragging = true;
780 }
781 }
782
783 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event))
784 {
785 if (m_hover_button)
786 {
787 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
788 m_hover_button = NULL;
789 Refresh();
790 Update();
791 }
792 }
793
794
795 // wxTabFrame is an interesting case. It's important that all child pages
796 // of the multi-notebook control are all actually children of that control
797 // (and not grandchildren). wxTabFrame facilitates this. There is one
798 // instance of wxTabFrame for each tab control inside the multi-notebook.
799 // It's important to know that wxTabFrame is not a real window, but it merely
800 // used to capture the dimensions/positioning of the internal tab control and
801 // it's managed page windows
802
803 class wxTabFrame : public wxWindow
804 {
805 public:
806
807 wxTabFrame()
808 {
809 m_tabs = NULL;
810 m_rect = wxRect(0,0,200,200);
811 m_tab_ctrl_height = 20;
812 }
813
814 void SetTabCtrlHeight(int h)
815 {
816 m_tab_ctrl_height = h;
817 }
818
819 void DoSetSize(int x, int y,
820 int width, int height,
821 int WXUNUSED(sizeFlags = wxSIZE_AUTO))
822 {
823 m_rect = wxRect(x, y, width, height);
824 DoSizing();
825 }
826
827 void DoGetClientSize(int* x, int* y) const
828 {
829 *x = m_rect.width;
830 *y = m_rect.height;
831 }
832
833 bool Show( bool WXUNUSED(show = true) ) { return false; }
834
835 void DoSizing()
836 {
837 if (!m_tabs)
838 return;
839
840 int tab_height = wxMin(m_rect.height, m_tab_ctrl_height);
841 m_tab_rect = wxRect(m_rect.x, m_rect.y, m_rect.width, tab_height);
842 m_tabs->SetSize(m_rect.x, m_rect.y, m_rect.width, tab_height);
843 m_tabs->SetRect(wxRect(0, 0, m_rect.width, tab_height));
844 m_tabs->Refresh();
845 m_tabs->Update();
846
847 wxAuiNotebookPageArray& pages = m_tabs->GetPages();
848 size_t i, page_count = pages.GetCount();
849
850 for (i = 0; i < page_count; ++i)
851 {
852 wxAuiNotebookPage& page = pages.Item(i);
853 page.window->SetSize(m_rect.x, m_rect.y+tab_height, m_rect.width, m_rect.height-tab_height);
854
855 if (page.window->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
856 {
857 wxTabMDIChildFrame* wnd = (wxTabMDIChildFrame*)page.window;
858 wnd->ApplyMDIChildFrameRect();
859 }
860 }
861 }
862
863 void DoGetSize(int* x, int* y) const
864 {
865 if (x)
866 *x = m_rect.GetWidth();
867 if (y)
868 *y = m_rect.GetHeight();
869 }
870
871 void Update()
872 {
873 // does nothing
874 }
875
876 public:
877
878 wxRect m_rect;
879 wxRect m_tab_rect;
880 wxAuiTabCtrl* m_tabs;
881 int m_tab_ctrl_height;
882 };
883
884
885
886
887
888 // -- wxAuiMultiNotebook class implementation --
889
890 BEGIN_EVENT_TABLE(wxAuiMultiNotebook, wxControl)
891 //EVT_ERASE_BACKGROUND(wxAuiMultiNotebook::OnEraseBackground)
892 //EVT_SIZE(wxAuiMultiNotebook::OnSize)
893 //EVT_LEFT_DOWN(wxAuiMultiNotebook::OnLeftDown)
894 EVT_CHILD_FOCUS(wxAuiMultiNotebook::OnChildFocus)
895 EVT_COMMAND_RANGE(10000, 10100,
896 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING,
897 wxAuiMultiNotebook::OnTabClicked)
898 EVT_COMMAND_RANGE(10000, 10100,
899 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG,
900 wxAuiMultiNotebook::OnTabBeginDrag)
901 EVT_COMMAND_RANGE(10000, 10100,
902 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG,
903 wxAuiMultiNotebook::OnTabEndDrag)
904 EVT_COMMAND_RANGE(10000, 10100,
905 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION,
906 wxAuiMultiNotebook::OnTabDragMotion)
907 EVT_COMMAND_RANGE(10000, 10100,
908 wxEVT_COMMAND_AUINOTEBOOK_BUTTON,
909 wxAuiMultiNotebook::OnTabButton)
910 END_EVENT_TABLE()
911
912 wxAuiMultiNotebook::wxAuiMultiNotebook()
913 {
914 m_curpage = -1;
915 m_tab_id_counter = 10000;
916 m_dummy_wnd = NULL;
917 m_tab_ctrl_height = 20;
918 }
919
920 wxAuiMultiNotebook::wxAuiMultiNotebook(wxWindow *parent,
921 wxWindowID id,
922 const wxPoint& pos,
923 const wxSize& size,
924 long style) : wxControl(parent, id, pos, size, style)
925 {
926 InitNotebook();
927 }
928
929 bool wxAuiMultiNotebook::Create(wxWindow* parent,
930 wxWindowID id,
931 const wxPoint& pos,
932 const wxSize& size,
933 long style)
934 {
935 if (!wxControl::Create(parent, id, pos, size, style))
936 return false;
937
938 InitNotebook();
939
940 return true;
941 }
942
943 // InitNotebook() contains common initialization
944 // code called by all constructors
945 void wxAuiMultiNotebook::InitNotebook()
946 {
947 m_curpage = -1;
948 m_tab_id_counter = 10000;
949 m_dummy_wnd = NULL;
950 m_tab_ctrl_height = 20;
951
952 m_normal_font = *wxNORMAL_FONT;
953 m_selected_font = *wxNORMAL_FONT;
954 m_selected_font.SetWeight(wxBOLD);
955
956 // choose a default for the tab height
957 wxClientDC dc(this);
958 int tx, ty;
959 dc.SetFont(m_selected_font);
960 dc.GetTextExtent(wxT("ABCDEFGHhijklm"), &tx, &ty);
961 m_tab_ctrl_height = (ty*150)/100;
962
963 m_dummy_wnd = new wxWindow(this, wxID_ANY, wxPoint(0,0), wxSize(0,0));
964 m_dummy_wnd->SetSize(200, 200);
965 m_dummy_wnd->Show(false);
966
967 m_mgr.SetManagedWindow(this);
968
969 m_mgr.AddPane(m_dummy_wnd,
970 wxPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
971
972 m_mgr.Update();
973 }
974
975 wxAuiMultiNotebook::~wxAuiMultiNotebook()
976 {
977 m_mgr.UnInit();
978 }
979
980 bool wxAuiMultiNotebook::AddPage(wxWindow* page,
981 const wxString& caption,
982 bool select,
983 const wxBitmap& bitmap)
984 {
985 return InsertPage(GetPageCount(), page, caption, select, bitmap);
986 }
987
988 bool wxAuiMultiNotebook::InsertPage(size_t page_idx,
989 wxWindow* page,
990 const wxString& caption,
991 bool select,
992 const wxBitmap& bitmap)
993 {
994 wxAuiNotebookPage info;
995 info.window = page;
996 info.caption = caption;
997 info.bitmap = bitmap;
998 info.active = false;
999
1000 // if there are currently no tabs, the first added
1001 // tab must be active
1002 if (m_tabs.GetPageCount() == 0)
1003 info.active = true;
1004
1005 m_tabs.InsertPage(page, info, page_idx);
1006
1007 wxAuiTabCtrl* active_tabctrl = GetActiveTabCtrl();
1008 if (page_idx >= active_tabctrl->GetPageCount())
1009 active_tabctrl->AddPage(page, info);
1010 else
1011 active_tabctrl->InsertPage(page, info, page_idx);
1012
1013 DoSizing();
1014 active_tabctrl->DoShowHide();
1015
1016 if (select)
1017 {
1018 int idx = m_tabs.GetIdxFromWindow(page);
1019 wxASSERT_MSG(idx != -1, wxT("Invalid Page index returned on wxAuiMultiNotebook::InsertPage()"));
1020
1021 SetSelection(idx);
1022 }
1023
1024 return true;
1025 }
1026
1027
1028 // DeletePage() removes a tab from the multi-notebook,
1029 // and destroys the window as well
1030 bool wxAuiMultiNotebook::DeletePage(size_t page_idx)
1031 {
1032 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
1033 wxWindow* new_active = NULL;
1034
1035 // find out which onscreen tab ctrl owns this tab
1036 wxAuiTabCtrl* ctrl;
1037 int ctrl_idx;
1038 if (!FindTab(wnd, &ctrl, &ctrl_idx))
1039 return false;
1040
1041 // find a new page and set it as active
1042 int new_idx = ctrl_idx+1;
1043 if (new_idx >= (int)ctrl->GetPageCount())
1044 new_idx = ctrl_idx-1;
1045
1046 if (new_idx >= 0 && new_idx < (int)ctrl->GetPageCount())
1047 {
1048 new_active = ctrl->GetWindowFromIdx(new_idx);
1049 }
1050 else
1051 {
1052 // set the active page to the first page that
1053 // isn't the one being deleted
1054 size_t i, page_count = m_tabs.GetPageCount();
1055 for (i = 0; i < page_count; ++i)
1056 {
1057 wxWindow* w = m_tabs.GetWindowFromIdx(i);
1058 if (wnd != w)
1059 {
1060 new_active = m_tabs.GetWindowFromIdx(i);
1061 break;
1062 }
1063 }
1064 }
1065
1066 // remove the tab from main catalog
1067 if (!m_tabs.RemovePage(wnd))
1068 return false;
1069
1070 // remove the tab from the onscreen tab ctrl
1071 ctrl->RemovePage(wnd);
1072
1073 // actually destroy the window now
1074 if (wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
1075 {
1076 // delete the child frame with pending delete, as is
1077 // customary with frame windows
1078 if (!wxPendingDelete.Member(wnd))
1079 wxPendingDelete.Append(wnd);
1080 }
1081 else
1082 {
1083 wnd->Destroy();
1084 }
1085
1086 RemoveEmptyTabFrames();
1087
1088 // set new active pane
1089 if (new_active)
1090 {
1091 m_curpage = -1;
1092 SetSelection(m_tabs.GetIdxFromWindow(new_active));
1093 }
1094
1095 return true;
1096 }
1097
1098
1099
1100 // RemovePage() removes a tab from the multi-notebook,
1101 // but does not destroy the window
1102 bool wxAuiMultiNotebook::RemovePage(size_t page_idx)
1103 {
1104 // remove the tab from our own catalog
1105 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
1106 if (!m_tabs.RemovePage(wnd))
1107 return false;
1108
1109 // remove the tab from the onscreen tab ctrl
1110 wxAuiTabCtrl* ctrl;
1111 int ctrl_idx;
1112 if (FindTab(wnd, &ctrl, &ctrl_idx))
1113 {
1114 ctrl->RemovePage(wnd);
1115 return true;
1116 }
1117
1118 return false;
1119 }
1120
1121 // SetPageText() changes the tab caption of the specified page
1122 bool wxAuiMultiNotebook::SetPageText(size_t page_idx, const wxString& text)
1123 {
1124 if (page_idx >= m_tabs.GetPageCount())
1125 return false;
1126
1127 // update our own tab catalog
1128 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
1129 page_info.caption = text;
1130
1131 // update what's on screen
1132 wxAuiTabCtrl* ctrl;
1133 int ctrl_idx;
1134 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
1135 {
1136 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
1137 info.caption = text;
1138 ctrl->Refresh();
1139 ctrl->Update();
1140 }
1141
1142 return true;
1143 }
1144
1145 // GetSelection() returns the index of the currently active page
1146 int wxAuiMultiNotebook::GetSelection() const
1147 {
1148 return m_curpage;
1149 }
1150
1151 // SetSelection() sets the currently active page
1152 size_t wxAuiMultiNotebook::SetSelection(size_t new_page)
1153 {
1154 wxWindow* wnd = m_tabs.GetWindowFromIdx(new_page);
1155 if (!wnd)
1156 return m_curpage;
1157
1158 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1159 evt.SetSelection(new_page);
1160 evt.SetOldSelection(m_curpage);
1161 evt.SetEventObject(this);
1162 if (!GetEventHandler()->ProcessEvent(evt) || evt.IsAllowed())
1163 {
1164 // program allows the page change
1165 evt.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED);
1166 (void)GetEventHandler()->ProcessEvent(evt);
1167
1168
1169
1170 wxAuiTabCtrl* ctrl;
1171 int ctrl_idx;
1172 if (FindTab(wnd, &ctrl, &ctrl_idx))
1173 {
1174 m_tabs.SetActivePage(wnd);
1175
1176 ctrl->SetActivePage(ctrl_idx);
1177 DoSizing();
1178 ctrl->DoShowHide();
1179
1180 int old_curpage = m_curpage;
1181 m_curpage = new_page;
1182
1183
1184 // set fonts
1185 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1186 size_t i, pane_count = all_panes.GetCount();
1187 for (i = 0; i < pane_count; ++i)
1188 {
1189 wxPaneInfo& pane = all_panes.Item(i);
1190 if (pane.name == wxT("dummy"))
1191 continue;
1192 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
1193 if (tabctrl != ctrl)
1194 tabctrl->SetSelectedFont(m_normal_font);
1195 else
1196 tabctrl->SetSelectedFont(m_selected_font);
1197 tabctrl->Refresh();
1198 }
1199
1200 wnd->SetFocus();
1201
1202 return old_curpage;
1203 }
1204 }
1205
1206 return m_curpage;
1207 }
1208
1209 // GetPageCount() returns the total number of
1210 // pages managed by the multi-notebook
1211 size_t wxAuiMultiNotebook::GetPageCount() const
1212 {
1213 return m_tabs.GetPageCount();
1214 }
1215
1216 // GetPage() returns the wxWindow pointer of the
1217 // specified page
1218 wxWindow* wxAuiMultiNotebook::GetPage(size_t page_idx) const
1219 {
1220 wxASSERT(page_idx < m_tabs.GetPageCount());
1221
1222 return m_tabs.GetWindowFromIdx(page_idx);
1223 }
1224
1225 // DoSizing() performs all sizing operations in each tab control
1226 void wxAuiMultiNotebook::DoSizing()
1227 {
1228 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1229 size_t i, pane_count = all_panes.GetCount();
1230 for (i = 0; i < pane_count; ++i)
1231 {
1232 if (all_panes.Item(i).name == wxT("dummy"))
1233 continue;
1234
1235 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1236 tabframe->DoSizing();
1237 }
1238 }
1239
1240 // GetActiveTabCtrl() returns the active tab control. It is
1241 // called to determine which control gets new windows being added
1242 wxAuiTabCtrl* wxAuiMultiNotebook::GetActiveTabCtrl()
1243 {
1244 if (m_curpage >= 0 && m_curpage < (int)m_tabs.GetPageCount())
1245 {
1246 wxAuiTabCtrl* ctrl;
1247 int idx;
1248
1249 // find the tab ctrl with the current page
1250 if (FindTab(m_tabs.GetPage(m_curpage).window,
1251 &ctrl, &idx))
1252 {
1253 return ctrl;
1254 }
1255 }
1256
1257 // no current page, just find the first tab ctrl
1258 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1259 size_t i, pane_count = all_panes.GetCount();
1260 for (i = 0; i < pane_count; ++i)
1261 {
1262 if (all_panes.Item(i).name == wxT("dummy"))
1263 continue;
1264
1265 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1266 return tabframe->m_tabs;
1267 }
1268
1269 // If there is no tabframe at all, create one
1270 wxTabFrame* tabframe = new wxTabFrame;
1271 tabframe->SetTabCtrlHeight(m_tab_ctrl_height);
1272 tabframe->m_tabs = new wxAuiTabCtrl(this,
1273 m_tab_id_counter++,
1274 wxDefaultPosition,
1275 wxDefaultSize,
1276 wxNO_BORDER);
1277 m_mgr.AddPane(tabframe,
1278 wxPaneInfo().Center().CaptionVisible(false));
1279
1280 m_mgr.Update();
1281
1282 return tabframe->m_tabs;
1283 }
1284
1285 // FindTab() finds the tab control that currently contains the window as well
1286 // as the index of the window in the tab control. It returns true if the
1287 // window was found, otherwise false.
1288 bool wxAuiMultiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx)
1289 {
1290 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1291 size_t i, pane_count = all_panes.GetCount();
1292 for (i = 0; i < pane_count; ++i)
1293 {
1294 if (all_panes.Item(i).name == wxT("dummy"))
1295 continue;
1296
1297 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1298
1299 int page_idx = tabframe->m_tabs->GetIdxFromWindow(page);
1300 if (page_idx != -1)
1301 {
1302 *ctrl = tabframe->m_tabs;
1303 *idx = page_idx;
1304 return true;
1305 }
1306 }
1307
1308 return false;
1309 }
1310
1311
1312 void wxAuiMultiNotebook::OnEraseBackground(wxEraseEvent&)
1313 {
1314 }
1315
1316 void wxAuiMultiNotebook::OnSize(wxSizeEvent&)
1317 {
1318 }
1319
1320 void wxAuiMultiNotebook::OnTabClicked(wxCommandEvent& command_evt)
1321 {
1322 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1323
1324 wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject();
1325 wxASSERT(ctrl != NULL);
1326
1327 wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection());
1328 wxASSERT(wnd != NULL);
1329
1330 int idx = m_tabs.GetIdxFromWindow(wnd);
1331 wxASSERT(idx != -1);
1332
1333 SetSelection(idx);
1334 }
1335
1336 void wxAuiMultiNotebook::OnTabBeginDrag(wxCommandEvent&)
1337 {
1338 }
1339
1340 void wxAuiMultiNotebook::OnTabDragMotion(wxCommandEvent& evt)
1341 {
1342 wxPoint screen_pt = ::wxGetMousePosition();
1343 wxPoint client_pt = ScreenToClient(screen_pt);
1344 wxPoint zero(0,0);
1345
1346 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1347
1348 wxAuiTabCtrl* tab_ctrl = GetTabCtrlFromPoint(client_pt);
1349 if (tab_ctrl == src_tabs)
1350 {
1351 // inner-tabctrl dragging is not yet implemented
1352 m_mgr.HideHint();
1353 return;
1354 }
1355
1356 if (tab_ctrl)
1357 {
1358 wxRect hint_rect = tab_ctrl->GetRect();
1359 ClientToScreen(&hint_rect.x, &hint_rect.y);
1360 m_mgr.ShowHint(hint_rect);
1361 }
1362 else
1363 {
1364 m_mgr.DrawHintRect(m_dummy_wnd, client_pt, zero);
1365 }
1366 }
1367
1368
1369
1370 void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
1371 {
1372 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1373
1374 m_mgr.HideHint();
1375
1376
1377 // get the mouse position, which will be used to determine the drop point
1378 wxPoint mouse_screen_pt = ::wxGetMousePosition();
1379 wxPoint mouse_client_pt = ScreenToClient(mouse_screen_pt);
1380
1381
1382 // the src tab control is the control that fired this event
1383 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1384 wxAuiTabCtrl* dest_tabs = NULL;
1385
1386
1387 // If the pointer is in an existing tab frame, do a tab insert
1388 wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt);
1389 wxTabFrame* tab_frame = (wxTabFrame*)GetTabFrameFromTabCtrl(hit_wnd);
1390 if (tab_frame)
1391 {
1392 dest_tabs = tab_frame->m_tabs;
1393
1394 if (dest_tabs == src_tabs)
1395 return;
1396 }
1397 else
1398 {
1399 // If there is no tabframe at all, create one
1400 wxTabFrame* new_tabs = new wxTabFrame;
1401 new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
1402 new_tabs->m_tabs = new wxAuiTabCtrl(this,
1403 m_tab_id_counter++,
1404 wxDefaultPosition,
1405 wxDefaultSize,
1406 wxNO_BORDER);
1407 m_mgr.AddPane(new_tabs,
1408 wxPaneInfo().Bottom().CaptionVisible(false),
1409 mouse_client_pt);
1410 m_mgr.Update();
1411 dest_tabs = new_tabs->m_tabs;
1412 }
1413
1414
1415
1416 // remove the page from the source tabs
1417 wxAuiNotebookPage page_info = src_tabs->GetPage(evt.GetSelection());
1418 page_info.active = false;
1419 src_tabs->RemovePage(page_info.window);
1420 if (src_tabs->GetPageCount() > 0)
1421 {
1422 src_tabs->SetActivePage((size_t)0);
1423 src_tabs->DoShowHide();
1424 src_tabs->Refresh();
1425 }
1426
1427
1428
1429 // add the page to the destination tabs
1430 dest_tabs->AddPage(page_info.window, page_info);
1431
1432 if (src_tabs->GetPageCount() == 0)
1433 {
1434 RemoveEmptyTabFrames();
1435 }
1436
1437 DoSizing();
1438 dest_tabs->DoShowHide();
1439 dest_tabs->Refresh();
1440
1441 SetSelection(m_tabs.GetIdxFromWindow(page_info.window));
1442 }
1443
1444 wxAuiTabCtrl* wxAuiMultiNotebook::GetTabCtrlFromPoint(const wxPoint& pt)
1445 {
1446 // if we've just removed the last tab from the source
1447 // tab set, the remove the tab control completely
1448 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1449 size_t i, pane_count = all_panes.GetCount();
1450 for (i = 0; i < pane_count; ++i)
1451 {
1452 if (all_panes.Item(i).name == wxT("dummy"))
1453 continue;
1454
1455 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1456 if (tabframe->m_tab_rect.Contains(pt))
1457 return tabframe->m_tabs;
1458 }
1459
1460 return NULL;
1461 }
1462
1463 wxWindow* wxAuiMultiNotebook::GetTabFrameFromTabCtrl(wxWindow* tab_ctrl)
1464 {
1465 // if we've just removed the last tab from the source
1466 // tab set, the remove the tab control completely
1467 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1468 size_t i, pane_count = all_panes.GetCount();
1469 for (i = 0; i < pane_count; ++i)
1470 {
1471 if (all_panes.Item(i).name == wxT("dummy"))
1472 continue;
1473
1474 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1475 if (tabframe->m_tabs == tab_ctrl)
1476 {
1477 return tabframe;
1478 }
1479 }
1480
1481 return NULL;
1482 }
1483
1484 void wxAuiMultiNotebook::RemoveEmptyTabFrames()
1485 {
1486 bool must_update = false;
1487
1488 // if we've just removed the last tab from the source
1489 // tab set, the remove the tab control completely
1490 wxPaneInfoArray all_panes = m_mgr.GetAllPanes();
1491 size_t i, pane_count = all_panes.GetCount();
1492 for (i = 0; i < pane_count; ++i)
1493 {
1494 if (all_panes.Item(i).name == wxT("dummy"))
1495 continue;
1496
1497 wxTabFrame* tab_frame = (wxTabFrame*)all_panes.Item(i).window;
1498 if (tab_frame->m_tabs->GetPageCount() == 0)
1499 {
1500 m_mgr.DetachPane(tab_frame);
1501
1502 // use pending delete because sometimes during
1503 // window closing, refreshs are pending
1504 if (!wxPendingDelete.Member(tab_frame->m_tabs))
1505 wxPendingDelete.Append(tab_frame->m_tabs);
1506 //tab_frame->m_tabs->Destroy();
1507
1508 delete tab_frame;
1509 must_update = true;
1510 }
1511 }
1512
1513
1514 // check to see if there is still a center pane;
1515 // if there isn't, make a frame the center pane
1516 wxPaneInfoArray panes = m_mgr.GetAllPanes();
1517 pane_count = panes.GetCount();
1518 wxWindow* first_good = NULL;
1519 bool center_found = false;
1520 for (i = 0; i < pane_count; ++i)
1521 {
1522 if (panes.Item(i).name == wxT("dummy"))
1523 continue;
1524 if (panes.Item(i).dock_direction == wxAUI_DOCK_CENTRE)
1525 center_found = true;
1526 if (!first_good)
1527 first_good = panes.Item(i).window;
1528 }
1529
1530 if (!center_found && first_good)
1531 {
1532 m_mgr.GetPane(first_good).Centre();
1533 must_update = true;
1534 }
1535
1536 m_mgr.Update();
1537 }
1538
1539 void wxAuiMultiNotebook::OnChildFocus(wxChildFocusEvent& evt)
1540 {
1541 int idx = m_tabs.GetIdxFromWindow(evt.GetWindow());
1542 if (idx != -1 && idx != m_curpage)
1543 {
1544 SetSelection(idx);
1545 }
1546 }
1547
1548
1549 void wxAuiMultiNotebook::OnTabButton(wxCommandEvent& command_evt)
1550 {
1551 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1552 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1553
1554 int button_id = evt.GetInt();
1555
1556 if (button_id == wxAuiButtonClose)
1557 {
1558 int selection = tabs->GetActivePage();
1559
1560 if (selection != -1)
1561 {
1562 wxWindow* close_wnd = tabs->GetWindowFromIdx(selection);
1563
1564 if (close_wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
1565 {
1566 close_wnd->Close();
1567 }
1568 else
1569 {
1570 int main_idx = m_tabs.GetIdxFromWindow(close_wnd);
1571 DeletePage(main_idx);
1572 }
1573 }
1574 }
1575 }
1576
1577
1578
1579
1580 #endif // wxUSE_AUI