]> git.saurik.com Git - wxWidgets.git/blob - src/aui/auibook.cpp
some GTK1 bulkd fixes from Sander Niemeijer
[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
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 wxWindow* new_wnd = ctrl->GetWindowFromIdx(new_idx);
1049 int main_idx = m_tabs.GetIdxFromWindow(new_wnd);
1050 wxASSERT(main_idx != -1);
1051 SetSelection(main_idx);
1052 }
1053 else
1054 {
1055 // set the active page to the first page that
1056 // isn't the one being deleted
1057 bool found = false;
1058 size_t i, page_count = m_tabs.GetPageCount();
1059 for (i = 0; i < page_count; ++i)
1060 {
1061 wxWindow* w = m_tabs.GetWindowFromIdx(i);
1062 if (wnd != w)
1063 {
1064 found = true;
1065 SetSelection(i);
1066 break;
1067 }
1068 }
1069
1070 if (!found)
1071 m_curpage = -1;
1072 }
1073
1074
1075 // remove the tab from main catalog
1076 if (!m_tabs.RemovePage(wnd))
1077 return false;
1078
1079 // remove the tab from the onscreen tab ctrl
1080 ctrl->RemovePage(wnd);
1081
1082 // actually destroy the window now
1083 if (wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
1084 {
1085 // delete the child frame with pending delete, as is
1086 // customary with frame windows
1087 if (!wxPendingDelete.Member(wnd))
1088 wxPendingDelete.Append(wnd);
1089 }
1090 else
1091 {
1092 wnd->Destroy();
1093 }
1094
1095 RemoveEmptyTabFrames();
1096
1097 return true;
1098 }
1099
1100
1101
1102 // RemovePage() removes a tab from the multi-notebook,
1103 // but does not destroy the window
1104 bool wxAuiMultiNotebook::RemovePage(size_t page_idx)
1105 {
1106 // remove the tab from our own catalog
1107 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
1108 if (!m_tabs.RemovePage(wnd))
1109 return false;
1110
1111 // remove the tab from the onscreen tab ctrl
1112 wxAuiTabCtrl* ctrl;
1113 int ctrl_idx;
1114 if (FindTab(wnd, &ctrl, &ctrl_idx))
1115 {
1116 ctrl->RemovePage(wnd);
1117 return true;
1118 }
1119
1120 return false;
1121 }
1122
1123 // SetPageText() changes the tab caption of the specified page
1124 bool wxAuiMultiNotebook::SetPageText(size_t page_idx, const wxString& text)
1125 {
1126 if (page_idx >= m_tabs.GetPageCount())
1127 return false;
1128
1129 // update our own tab catalog
1130 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
1131 page_info.caption = text;
1132
1133 // update what's on screen
1134 wxAuiTabCtrl* ctrl;
1135 int ctrl_idx;
1136 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
1137 {
1138 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
1139 info.caption = text;
1140 ctrl->Refresh();
1141 ctrl->Update();
1142 }
1143
1144 return true;
1145 }
1146
1147 // GetSelection() returns the index of the currently active page
1148 int wxAuiMultiNotebook::GetSelection() const
1149 {
1150 return m_curpage;
1151 }
1152
1153 // SetSelection() sets the currently active page
1154 size_t wxAuiMultiNotebook::SetSelection(size_t new_page)
1155 {
1156 wxWindow* wnd = m_tabs.GetWindowFromIdx(new_page);
1157 if (!wnd)
1158 return m_curpage;
1159
1160 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1161 evt.SetSelection(new_page);
1162 evt.SetOldSelection(m_curpage);
1163 evt.SetEventObject(this);
1164 if (!GetEventHandler()->ProcessEvent(evt) || evt.IsAllowed())
1165 {
1166 // program allows the page change
1167 evt.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED);
1168 (void)GetEventHandler()->ProcessEvent(evt);
1169
1170
1171
1172 wxAuiTabCtrl* ctrl;
1173 int ctrl_idx;
1174 if (FindTab(wnd, &ctrl, &ctrl_idx))
1175 {
1176 m_tabs.SetActivePage(wnd);
1177
1178 ctrl->SetActivePage(ctrl_idx);
1179 DoSizing();
1180 ctrl->DoShowHide();
1181
1182 int old_curpage = m_curpage;
1183 m_curpage = new_page;
1184
1185
1186 // set fonts
1187 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1188 size_t i, pane_count = all_panes.GetCount();
1189 for (i = 0; i < pane_count; ++i)
1190 {
1191 wxPaneInfo& pane = all_panes.Item(i);
1192 if (pane.name == wxT("dummy"))
1193 continue;
1194 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
1195 if (tabctrl != ctrl)
1196 tabctrl->SetSelectedFont(m_normal_font);
1197 else
1198 tabctrl->SetSelectedFont(m_selected_font);
1199 tabctrl->Refresh();
1200 }
1201
1202 wnd->SetFocus();
1203
1204 return old_curpage;
1205 }
1206 }
1207
1208 return m_curpage;
1209 }
1210
1211 // GetPageCount() returns the total number of
1212 // pages managed by the multi-notebook
1213 size_t wxAuiMultiNotebook::GetPageCount() const
1214 {
1215 return m_tabs.GetPageCount();
1216 }
1217
1218 // GetPage() returns the wxWindow pointer of the
1219 // specified page
1220 wxWindow* wxAuiMultiNotebook::GetPage(size_t page_idx) const
1221 {
1222 wxASSERT(page_idx < m_tabs.GetPageCount());
1223
1224 return m_tabs.GetWindowFromIdx(page_idx);
1225 }
1226
1227 // DoSizing() performs all sizing operations in each tab control
1228 void wxAuiMultiNotebook::DoSizing()
1229 {
1230 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1231 size_t i, pane_count = all_panes.GetCount();
1232 for (i = 0; i < pane_count; ++i)
1233 {
1234 if (all_panes.Item(i).name == wxT("dummy"))
1235 continue;
1236
1237 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1238 tabframe->DoSizing();
1239 }
1240 }
1241
1242 // GetActiveTabCtrl() returns the active tab control. It is
1243 // called to determine which control gets new windows being added
1244 wxAuiTabCtrl* wxAuiMultiNotebook::GetActiveTabCtrl()
1245 {
1246 if (m_curpage >= 0 && m_curpage < (int)m_tabs.GetPageCount())
1247 {
1248 wxAuiTabCtrl* ctrl;
1249 int idx;
1250
1251 // find the tab ctrl with the current page
1252 if (FindTab(m_tabs.GetPage(m_curpage).window,
1253 &ctrl, &idx))
1254 {
1255 return ctrl;
1256 }
1257 }
1258
1259 // no current page, just find the first tab ctrl
1260 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1261 size_t i, pane_count = all_panes.GetCount();
1262 for (i = 0; i < pane_count; ++i)
1263 {
1264 if (all_panes.Item(i).name == wxT("dummy"))
1265 continue;
1266
1267 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1268 return tabframe->m_tabs;
1269 }
1270
1271 // If there is no tabframe at all, create one
1272 wxTabFrame* tabframe = new wxTabFrame;
1273 tabframe->SetTabCtrlHeight(m_tab_ctrl_height);
1274 tabframe->m_tabs = new wxAuiTabCtrl(this,
1275 m_tab_id_counter++,
1276 wxDefaultPosition,
1277 wxDefaultSize,
1278 wxNO_BORDER);
1279 m_mgr.AddPane(tabframe,
1280 wxPaneInfo().Center().CaptionVisible(false));
1281
1282 m_mgr.Update();
1283
1284 return tabframe->m_tabs;
1285 }
1286
1287 // FindTab() finds the tab control that currently contains the window as well
1288 // as the index of the window in the tab control. It returns true if the
1289 // window was found, otherwise false.
1290 bool wxAuiMultiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx)
1291 {
1292 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1293 size_t i, pane_count = all_panes.GetCount();
1294 for (i = 0; i < pane_count; ++i)
1295 {
1296 if (all_panes.Item(i).name == wxT("dummy"))
1297 continue;
1298
1299 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1300
1301 int page_idx = tabframe->m_tabs->GetIdxFromWindow(page);
1302 if (page_idx != -1)
1303 {
1304 *ctrl = tabframe->m_tabs;
1305 *idx = page_idx;
1306 return true;
1307 }
1308 }
1309
1310 return false;
1311 }
1312
1313
1314 void wxAuiMultiNotebook::OnEraseBackground(wxEraseEvent&)
1315 {
1316 }
1317
1318 void wxAuiMultiNotebook::OnSize(wxSizeEvent&)
1319 {
1320 }
1321
1322 void wxAuiMultiNotebook::OnTabClicked(wxCommandEvent& command_evt)
1323 {
1324 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1325
1326 wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject();
1327 wxASSERT(ctrl != NULL);
1328
1329 wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection());
1330 wxASSERT(wnd != NULL);
1331
1332 int idx = m_tabs.GetIdxFromWindow(wnd);
1333 wxASSERT(idx != -1);
1334
1335 SetSelection(idx);
1336 }
1337
1338 void wxAuiMultiNotebook::OnTabBeginDrag(wxCommandEvent&)
1339 {
1340 }
1341
1342 void wxAuiMultiNotebook::OnTabDragMotion(wxCommandEvent& evt)
1343 {
1344 wxPoint screen_pt = ::wxGetMousePosition();
1345 wxPoint client_pt = ScreenToClient(screen_pt);
1346 wxPoint zero(0,0);
1347
1348 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1349
1350 wxAuiTabCtrl* tab_ctrl = GetTabCtrlFromPoint(client_pt);
1351 if (tab_ctrl == src_tabs)
1352 {
1353 // inner-tabctrl dragging is not yet implemented
1354 m_mgr.HideHint();
1355 return;
1356 }
1357
1358 if (tab_ctrl)
1359 {
1360 wxRect hint_rect = tab_ctrl->GetRect();
1361 ClientToScreen(&hint_rect.x, &hint_rect.y);
1362 m_mgr.ShowHint(hint_rect);
1363 }
1364 else
1365 {
1366 m_mgr.DrawHintRect(m_dummy_wnd, client_pt, zero);
1367 }
1368 }
1369
1370
1371
1372 void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
1373 {
1374 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1375
1376 m_mgr.HideHint();
1377
1378
1379 // get the mouse position, which will be used to determine the drop point
1380 wxPoint mouse_screen_pt = ::wxGetMousePosition();
1381 wxPoint mouse_client_pt = ScreenToClient(mouse_screen_pt);
1382
1383
1384 // the src tab control is the control that fired this event
1385 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1386 wxAuiTabCtrl* dest_tabs = NULL;
1387
1388
1389 // If the pointer is in an existing tab frame, do a tab insert
1390 wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt);
1391 wxTabFrame* tab_frame = (wxTabFrame*)GetTabFrameFromTabCtrl(hit_wnd);
1392 if (tab_frame)
1393 {
1394 dest_tabs = tab_frame->m_tabs;
1395
1396 if (dest_tabs == src_tabs)
1397 return;
1398 }
1399 else
1400 {
1401 // If there is no tabframe at all, create one
1402 wxTabFrame* new_tabs = new wxTabFrame;
1403 new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
1404 new_tabs->m_tabs = new wxAuiTabCtrl(this,
1405 m_tab_id_counter++,
1406 wxDefaultPosition,
1407 wxDefaultSize,
1408 wxNO_BORDER);
1409 m_mgr.AddPane(new_tabs,
1410 wxPaneInfo().Bottom().CaptionVisible(false),
1411 mouse_client_pt);
1412 m_mgr.Update();
1413 dest_tabs = new_tabs->m_tabs;
1414 }
1415
1416
1417
1418 // remove the page from the source tabs
1419 wxAuiNotebookPage page_info = src_tabs->GetPage(evt.GetSelection());
1420 page_info.active = false;
1421 src_tabs->RemovePage(page_info.window);
1422 if (src_tabs->GetPageCount() > 0)
1423 {
1424 src_tabs->SetActivePage((size_t)0);
1425 src_tabs->DoShowHide();
1426 src_tabs->Refresh();
1427 }
1428
1429
1430
1431 // add the page to the destination tabs
1432 dest_tabs->AddPage(page_info.window, page_info);
1433
1434 if (src_tabs->GetPageCount() == 0)
1435 {
1436 RemoveEmptyTabFrames();
1437 }
1438
1439 DoSizing();
1440 dest_tabs->DoShowHide();
1441 dest_tabs->Refresh();
1442
1443 SetSelection(m_tabs.GetIdxFromWindow(page_info.window));
1444 }
1445
1446 wxAuiTabCtrl* wxAuiMultiNotebook::GetTabCtrlFromPoint(const wxPoint& pt)
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_tab_rect.Contains(pt))
1459 return tabframe->m_tabs;
1460 }
1461
1462 return NULL;
1463 }
1464
1465 wxWindow* wxAuiMultiNotebook::GetTabFrameFromTabCtrl(wxWindow* tab_ctrl)
1466 {
1467 // if we've just removed the last tab from the source
1468 // tab set, the remove the tab control completely
1469 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1470 size_t i, pane_count = all_panes.GetCount();
1471 for (i = 0; i < pane_count; ++i)
1472 {
1473 if (all_panes.Item(i).name == wxT("dummy"))
1474 continue;
1475
1476 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1477 if (tabframe->m_tabs == tab_ctrl)
1478 {
1479 return tabframe;
1480 }
1481 }
1482
1483 return NULL;
1484 }
1485
1486 void wxAuiMultiNotebook::RemoveEmptyTabFrames()
1487 {
1488 bool must_update = false;
1489
1490 // if we've just removed the last tab from the source
1491 // tab set, the remove the tab control completely
1492 wxPaneInfoArray all_panes = m_mgr.GetAllPanes();
1493 size_t i, pane_count = all_panes.GetCount();
1494 for (i = 0; i < pane_count; ++i)
1495 {
1496 if (all_panes.Item(i).name == wxT("dummy"))
1497 continue;
1498
1499 wxTabFrame* tab_frame = (wxTabFrame*)all_panes.Item(i).window;
1500 if (tab_frame->m_tabs->GetPageCount() == 0)
1501 {
1502 m_mgr.DetachPane(tab_frame);
1503
1504 // use pending delete because sometimes during
1505 // window closing, refreshs are pending
1506 if (!wxPendingDelete.Member(tab_frame->m_tabs))
1507 wxPendingDelete.Append(tab_frame->m_tabs);
1508 //tab_frame->m_tabs->Destroy();
1509
1510 delete tab_frame;
1511 must_update = true;
1512 }
1513 }
1514
1515
1516 // check to see if there is still a center pane;
1517 // if there isn't, make a frame the center pane
1518 wxPaneInfoArray panes = m_mgr.GetAllPanes();
1519 pane_count = panes.GetCount();
1520 wxWindow* first_good = NULL;
1521 bool center_found = false;
1522 for (i = 0; i < pane_count; ++i)
1523 {
1524 if (panes.Item(i).name == wxT("dummy"))
1525 continue;
1526 if (panes.Item(i).dock_direction == wxAUI_DOCK_CENTRE)
1527 center_found = true;
1528 if (!first_good)
1529 first_good = panes.Item(i).window;
1530 }
1531
1532 if (!center_found && first_good)
1533 {
1534 m_mgr.GetPane(first_good).Centre();
1535 must_update = true;
1536 }
1537
1538 m_mgr.Update();
1539 }
1540
1541 void wxAuiMultiNotebook::OnChildFocus(wxChildFocusEvent& evt)
1542 {
1543 int idx = m_tabs.GetIdxFromWindow(evt.GetWindow());
1544 if (idx != -1 && idx != m_curpage)
1545 {
1546 SetSelection(idx);
1547 }
1548 }
1549
1550
1551 void wxAuiMultiNotebook::OnTabButton(wxCommandEvent& command_evt)
1552 {
1553 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1554 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1555
1556 int button_id = evt.GetInt();
1557
1558 if (button_id == wxAuiButtonClose)
1559 {
1560 int selection = tabs->GetActivePage();
1561
1562 if (selection != -1)
1563 {
1564 wxWindow* close_wnd = tabs->GetWindowFromIdx(selection);
1565
1566 if (close_wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
1567 {
1568 close_wnd->Close();
1569 }
1570 else
1571 {
1572 int main_idx = m_tabs.GetIdxFromWindow(close_wnd);
1573 DeletePage(main_idx);
1574 }
1575 }
1576 }
1577 }
1578
1579
1580
1581
1582 #endif // wxUSE_AUI