]> git.saurik.com Git - wxWidgets.git/blob - src/aui/auibook.cpp
0df4995c4fc167b2b9f2c7305b47695516ef1abb
[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 IMPLEMENT_CLASS(wxAuiNotebook, wxControl)
46 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent, wxEvent)
47
48
49
50
51
52 // This functions are here for this proof of concept
53 // and will be factored out later. See dockart.cpp
54 static wxColor StepColour(const wxColor& c, int percent)
55 {
56 int r = c.Red(), g = c.Green(), b = c.Blue();
57 return wxColour((unsigned char)wxMin((r*percent)/100,255),
58 (unsigned char)wxMin((g*percent)/100,255),
59 (unsigned char)wxMin((b*percent)/100,255));
60 }
61
62 // This functions are here for this proof of concept
63 // and will be factored out later. See dockart.cpp
64 static wxBitmap BitmapFromBits(const unsigned char bits[], int w, int h,
65 const wxColour& color)
66 {
67 wxImage img = wxBitmap((const char*)bits, w, h).ConvertToImage();
68 img.Replace(0,0,0,123,123,123);
69 img.Replace(255,255,255,color.Red(),color.Green(),color.Blue());
70 img.SetMaskColour(123,123,123);
71 return wxBitmap(img);
72 }
73
74 static void DrawButtonS(wxDC& dc,
75 const wxRect& _rect,
76 const wxBitmap& bmp,
77 const wxColour& bkcolour,
78 int button_state)
79 {
80 wxRect rect = _rect;
81
82 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
83 {
84 rect.x++;
85 rect.y++;
86 }
87
88 if (button_state == wxAUI_BUTTON_STATE_HOVER ||
89 button_state == wxAUI_BUTTON_STATE_PRESSED)
90 {
91 dc.SetBrush(wxBrush(StepColour(bkcolour, 120)));
92 dc.SetPen(wxPen(StepColour(bkcolour, 70)));
93
94 // draw the background behind the button
95 dc.DrawRectangle(rect.x, rect.y, 15, 15);
96 }
97
98 // draw the button itself
99 dc.DrawBitmap(bmp, rect.x, rect.y, true);
100 }
101
102
103
104
105
106 // -- wxAuiDefaultTabArt class implementation --
107
108 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
109 {
110 m_normal_font = *wxNORMAL_FONT;
111 m_selected_font = *wxNORMAL_FONT;
112 m_selected_font.SetWeight(wxBOLD);
113 m_measuring_font = m_selected_font;
114
115 wxColour base_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
116
117 wxColour background_colour = StepColour(base_colour, 95);
118 wxColour normaltab_colour = base_colour;
119 wxColour selectedtab_colour = *wxWHITE;
120
121 m_bkbrush = wxBrush(background_colour);
122 m_normal_bkbrush = wxBrush(normaltab_colour);
123 m_normal_bkpen = wxPen(normaltab_colour);
124 m_selected_bkbrush = wxBrush(selectedtab_colour);
125 m_selected_bkpen = wxPen(selectedtab_colour);
126
127
128 #if defined( __WXMAC__ )
129 static unsigned char close_bits[]={
130 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
131 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
132 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
133 #elif defined( __WXGTK__)
134 static unsigned char close_bits[]={
135 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
136 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
137 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
138 #else
139 static unsigned char close_bits[]={
140 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
141 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
142 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
143 #endif
144
145 static unsigned char left_bits[] = {
146 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
147 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
148 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
149
150 static unsigned char right_bits[] = {
151 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
152 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
153 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
154
155 m_active_close_bmp = BitmapFromBits(close_bits, 16, 16, *wxBLACK);
156 m_disabled_close_bmp = BitmapFromBits(close_bits, 16, 16, wxColour(128,128,128));
157
158 m_active_left_bmp = BitmapFromBits(left_bits, 16, 16, *wxBLACK);
159 m_disabled_left_bmp = BitmapFromBits(left_bits, 16, 16, wxColour(128,128,128));
160
161 m_active_right_bmp = BitmapFromBits(right_bits, 16, 16, *wxBLACK);
162 m_disabled_right_bmp = BitmapFromBits(right_bits, 16, 16, wxColour(128,128,128));
163 }
164
165 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
166 {
167 }
168
169 void wxAuiDefaultTabArt::DrawBackground(wxDC* dc,
170 const wxRect& rect)
171 {
172 // draw background
173 dc->SetBrush(m_bkbrush);
174 dc->SetPen(*wxTRANSPARENT_PEN);
175 dc->DrawRectangle(-1, -1, rect.GetWidth()+2, rect.GetHeight()+2);
176
177 // draw base line
178 dc->SetPen(*wxGREY_PEN);
179 dc->DrawLine(0, rect.GetHeight()-1, rect.GetWidth(), rect.GetHeight()-1);
180 }
181
182
183 // DrawTab() draws an individual tab.
184 //
185 // dc - output dc
186 // in_rect - rectangle the tab should be confined to
187 // caption - tab's caption
188 // active - whether or not the tab is active
189 // out_rect - actual output rectangle
190 // x_extent - the advance x; where the next tab should start
191
192 void wxAuiDefaultTabArt::DrawTab(wxDC* dc,
193 const wxRect& in_rect,
194 const wxString& caption_text,
195 bool active,
196 int close_button_state,
197 wxRect* out_tab_rect,
198 wxRect* out_button_rect,
199 int* x_extent)
200 {
201 wxCoord normal_textx, normal_texty;
202 wxCoord selected_textx, selected_texty;
203 wxCoord textx, texty;
204
205 // if the caption is empty, measure some temporary text
206 wxString caption = caption_text;
207 if (caption_text.empty())
208 caption = wxT("Xj");
209
210 dc->SetFont(m_selected_font);
211 dc->GetTextExtent(caption, &selected_textx, &selected_texty);
212
213 dc->SetFont(m_normal_font);
214 dc->GetTextExtent(caption, &normal_textx, &normal_texty);
215
216 // figure out the size of the tab
217 wxSize tab_size = GetTabSize(dc, caption, active, close_button_state, x_extent);
218
219 wxCoord tab_height = tab_size.y;
220 wxCoord tab_width = tab_size.x;
221 wxCoord tab_x = in_rect.x;
222 wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
223
224 // select pen, brush and font for the tab to be drawn
225
226 if (active)
227 {
228 dc->SetPen(m_selected_bkpen);
229 dc->SetBrush(m_selected_bkbrush);
230 dc->SetFont(m_selected_font);
231 textx = selected_textx;
232 texty = selected_texty;
233 }
234 else
235 {
236 dc->SetPen(m_normal_bkpen);
237 dc->SetBrush(m_normal_bkbrush);
238 dc->SetFont(m_normal_font);
239 textx = normal_textx;
240 texty = normal_texty;
241 }
242
243
244 // -- draw line --
245
246 wxPoint points[7];
247 points[0].x = tab_x;
248 points[0].y = tab_y + tab_height - 1;
249 points[1].x = tab_x + tab_height - 3;
250 points[1].y = tab_y + 2;
251 points[2].x = tab_x + tab_height + 3;
252 points[2].y = tab_y;
253 points[3].x = tab_x + tab_width - 2;
254 points[3].y = tab_y;
255 points[4].x = tab_x + tab_width;
256 points[4].y = tab_y + 2;
257 points[5].x = tab_x + tab_width;
258 points[5].y = tab_y + tab_height - 1;
259 points[6] = points[0];
260
261
262 dc->DrawPolygon(6, points);
263
264 dc->SetPen(*wxGREY_PEN);
265
266 //dc->DrawLines(active ? 6 : 7, points);
267 dc->DrawLines(7, points);
268
269
270 int text_offset;
271
272 int close_button_width = 0;
273 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
274 {
275 close_button_width = m_active_close_bmp.GetWidth();
276 text_offset = tab_x + (tab_height/2) + ((tab_width-close_button_width)/2) - (textx/2);
277 }
278 else
279 {
280 text_offset = tab_x + (tab_height/3) + (tab_width/2) - (textx/2);
281 }
282
283
284 // draw tab text
285 dc->DrawText(caption,
286 text_offset,
287 (tab_y + tab_height)/2 - (texty/2) + 1);
288
289
290 // draw close button if necessary
291 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
292 {
293 wxBitmap bmp;
294 if (active)
295 bmp = m_active_close_bmp;
296 else
297 bmp = m_disabled_close_bmp;
298
299 wxRect rect(tab_x + tab_width - close_button_width - 1,
300 tab_y + (tab_height/2) - (bmp.GetHeight()/2) + 1,
301 close_button_width,
302 tab_height - 1);
303 DrawButtonS(*dc, rect, bmp, *wxWHITE, close_button_state);
304
305 *out_button_rect = rect;
306 }
307
308
309 *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
310 }
311
312
313 wxSize wxAuiDefaultTabArt::GetTabSize(wxDC* dc,
314 const wxString& caption,
315 bool WXUNUSED(active),
316 int close_button_state,
317 int* x_extent)
318 {
319 wxCoord measured_textx, measured_texty;
320
321 dc->SetFont(m_measuring_font);
322 dc->GetTextExtent(caption, &measured_textx, &measured_texty);
323
324 wxCoord tab_height = measured_texty + 4;
325 wxCoord tab_width = measured_textx + tab_height + 5;
326
327 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
328 tab_width += m_active_close_bmp.GetWidth();
329
330 *x_extent = tab_width - (tab_height/2) - 1;
331
332 return wxSize(tab_width, tab_height);
333 }
334
335
336 void wxAuiDefaultTabArt::DrawButton(
337 wxDC* dc,
338 const wxRect& in_rect,
339 int bitmap_id,
340 int button_state,
341 int orientation,
342 const wxBitmap& bitmap_override,
343 wxRect* out_rect)
344 {
345 wxBitmap bmp;
346 wxRect rect;
347
348 if (bitmap_override.IsOk())
349 {
350 bmp = bitmap_override;
351 }
352 else
353 {
354 switch (bitmap_id)
355 {
356 case wxAUI_BUTTON_CLOSE:
357 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
358 bmp = m_disabled_close_bmp;
359 else
360 bmp = m_active_close_bmp;
361 break;
362 case wxAUI_BUTTON_LEFT:
363 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
364 bmp = m_disabled_left_bmp;
365 else
366 bmp = m_active_left_bmp;
367 break;
368 case wxAUI_BUTTON_RIGHT:
369 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
370 bmp = m_disabled_right_bmp;
371 else
372 bmp = m_active_right_bmp;
373 break;
374 }
375 }
376
377 if (!bmp.IsOk())
378 return;
379
380 rect = in_rect;
381
382 if (orientation == wxLEFT)
383 {
384 rect.SetX(in_rect.x);
385 rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2));
386 rect.SetWidth(bmp.GetWidth());
387 rect.SetHeight(bmp.GetHeight());
388 }
389 else
390 {
391 rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
392 ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
393 bmp.GetWidth(), bmp.GetHeight());
394 }
395
396
397 DrawButtonS(*dc, rect, bmp, *wxWHITE, button_state);
398
399 *out_rect = rect;
400 }
401
402
403
404 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow* wnd)
405 {
406 wxClientDC dc(wnd);
407 dc.SetFont(m_measuring_font);
408 int x_ext = 0;
409 wxSize s = GetTabSize(&dc, wxT("ABCDEFGHIj"), true, wxAUI_BUTTON_STATE_HIDDEN, &x_ext);
410 return s.y+3;
411 }
412
413 void wxAuiDefaultTabArt::SetNormalFont(const wxFont& font)
414 {
415 m_normal_font = font;
416 }
417
418 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont& font)
419 {
420 m_selected_font = font;
421 }
422
423 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont& font)
424 {
425 m_measuring_font = font;
426 }
427
428
429
430
431
432
433 // -- wxAuiTabContainer class implementation --
434
435
436 // wxAuiTabContainer is a class which contains information about each
437 // tab. It also can render an entire tab control to a specified DC.
438 // It's not a window class itself, because this code will be used by
439 // the wxFrameMananger, where it is disadvantageous to have separate
440 // windows for each tab control in the case of "docked tabs"
441
442 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
443 // which can be used as a tab control in the normal sense.
444
445
446 wxAuiTabContainer::wxAuiTabContainer()
447 {
448 m_tab_offset = 0;
449 m_flags = 0;
450 m_art = new wxAuiDefaultTabArt;
451
452 AddButton(wxAUI_BUTTON_LEFT, wxLEFT);
453 AddButton(wxAUI_BUTTON_RIGHT, wxRIGHT);
454 AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT);
455 }
456
457 wxAuiTabContainer::~wxAuiTabContainer()
458 {
459 delete m_art;
460 }
461
462 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt* art)
463 {
464 delete m_art;
465 m_art = art;
466 }
467
468 wxAuiTabArt* wxAuiTabContainer::GetArtProvider()
469 {
470 return m_art;
471 }
472
473 void wxAuiTabContainer::SetFlags(unsigned int flags)
474 {
475 m_flags = flags;
476
477 // check for new close button settings
478 RemoveButton(wxAUI_BUTTON_CLOSE);
479 if (flags & wxAUI_NB_CLOSE_BUTTON)
480 {
481 AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT);
482 }
483 }
484
485 unsigned int wxAuiTabContainer::GetFlags() const
486 {
487 return m_flags;
488 }
489
490
491 void wxAuiTabContainer::SetNormalFont(const wxFont& font)
492 {
493 m_art->SetNormalFont(font);
494 }
495
496 void wxAuiTabContainer::SetSelectedFont(const wxFont& font)
497 {
498 m_art->SetSelectedFont(font);
499 }
500
501 void wxAuiTabContainer::SetMeasuringFont(const wxFont& font)
502 {
503 m_art->SetMeasuringFont(font);
504 }
505
506 void wxAuiTabContainer::SetRect(const wxRect& rect)
507 {
508 m_rect = rect;
509 }
510
511 bool wxAuiTabContainer::AddPage(wxWindow* page,
512 const wxAuiNotebookPage& info)
513 {
514 wxAuiNotebookPage page_info;
515 page_info = info;
516 page_info.window = page;
517
518 m_pages.Add(page_info);
519
520 return true;
521 }
522
523 bool wxAuiTabContainer::InsertPage(wxWindow* page,
524 const wxAuiNotebookPage& info,
525 size_t idx)
526 {
527 wxAuiNotebookPage page_info;
528 page_info = info;
529 page_info.window = page;
530
531 if (idx >= m_pages.GetCount())
532 m_pages.Add(page_info);
533 else
534 m_pages.Insert(page_info, idx);
535
536 return true;
537 }
538
539 bool wxAuiTabContainer::MovePage(wxWindow* page,
540 size_t new_idx)
541 {
542 int idx = GetIdxFromWindow(page);
543 if (idx == -1)
544 return false;
545
546 // get page entry, make a copy of it
547 wxAuiNotebookPage p = GetPage(idx);
548
549 // remove old page entry
550 RemovePage(page);
551
552 // insert page where it should be
553 InsertPage(page, p, new_idx);
554
555 return true;
556 }
557
558 bool wxAuiTabContainer::RemovePage(wxWindow* wnd)
559 {
560 size_t i, page_count = m_pages.GetCount();
561 for (i = 0; i < page_count; ++i)
562 {
563 wxAuiNotebookPage& page = m_pages.Item(i);
564 if (page.window == wnd)
565 {
566 m_pages.RemoveAt(i);
567 return true;
568 }
569 }
570
571 return false;
572 }
573
574 bool wxAuiTabContainer::SetActivePage(wxWindow* wnd)
575 {
576 bool found = false;
577
578 size_t i, page_count = m_pages.GetCount();
579 for (i = 0; i < page_count; ++i)
580 {
581 wxAuiNotebookPage& page = m_pages.Item(i);
582 if (page.window == wnd)
583 {
584 page.active = true;
585 found = true;
586 }
587 else
588 {
589 page.active = false;
590 }
591 }
592
593 return found;
594 }
595
596 void wxAuiTabContainer::SetNoneActive()
597 {
598 size_t i, page_count = m_pages.GetCount();
599 for (i = 0; i < page_count; ++i)
600 {
601 wxAuiNotebookPage& page = m_pages.Item(i);
602 page.active = false;
603 }
604 }
605
606 bool wxAuiTabContainer::SetActivePage(size_t page)
607 {
608 if (page >= m_pages.GetCount())
609 return false;
610
611 return SetActivePage(m_pages.Item(page).window);
612 }
613
614 int wxAuiTabContainer::GetActivePage() const
615 {
616 size_t i, page_count = m_pages.GetCount();
617 for (i = 0; i < page_count; ++i)
618 {
619 wxAuiNotebookPage& page = m_pages.Item(i);
620 if (page.active)
621 return i;
622 }
623
624 return -1;
625 }
626
627 wxWindow* wxAuiTabContainer::GetWindowFromIdx(size_t idx) const
628 {
629 if (idx >= m_pages.GetCount())
630 return NULL;
631
632 return m_pages[idx].window;
633 }
634
635 int wxAuiTabContainer::GetIdxFromWindow(wxWindow* wnd) const
636 {
637 size_t i, page_count = m_pages.GetCount();
638 for (i = 0; i < page_count; ++i)
639 {
640 wxAuiNotebookPage& page = m_pages.Item(i);
641 if (page.window == wnd)
642 return i;
643 }
644 return -1;
645 }
646
647 wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx)
648 {
649 wxASSERT_MSG(idx < m_pages.GetCount(), wxT("Invalid Page index"));
650
651 return m_pages[idx];
652 }
653
654 wxAuiNotebookPageArray& wxAuiTabContainer::GetPages()
655 {
656 return m_pages;
657 }
658
659 size_t wxAuiTabContainer::GetPageCount() const
660 {
661 return m_pages.GetCount();
662 }
663
664 void wxAuiTabContainer::AddButton(int id,
665 int location,
666 const wxBitmap& normal_bitmap,
667 const wxBitmap& disabled_bitmap)
668 {
669 wxAuiTabContainerButton button;
670 button.id = id;
671 button.bitmap = normal_bitmap;
672 button.dis_bitmap = disabled_bitmap;
673 button.location = location;
674 button.cur_state = wxAUI_BUTTON_STATE_NORMAL;
675
676 m_buttons.Add(button);
677 }
678
679 void wxAuiTabContainer::RemoveButton(int id)
680 {
681 size_t i, button_count = m_buttons.GetCount();
682
683 for (i = 0; i < button_count; ++i)
684 {
685 if (m_buttons.Item(i).id == id)
686 {
687 m_buttons.RemoveAt(i);
688 return;
689 }
690 }
691 }
692
693
694
695 size_t wxAuiTabContainer::GetTabOffset() const
696 {
697 return m_tab_offset;
698 }
699
700 void wxAuiTabContainer::SetTabOffset(size_t offset)
701 {
702 m_tab_offset = offset;
703 }
704
705 // Render() renders the tab catalog to the specified DC
706 // It is a virtual function and can be overridden to
707 // provide custom drawing capabilities
708 void wxAuiTabContainer::Render(wxDC* raw_dc)
709 {
710 wxMemoryDC dc;
711 wxBitmap bmp;
712 size_t i;
713 size_t page_count = m_pages.GetCount();
714 size_t button_count = m_buttons.GetCount();
715
716 // create off-screen bitmap
717 bmp.Create(m_rect.GetWidth(), m_rect.GetHeight());
718 dc.SelectObject(bmp);
719
720
721 // find out if size of tabs is larger than can be
722 // afforded on screen
723 int total_width = 0;
724 int visible_width = 0;
725 for (i = 0; i < page_count; ++i)
726 {
727 wxAuiNotebookPage& page = m_pages.Item(i);
728
729 // determine if a close button is on this tab
730 bool close_button = false;
731 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
732 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
733 {
734 close_button = true;
735 }
736
737
738 int x_extent = 0;
739 wxSize size = m_art->GetTabSize(&dc,
740 page.caption,
741 page.active,
742 close_button ?
743 wxAUI_BUTTON_STATE_NORMAL :
744 wxAUI_BUTTON_STATE_HIDDEN,
745 &x_extent);
746
747 if (i+1 < page_count)
748 total_width += x_extent;
749 else
750 total_width += size.x;
751
752 if (i >= m_tab_offset)
753 {
754 if (i+1 < page_count)
755 visible_width += x_extent;
756 else
757 visible_width += size.x;
758 }
759 }
760
761 if (total_width > m_rect.GetWidth() - 20 || m_tab_offset != 0)
762 {
763 // show left/right buttons
764 for (i = 0; i < button_count; ++i)
765 {
766 wxAuiTabContainerButton& button = m_buttons.Item(i);
767 if (button.id == wxAUI_BUTTON_LEFT ||
768 button.id == wxAUI_BUTTON_RIGHT)
769 {
770 button.cur_state &= ~wxAUI_BUTTON_STATE_HIDDEN;
771 }
772 }
773 }
774 else
775 {
776 // hide left/right buttons
777 for (i = 0; i < button_count; ++i)
778 {
779 wxAuiTabContainerButton& button = m_buttons.Item(i);
780 if (button.id == wxAUI_BUTTON_LEFT ||
781 button.id == wxAUI_BUTTON_RIGHT)
782 {
783 button.cur_state |= wxAUI_BUTTON_STATE_HIDDEN;
784 }
785 }
786 }
787
788 // determine whether left button should be enabled
789 for (i = 0; i < button_count; ++i)
790 {
791 wxAuiTabContainerButton& button = m_buttons.Item(i);
792 if (button.id == wxAUI_BUTTON_LEFT)
793 {
794 if (m_tab_offset == 0)
795 button.cur_state |= wxAUI_BUTTON_STATE_DISABLED;
796 else
797 button.cur_state &= ~wxAUI_BUTTON_STATE_DISABLED;
798 }
799 if (button.id == wxAUI_BUTTON_RIGHT)
800 {
801 if (visible_width < m_rect.GetWidth() - ((int)button_count*16))
802 button.cur_state |= wxAUI_BUTTON_STATE_DISABLED;
803 else
804 button.cur_state &= ~wxAUI_BUTTON_STATE_DISABLED;
805 }
806 }
807
808
809
810 // draw background
811 m_art->DrawBackground(&dc, m_rect);
812
813 // draw buttons
814 int left_buttons_width = 0;
815 int right_buttons_width = 0;
816
817 int offset = 0;
818
819 // draw the buttons on the right side
820 offset = m_rect.x + m_rect.width;
821 for (i = 0; i < button_count; ++i)
822 {
823 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
824
825 if (button.location != wxRIGHT)
826 continue;
827 if (button.cur_state & wxAUI_BUTTON_STATE_HIDDEN)
828 continue;
829
830 wxRect button_rect = m_rect;
831 button_rect.SetY(1);
832 button_rect.SetWidth(offset);
833
834 m_art->DrawButton(&dc,
835 button_rect,
836 button.id,
837 button.cur_state,
838 wxRIGHT,
839 wxNullBitmap,
840 &button.rect);
841
842 offset -= button.rect.GetWidth();
843 right_buttons_width += button.rect.GetWidth();
844 }
845
846
847
848 offset = 0;
849
850 // draw the buttons on the left side
851
852 for (i = 0; i < button_count; ++i)
853 {
854 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
855
856 if (button.location != wxLEFT)
857 continue;
858 if (button.cur_state & wxAUI_BUTTON_STATE_HIDDEN)
859 continue;
860
861 wxRect button_rect(offset, 1, 1000, m_rect.height);
862
863 m_art->DrawButton(&dc,
864 button_rect,
865 button.id,
866 button.cur_state,
867 wxLEFT,
868 wxNullBitmap,
869 &button.rect);
870
871 offset += button.rect.GetWidth();
872 left_buttons_width += button.rect.GetWidth();
873 }
874
875 offset = left_buttons_width;
876
877 // set a clipping region to the tabs don't draw over the buttons
878 dc.SetClippingRegion(left_buttons_width, 0,
879 m_rect.GetWidth() - right_buttons_width - left_buttons_width - 2,
880 m_rect.GetHeight());
881
882
883
884 // prepare the tab-close-button array
885 while (m_tab_close_buttons.GetCount() < page_count)
886 {
887 wxAuiTabContainerButton tempbtn;
888 tempbtn.id = wxAUI_BUTTON_CLOSE;
889 tempbtn.location = wxCENTER;
890 tempbtn.cur_state = wxAUI_BUTTON_STATE_HIDDEN;
891 m_tab_close_buttons.Add(tempbtn);
892 }
893
894 for (i = 0; i < m_tab_offset; ++i)
895 {
896 // buttons before the tab offset must be set to hidden
897 m_tab_close_buttons.Item(i).cur_state = wxAUI_BUTTON_STATE_HIDDEN;
898 }
899
900
901 // draw the tabs
902
903 size_t active = 999;
904 int active_offset = 0;
905
906 int x_extent = 0;
907 wxRect rect = m_rect;
908 rect.y = 0;
909 rect.width = 1000;
910 rect.height = m_rect.height;
911
912 for (i = m_tab_offset; i < page_count; ++i)
913 {
914 wxAuiNotebookPage& page = m_pages.Item(i);
915 wxAuiTabContainerButton& tab_button = m_tab_close_buttons.Item(i);
916
917 // determine if a close button is on this tab
918 bool close_button = false;
919 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
920 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
921 {
922 close_button = true;
923 if (tab_button.cur_state == wxAUI_BUTTON_STATE_HIDDEN)
924 {
925 tab_button.id = wxAUI_BUTTON_CLOSE;
926 tab_button.cur_state = wxAUI_BUTTON_STATE_NORMAL;
927 tab_button.location = wxCENTER;
928 }
929 }
930 else
931 {
932 tab_button.cur_state = wxAUI_BUTTON_STATE_HIDDEN;
933 }
934
935 rect.x = offset;
936
937 m_art->DrawTab(&dc,
938 rect,
939 page.caption,
940 page.active,
941 tab_button.cur_state,
942 &page.rect,
943 &tab_button.rect,
944 &x_extent);
945
946 if (page.active)
947 {
948 active = i;
949 active_offset = offset;
950 }
951
952 offset += x_extent;
953 }
954
955 // draw the active tab again so it stands in the foreground
956 if (active >= m_tab_offset && active < m_pages.GetCount())
957 {
958 wxAuiNotebookPage& page = m_pages.Item(active);
959
960 wxAuiTabContainerButton& tab_button = m_tab_close_buttons.Item(active);
961
962 // determine if a close button is on this tab
963 bool close_button = false;
964 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
965 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
966 {
967 close_button = true;
968 }
969
970 rect.x = active_offset;
971 m_art->DrawTab(&dc,
972 rect,
973 page.caption,
974 page.active,
975 tab_button.cur_state,
976 &page.rect,
977 &tab_button.rect,
978 &x_extent);
979 }
980
981 dc.DestroyClippingRegion();
982
983 raw_dc->Blit(m_rect.x, m_rect.y,
984 m_rect.GetWidth(), m_rect.GetHeight(),
985 &dc, 0, 0);
986 }
987
988
989 // TabHitTest() tests if a tab was hit, passing the window pointer
990 // back if that condition was fulfilled. The function returns
991 // true if a tab was hit, otherwise false
992 bool wxAuiTabContainer::TabHitTest(int x, int y, wxWindow** hit) const
993 {
994 if (!m_rect.Contains(x,y))
995 return false;
996
997 wxAuiTabContainerButton* btn = NULL;
998 if (ButtonHitTest(x, y, &btn))
999 {
1000 if (m_buttons.Index(*btn) != wxNOT_FOUND)
1001 return false;
1002 }
1003
1004 size_t i, page_count = m_pages.GetCount();
1005
1006 for (i = m_tab_offset; i < page_count; ++i)
1007 {
1008 wxAuiNotebookPage& page = m_pages.Item(i);
1009 if (page.rect.Contains(x,y))
1010 {
1011 if (hit)
1012 *hit = page.window;
1013 return true;
1014 }
1015 }
1016
1017 return false;
1018 }
1019
1020 // ButtonHitTest() tests if a button was hit. The function returns
1021 // true if a button was hit, otherwise false
1022 bool wxAuiTabContainer::ButtonHitTest(int x, int y,
1023 wxAuiTabContainerButton** hit) const
1024 {
1025 if (!m_rect.Contains(x,y))
1026 return false;
1027
1028 size_t i, button_count;
1029
1030
1031 button_count = m_buttons.GetCount();
1032 for (i = 0; i < button_count; ++i)
1033 {
1034 wxAuiTabContainerButton& button = m_buttons.Item(i);
1035 if (button.rect.Contains(x,y))
1036 {
1037 if (hit)
1038 *hit = &button;
1039 return true;
1040 }
1041 }
1042
1043 button_count = m_tab_close_buttons.GetCount();
1044 for (i = 0; i < button_count; ++i)
1045 {
1046 wxAuiTabContainerButton& button = m_tab_close_buttons.Item(i);
1047 if (button.rect.Contains(x,y))
1048 {
1049 if (hit)
1050 *hit = &button;
1051 return true;
1052 }
1053 }
1054
1055 return false;
1056 }
1057
1058
1059
1060 // the utility function ShowWnd() is the same as show,
1061 // except it handles wxAuiMDIChildFrame windows as well,
1062 // as the Show() method on this class is "unplugged"
1063 static void ShowWnd(wxWindow* wnd, bool show)
1064 {
1065 if (wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
1066 {
1067 wxAuiMDIChildFrame* cf = (wxAuiMDIChildFrame*)wnd;
1068 cf->DoShow(show);
1069 }
1070 else
1071 {
1072 wnd->Show(show);
1073 }
1074 }
1075
1076
1077 // DoShowHide() this function shows the active window, then
1078 // hides all of the other windows (in that order)
1079 void wxAuiTabContainer::DoShowHide()
1080 {
1081 wxAuiNotebookPageArray& pages = GetPages();
1082 size_t i, page_count = pages.GetCount();
1083
1084 // show new active page first
1085 for (i = 0; i < page_count; ++i)
1086 {
1087 wxAuiNotebookPage& page = pages.Item(i);
1088 if (page.active)
1089 {
1090 ShowWnd(page.window, true);
1091 break;
1092 }
1093 }
1094
1095 // hide all other pages
1096 for (i = 0; i < page_count; ++i)
1097 {
1098 wxAuiNotebookPage& page = pages.Item(i);
1099 ShowWnd(page.window, page.active);
1100 }
1101 }
1102
1103
1104
1105
1106
1107
1108 // -- wxAuiTabCtrl class implementation --
1109
1110
1111
1112 BEGIN_EVENT_TABLE(wxAuiTabCtrl, wxControl)
1113 EVT_PAINT(wxAuiTabCtrl::OnPaint)
1114 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground)
1115 EVT_SIZE(wxAuiTabCtrl::OnSize)
1116 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown)
1117 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp)
1118 EVT_MOTION(wxAuiTabCtrl::OnMotion)
1119 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow)
1120 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton)
1121 END_EVENT_TABLE()
1122
1123
1124 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow* parent,
1125 wxWindowID id,
1126 const wxPoint& pos,
1127 const wxSize& size,
1128 long style) : wxControl(parent, id, pos, size, style)
1129 {
1130 m_click_pt = wxDefaultPosition;
1131 m_is_dragging = false;
1132 m_hover_button = NULL;
1133 }
1134
1135 wxAuiTabCtrl::~wxAuiTabCtrl()
1136 {
1137 }
1138
1139 void wxAuiTabCtrl::OnPaint(wxPaintEvent&)
1140 {
1141 wxPaintDC dc(this);
1142
1143 dc.SetFont(GetFont());
1144
1145 if (GetPageCount() > 0)
1146 Render(&dc);
1147 }
1148
1149 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
1150 {
1151 }
1152
1153 void wxAuiTabCtrl::OnSize(wxSizeEvent& evt)
1154 {
1155 wxSize s = evt.GetSize();
1156 wxRect r(0, 0, s.GetWidth(), s.GetHeight());
1157 SetRect(r);
1158 }
1159
1160 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt)
1161 {
1162 CaptureMouse();
1163 m_click_pt = wxDefaultPosition;
1164 m_is_dragging = false;
1165 m_click_tab = NULL;
1166
1167 wxWindow* wnd;
1168 if (TabHitTest(evt.m_x, evt.m_y, &wnd))
1169 {
1170 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1171 e.SetSelection(GetIdxFromWindow(wnd));
1172 e.SetOldSelection(GetActivePage());
1173 e.SetEventObject(this);
1174 GetEventHandler()->ProcessEvent(e);
1175
1176 m_click_pt.x = evt.m_x;
1177 m_click_pt.y = evt.m_y;
1178 m_click_tab = wnd;
1179 }
1180
1181 if (m_hover_button)
1182 {
1183 m_hover_button->cur_state = wxAUI_BUTTON_STATE_PRESSED;
1184 Refresh();
1185 Update();
1186 }
1187 }
1188
1189 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent&)
1190 {
1191 if (GetCapture() == this)
1192 ReleaseMouse();
1193
1194 if (m_is_dragging)
1195 {
1196 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, m_windowId);
1197 evt.SetSelection(GetIdxFromWindow(m_click_tab));
1198 evt.SetOldSelection(evt.GetSelection());
1199 evt.SetEventObject(this);
1200 GetEventHandler()->ProcessEvent(evt);
1201 return;
1202 }
1203
1204 if (m_hover_button)
1205 {
1206 m_hover_button->cur_state = wxAUI_BUTTON_STATE_HOVER;
1207 Refresh();
1208 Update();
1209
1210 if (!(m_hover_button->cur_state & wxAUI_BUTTON_STATE_DISABLED))
1211 {
1212 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_windowId);
1213 evt.SetInt(m_hover_button->id);
1214 evt.SetEventObject(this);
1215 GetEventHandler()->ProcessEvent(evt);
1216 }
1217 }
1218
1219 m_click_pt = wxDefaultPosition;
1220 m_is_dragging = false;
1221 m_click_tab = NULL;
1222 }
1223
1224 void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt)
1225 {
1226 wxPoint pos = evt.GetPosition();
1227
1228 // check if the mouse is hovering above a button
1229 wxAuiTabContainerButton* button;
1230 if (ButtonHitTest(pos.x, pos.y, &button))
1231 {
1232 if (m_hover_button && button != m_hover_button)
1233 {
1234 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
1235 m_hover_button = NULL;
1236 Refresh();
1237 Update();
1238 }
1239
1240 if (button->cur_state != wxAUI_BUTTON_STATE_HOVER)
1241 {
1242 button->cur_state = wxAUI_BUTTON_STATE_HOVER;
1243 Refresh();
1244 Update();
1245 m_hover_button = button;
1246 return;
1247 }
1248 }
1249 else
1250 {
1251 if (m_hover_button)
1252 {
1253 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
1254 m_hover_button = NULL;
1255 Refresh();
1256 Update();
1257 }
1258 }
1259
1260
1261 if (!evt.LeftIsDown() || m_click_pt == wxDefaultPosition)
1262 return;
1263
1264 if (m_is_dragging)
1265 {
1266 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, m_windowId);
1267 evt.SetSelection(GetIdxFromWindow(m_click_tab));
1268 evt.SetOldSelection(evt.GetSelection());
1269 evt.SetEventObject(this);
1270 GetEventHandler()->ProcessEvent(evt);
1271 return;
1272 }
1273
1274
1275 int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
1276 int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
1277
1278 if (abs(pos.x - m_click_pt.x) > drag_x_threshold ||
1279 abs(pos.y - m_click_pt.y) > drag_y_threshold)
1280 {
1281 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, m_windowId);
1282 evt.SetSelection(GetIdxFromWindow(m_click_tab));
1283 evt.SetOldSelection(evt.GetSelection());
1284 evt.SetEventObject(this);
1285 GetEventHandler()->ProcessEvent(evt);
1286
1287 m_is_dragging = true;
1288 }
1289 }
1290
1291 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event))
1292 {
1293 if (m_hover_button)
1294 {
1295 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
1296 m_hover_button = NULL;
1297 Refresh();
1298 Update();
1299 }
1300 }
1301
1302 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent& event)
1303 {
1304 int button = event.GetInt();
1305
1306 if (button == wxAUI_BUTTON_LEFT || button == wxAUI_BUTTON_RIGHT)
1307 {
1308 if (button == wxAUI_BUTTON_LEFT)
1309 {
1310 if (GetTabOffset() > 0)
1311 {
1312 SetTabOffset(GetTabOffset()-1);
1313 Refresh();
1314 Update();
1315 }
1316 }
1317 else
1318 {
1319 SetTabOffset(GetTabOffset()+1);
1320 Refresh();
1321 Update();
1322 }
1323 }
1324 else
1325 {
1326 event.Skip();
1327 }
1328 }
1329
1330 // wxTabFrame is an interesting case. It's important that all child pages
1331 // of the multi-notebook control are all actually children of that control
1332 // (and not grandchildren). wxTabFrame facilitates this. There is one
1333 // instance of wxTabFrame for each tab control inside the multi-notebook.
1334 // It's important to know that wxTabFrame is not a real window, but it merely
1335 // used to capture the dimensions/positioning of the internal tab control and
1336 // it's managed page windows
1337
1338 class wxTabFrame : public wxWindow
1339 {
1340 public:
1341
1342 wxTabFrame()
1343 {
1344 m_tabs = NULL;
1345 m_rect = wxRect(0,0,200,200);
1346 m_tab_ctrl_height = 20;
1347 }
1348
1349 void SetTabCtrlHeight(int h)
1350 {
1351 m_tab_ctrl_height = h;
1352 }
1353
1354 void DoSetSize(int x, int y,
1355 int width, int height,
1356 int WXUNUSED(sizeFlags = wxSIZE_AUTO))
1357 {
1358 m_rect = wxRect(x, y, width, height);
1359 DoSizing();
1360 }
1361
1362 void DoGetClientSize(int* x, int* y) const
1363 {
1364 *x = m_rect.width;
1365 *y = m_rect.height;
1366 }
1367
1368 bool Show( bool WXUNUSED(show = true) ) { return false; }
1369
1370 void DoSizing()
1371 {
1372 if (!m_tabs)
1373 return;
1374
1375 int tab_height = wxMin(m_rect.height, m_tab_ctrl_height);
1376 m_tab_rect = wxRect(m_rect.x, m_rect.y, m_rect.width, tab_height);
1377 m_tabs->SetSize(m_rect.x, m_rect.y, m_rect.width, tab_height);
1378 m_tabs->SetRect(wxRect(0, 0, m_rect.width, tab_height));
1379 m_tabs->Refresh();
1380 m_tabs->Update();
1381
1382 wxAuiNotebookPageArray& pages = m_tabs->GetPages();
1383 size_t i, page_count = pages.GetCount();
1384
1385 for (i = 0; i < page_count; ++i)
1386 {
1387 wxAuiNotebookPage& page = pages.Item(i);
1388 page.window->SetSize(m_rect.x, m_rect.y+tab_height, m_rect.width, m_rect.height-tab_height);
1389
1390 if (page.window->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
1391 {
1392 wxAuiMDIChildFrame* wnd = (wxAuiMDIChildFrame*)page.window;
1393 wnd->ApplyMDIChildFrameRect();
1394 }
1395 }
1396 }
1397
1398 void DoGetSize(int* x, int* y) const
1399 {
1400 if (x)
1401 *x = m_rect.GetWidth();
1402 if (y)
1403 *y = m_rect.GetHeight();
1404 }
1405
1406 void Update()
1407 {
1408 // does nothing
1409 }
1410
1411 public:
1412
1413 wxRect m_rect;
1414 wxRect m_tab_rect;
1415 wxAuiTabCtrl* m_tabs;
1416 int m_tab_ctrl_height;
1417 };
1418
1419
1420
1421
1422
1423 // -- wxAuiNotebook class implementation --
1424
1425 BEGIN_EVENT_TABLE(wxAuiNotebook, wxControl)
1426 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
1427 //EVT_SIZE(wxAuiNotebook::OnSize)
1428 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
1429 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus)
1430 EVT_COMMAND_RANGE(10000, 10100,
1431 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING,
1432 wxAuiNotebook::OnTabClicked)
1433 EVT_COMMAND_RANGE(10000, 10100,
1434 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG,
1435 wxAuiNotebook::OnTabBeginDrag)
1436 EVT_COMMAND_RANGE(10000, 10100,
1437 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG,
1438 wxAuiNotebook::OnTabEndDrag)
1439 EVT_COMMAND_RANGE(10000, 10100,
1440 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION,
1441 wxAuiNotebook::OnTabDragMotion)
1442 EVT_COMMAND_RANGE(10000, 10100,
1443 wxEVT_COMMAND_AUINOTEBOOK_BUTTON,
1444 wxAuiNotebook::OnTabButton)
1445 END_EVENT_TABLE()
1446
1447 wxAuiNotebook::wxAuiNotebook()
1448 {
1449 m_curpage = -1;
1450 m_tab_id_counter = 10000;
1451 m_dummy_wnd = NULL;
1452 m_tab_ctrl_height = 20;
1453 }
1454
1455 wxAuiNotebook::wxAuiNotebook(wxWindow *parent,
1456 wxWindowID id,
1457 const wxPoint& pos,
1458 const wxSize& size,
1459 long style) : wxControl(parent, id, pos, size, style)
1460 {
1461 InitNotebook(style);
1462 }
1463
1464 bool wxAuiNotebook::Create(wxWindow* parent,
1465 wxWindowID id,
1466 const wxPoint& pos,
1467 const wxSize& size,
1468 long style)
1469 {
1470 if (!wxControl::Create(parent, id, pos, size, style))
1471 return false;
1472
1473 InitNotebook(style);
1474
1475 return true;
1476 }
1477
1478 // InitNotebook() contains common initialization
1479 // code called by all constructors
1480 void wxAuiNotebook::InitNotebook(long style)
1481 {
1482 m_curpage = -1;
1483 m_tab_id_counter = 10000;
1484 m_dummy_wnd = NULL;
1485 m_tab_ctrl_height = 20;
1486 m_flags = (unsigned int)style;
1487
1488 m_normal_font = *wxNORMAL_FONT;
1489 m_selected_font = *wxNORMAL_FONT;
1490 m_selected_font.SetWeight(wxBOLD);
1491
1492 // choose a default for the tab height
1493 m_tab_ctrl_height = m_tabs.GetArtProvider()->GetBestTabCtrlSize(this);
1494
1495 m_dummy_wnd = new wxWindow(this, wxID_ANY, wxPoint(0,0), wxSize(0,0));
1496 m_dummy_wnd->SetSize(200, 200);
1497 m_dummy_wnd->Show(false);
1498
1499 m_mgr.SetManagedWindow(this);
1500
1501 m_mgr.AddPane(m_dummy_wnd,
1502 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
1503
1504 m_mgr.Update();
1505 }
1506
1507 wxAuiNotebook::~wxAuiNotebook()
1508 {
1509 m_mgr.UnInit();
1510 }
1511
1512 void wxAuiNotebook::SetArtProvider(wxAuiTabArt* art)
1513 {
1514 m_tabs.SetArtProvider(art);
1515 }
1516
1517 wxAuiTabArt* wxAuiNotebook::GetArtProvider()
1518 {
1519 return m_tabs.GetArtProvider();
1520 }
1521
1522 void wxAuiNotebook::SetWindowStyleFlag(long style)
1523 {
1524 wxControl::SetWindowStyleFlag(style);
1525
1526 m_flags = (unsigned int)style;
1527
1528 // if the control is already initialized
1529 if (m_mgr.GetManagedWindow() == (wxWindow*)this)
1530 {
1531 // let all of the tab children know about the new style
1532
1533 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1534 size_t i, pane_count = all_panes.GetCount();
1535 for (i = 0; i < pane_count; ++i)
1536 {
1537 wxAuiPaneInfo& pane = all_panes.Item(i);
1538 if (pane.name == wxT("dummy"))
1539 continue;
1540 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
1541 tabctrl->SetFlags(m_flags);
1542 tabctrl->Refresh();
1543 tabctrl->Update();
1544 }
1545 }
1546 }
1547
1548
1549 bool wxAuiNotebook::AddPage(wxWindow* page,
1550 const wxString& caption,
1551 bool select,
1552 const wxBitmap& bitmap)
1553 {
1554 return InsertPage(GetPageCount(), page, caption, select, bitmap);
1555 }
1556
1557 bool wxAuiNotebook::InsertPage(size_t page_idx,
1558 wxWindow* page,
1559 const wxString& caption,
1560 bool select,
1561 const wxBitmap& bitmap)
1562 {
1563 wxAuiNotebookPage info;
1564 info.window = page;
1565 info.caption = caption;
1566 info.bitmap = bitmap;
1567 info.active = false;
1568
1569 // if there are currently no tabs, the first added
1570 // tab must be active
1571 if (m_tabs.GetPageCount() == 0)
1572 info.active = true;
1573
1574 m_tabs.InsertPage(page, info, page_idx);
1575
1576 wxAuiTabCtrl* active_tabctrl = GetActiveTabCtrl();
1577 if (page_idx >= active_tabctrl->GetPageCount())
1578 active_tabctrl->AddPage(page, info);
1579 else
1580 active_tabctrl->InsertPage(page, info, page_idx);
1581
1582 DoSizing();
1583 active_tabctrl->DoShowHide();
1584
1585 if (select)
1586 {
1587 int idx = m_tabs.GetIdxFromWindow(page);
1588 wxASSERT_MSG(idx != -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
1589
1590 SetSelection(idx);
1591 }
1592
1593 return true;
1594 }
1595
1596
1597 // DeletePage() removes a tab from the multi-notebook,
1598 // and destroys the window as well
1599 bool wxAuiNotebook::DeletePage(size_t page_idx)
1600 {
1601 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
1602 wxWindow* new_active = NULL;
1603
1604 // find out which onscreen tab ctrl owns this tab
1605 wxAuiTabCtrl* ctrl;
1606 int ctrl_idx;
1607 if (!FindTab(wnd, &ctrl, &ctrl_idx))
1608 return false;
1609
1610 // find a new page and set it as active
1611 int new_idx = ctrl_idx+1;
1612 if (new_idx >= (int)ctrl->GetPageCount())
1613 new_idx = ctrl_idx-1;
1614
1615 if (new_idx >= 0 && new_idx < (int)ctrl->GetPageCount())
1616 {
1617 new_active = ctrl->GetWindowFromIdx(new_idx);
1618 }
1619 else
1620 {
1621 // set the active page to the first page that
1622 // isn't the one being deleted
1623 size_t i, page_count = m_tabs.GetPageCount();
1624 for (i = 0; i < page_count; ++i)
1625 {
1626 wxWindow* w = m_tabs.GetWindowFromIdx(i);
1627 if (wnd != w)
1628 {
1629 new_active = m_tabs.GetWindowFromIdx(i);
1630 break;
1631 }
1632 }
1633 }
1634
1635 // remove the tab from main catalog
1636 if (!m_tabs.RemovePage(wnd))
1637 return false;
1638
1639 // remove the tab from the onscreen tab ctrl
1640 ctrl->RemovePage(wnd);
1641
1642 // actually destroy the window now
1643 if (wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
1644 {
1645 // delete the child frame with pending delete, as is
1646 // customary with frame windows
1647 if (!wxPendingDelete.Member(wnd))
1648 wxPendingDelete.Append(wnd);
1649 }
1650 else
1651 {
1652 wnd->Destroy();
1653 }
1654
1655 RemoveEmptyTabFrames();
1656
1657 // set new active pane
1658 if (new_active)
1659 {
1660 m_curpage = -1;
1661 SetSelection(m_tabs.GetIdxFromWindow(new_active));
1662 }
1663
1664 return true;
1665 }
1666
1667
1668
1669 // RemovePage() removes a tab from the multi-notebook,
1670 // but does not destroy the window
1671 bool wxAuiNotebook::RemovePage(size_t page_idx)
1672 {
1673 // remove the tab from our own catalog
1674 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
1675 if (!m_tabs.RemovePage(wnd))
1676 return false;
1677
1678 // remove the tab from the onscreen tab ctrl
1679 wxAuiTabCtrl* ctrl;
1680 int ctrl_idx;
1681 if (FindTab(wnd, &ctrl, &ctrl_idx))
1682 {
1683 ctrl->RemovePage(wnd);
1684 return true;
1685 }
1686
1687 return false;
1688 }
1689
1690 // SetPageText() changes the tab caption of the specified page
1691 bool wxAuiNotebook::SetPageText(size_t page_idx, const wxString& text)
1692 {
1693 if (page_idx >= m_tabs.GetPageCount())
1694 return false;
1695
1696 // update our own tab catalog
1697 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
1698 page_info.caption = text;
1699
1700 // update what's on screen
1701 wxAuiTabCtrl* ctrl;
1702 int ctrl_idx;
1703 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
1704 {
1705 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
1706 info.caption = text;
1707 ctrl->Refresh();
1708 ctrl->Update();
1709 }
1710
1711 return true;
1712 }
1713
1714 // GetSelection() returns the index of the currently active page
1715 int wxAuiNotebook::GetSelection() const
1716 {
1717 return m_curpage;
1718 }
1719
1720 // SetSelection() sets the currently active page
1721 size_t wxAuiNotebook::SetSelection(size_t new_page)
1722 {
1723 wxWindow* wnd = m_tabs.GetWindowFromIdx(new_page);
1724 if (!wnd)
1725 return m_curpage;
1726
1727 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1728 evt.SetSelection(new_page);
1729 evt.SetOldSelection(m_curpage);
1730 evt.SetEventObject(this);
1731 if (!GetEventHandler()->ProcessEvent(evt) || evt.IsAllowed())
1732 {
1733 // program allows the page change
1734 evt.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED);
1735 (void)GetEventHandler()->ProcessEvent(evt);
1736
1737
1738
1739 wxAuiTabCtrl* ctrl;
1740 int ctrl_idx;
1741 if (FindTab(wnd, &ctrl, &ctrl_idx))
1742 {
1743 m_tabs.SetActivePage(wnd);
1744
1745 ctrl->SetActivePage(ctrl_idx);
1746 DoSizing();
1747 ctrl->DoShowHide();
1748
1749 int old_curpage = m_curpage;
1750 m_curpage = new_page;
1751
1752
1753 // set fonts
1754 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1755 size_t i, pane_count = all_panes.GetCount();
1756 for (i = 0; i < pane_count; ++i)
1757 {
1758 wxAuiPaneInfo& pane = all_panes.Item(i);
1759 if (pane.name == wxT("dummy"))
1760 continue;
1761 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
1762 if (tabctrl != ctrl)
1763 tabctrl->SetSelectedFont(m_normal_font);
1764 else
1765 tabctrl->SetSelectedFont(m_selected_font);
1766 tabctrl->Refresh();
1767 }
1768
1769 wnd->SetFocus();
1770
1771 return old_curpage;
1772 }
1773 }
1774
1775 return m_curpage;
1776 }
1777
1778 // GetPageCount() returns the total number of
1779 // pages managed by the multi-notebook
1780 size_t wxAuiNotebook::GetPageCount() const
1781 {
1782 return m_tabs.GetPageCount();
1783 }
1784
1785 // GetPage() returns the wxWindow pointer of the
1786 // specified page
1787 wxWindow* wxAuiNotebook::GetPage(size_t page_idx) const
1788 {
1789 wxASSERT(page_idx < m_tabs.GetPageCount());
1790
1791 return m_tabs.GetWindowFromIdx(page_idx);
1792 }
1793
1794 // DoSizing() performs all sizing operations in each tab control
1795 void wxAuiNotebook::DoSizing()
1796 {
1797 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1798 size_t i, pane_count = all_panes.GetCount();
1799 for (i = 0; i < pane_count; ++i)
1800 {
1801 if (all_panes.Item(i).name == wxT("dummy"))
1802 continue;
1803
1804 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1805 tabframe->DoSizing();
1806 }
1807 }
1808
1809 // GetActiveTabCtrl() returns the active tab control. It is
1810 // called to determine which control gets new windows being added
1811 wxAuiTabCtrl* wxAuiNotebook::GetActiveTabCtrl()
1812 {
1813 if (m_curpage >= 0 && m_curpage < (int)m_tabs.GetPageCount())
1814 {
1815 wxAuiTabCtrl* ctrl;
1816 int idx;
1817
1818 // find the tab ctrl with the current page
1819 if (FindTab(m_tabs.GetPage(m_curpage).window,
1820 &ctrl, &idx))
1821 {
1822 return ctrl;
1823 }
1824 }
1825
1826 // no current page, just find the first tab ctrl
1827 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1828 size_t i, pane_count = all_panes.GetCount();
1829 for (i = 0; i < pane_count; ++i)
1830 {
1831 if (all_panes.Item(i).name == wxT("dummy"))
1832 continue;
1833
1834 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1835 return tabframe->m_tabs;
1836 }
1837
1838 // If there is no tabframe at all, create one
1839 wxTabFrame* tabframe = new wxTabFrame;
1840 tabframe->SetTabCtrlHeight(m_tab_ctrl_height);
1841 tabframe->m_tabs = new wxAuiTabCtrl(this,
1842 m_tab_id_counter++,
1843 wxDefaultPosition,
1844 wxDefaultSize,
1845 wxNO_BORDER);
1846 tabframe->m_tabs->SetFlags(m_flags);
1847 m_mgr.AddPane(tabframe,
1848 wxAuiPaneInfo().Center().CaptionVisible(false));
1849
1850 m_mgr.Update();
1851
1852 return tabframe->m_tabs;
1853 }
1854
1855 // FindTab() finds the tab control that currently contains the window as well
1856 // as the index of the window in the tab control. It returns true if the
1857 // window was found, otherwise false.
1858 bool wxAuiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx)
1859 {
1860 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1861 size_t i, pane_count = all_panes.GetCount();
1862 for (i = 0; i < pane_count; ++i)
1863 {
1864 if (all_panes.Item(i).name == wxT("dummy"))
1865 continue;
1866
1867 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1868
1869 int page_idx = tabframe->m_tabs->GetIdxFromWindow(page);
1870 if (page_idx != -1)
1871 {
1872 *ctrl = tabframe->m_tabs;
1873 *idx = page_idx;
1874 return true;
1875 }
1876 }
1877
1878 return false;
1879 }
1880
1881
1882 void wxAuiNotebook::OnEraseBackground(wxEraseEvent&)
1883 {
1884 }
1885
1886 void wxAuiNotebook::OnSize(wxSizeEvent&)
1887 {
1888 }
1889
1890 void wxAuiNotebook::OnTabClicked(wxCommandEvent& command_evt)
1891 {
1892 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1893
1894 wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject();
1895 wxASSERT(ctrl != NULL);
1896
1897 wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection());
1898 wxASSERT(wnd != NULL);
1899
1900 int idx = m_tabs.GetIdxFromWindow(wnd);
1901 wxASSERT(idx != -1);
1902
1903 SetSelection(idx);
1904 }
1905
1906 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent&)
1907 {
1908 m_last_drag_x = 0;
1909 }
1910
1911 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent& evt)
1912 {
1913 wxPoint screen_pt = ::wxGetMousePosition();
1914 wxPoint client_pt = ScreenToClient(screen_pt);
1915 wxPoint zero(0,0);
1916
1917 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1918
1919 wxAuiTabCtrl* dest_tabs = GetTabCtrlFromPoint(client_pt);
1920 if (dest_tabs == src_tabs)
1921 {
1922 if (src_tabs)
1923 {
1924 src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
1925 }
1926
1927 // always hide the hint for inner-tabctrl drag
1928 m_mgr.HideHint();
1929
1930 // if tab moving is not allowed, leave
1931 if (!(m_flags & wxAUI_NB_TAB_MOVE))
1932 {
1933 return;
1934 }
1935
1936 wxPoint pt = dest_tabs->ScreenToClient(screen_pt);
1937 wxWindow* dest_location_tab;
1938
1939 // this is an inner-tab drag/reposition
1940 if (dest_tabs->TabHitTest(pt.x, pt.y, &dest_location_tab))
1941 {
1942 int src_idx = evt.GetSelection();
1943 int dest_idx = dest_tabs->GetIdxFromWindow(dest_location_tab);
1944
1945 // prevent jumpy drag
1946 if ((src_idx == dest_idx) || dest_idx == -1 ||
1947 (src_idx > dest_idx && m_last_drag_x <= pt.x) ||
1948 (src_idx < dest_idx && m_last_drag_x >= pt.x))
1949 {
1950 m_last_drag_x = pt.x;
1951 return;
1952 }
1953
1954
1955 wxWindow* src_tab = dest_tabs->GetWindowFromIdx(src_idx);
1956 dest_tabs->MovePage(src_tab, dest_idx);
1957 dest_tabs->SetActivePage((size_t)dest_idx);
1958 dest_tabs->DoShowHide();
1959 dest_tabs->Refresh();
1960 m_last_drag_x = pt.x;
1961
1962 }
1963
1964 return;
1965 }
1966
1967
1968 // if tab moving is not allowed, leave
1969 if (!(m_flags & wxAUI_NB_TAB_SPLIT))
1970 {
1971 return;
1972 }
1973
1974
1975 if (src_tabs)
1976 {
1977 src_tabs->SetCursor(wxCursor(wxCURSOR_SIZING));
1978 }
1979
1980
1981 if (dest_tabs)
1982 {
1983 wxRect hint_rect = dest_tabs->GetRect();
1984 ClientToScreen(&hint_rect.x, &hint_rect.y);
1985 m_mgr.ShowHint(hint_rect);
1986 }
1987 else
1988 {
1989 m_mgr.DrawHintRect(m_dummy_wnd, client_pt, zero);
1990 }
1991 }
1992
1993
1994
1995 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
1996 {
1997 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1998
1999 m_mgr.HideHint();
2000
2001 // if tab moving is not allowed, leave
2002 if (!(m_flags & wxAUI_NB_TAB_SPLIT))
2003 {
2004 return;
2005 }
2006
2007 // set cursor back to an arrow
2008 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
2009 if (src_tabs)
2010 {
2011 src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
2012 }
2013
2014 // get the mouse position, which will be used to determine the drop point
2015 wxPoint mouse_screen_pt = ::wxGetMousePosition();
2016 wxPoint mouse_client_pt = ScreenToClient(mouse_screen_pt);
2017
2018
2019 // the src tab control is the control that fired this event
2020 wxAuiTabCtrl* dest_tabs = NULL;
2021
2022
2023 // If the pointer is in an existing tab frame, do a tab insert
2024 wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt);
2025 wxTabFrame* tab_frame = (wxTabFrame*)GetTabFrameFromTabCtrl(hit_wnd);
2026 int insert_idx = -1;
2027 if (tab_frame)
2028 {
2029 dest_tabs = tab_frame->m_tabs;
2030
2031 if (dest_tabs == src_tabs)
2032 return;
2033
2034
2035 wxPoint pt = dest_tabs->ScreenToClient(mouse_screen_pt);
2036 wxWindow* target = NULL;
2037 dest_tabs->TabHitTest(pt.x, pt.y, &target);
2038 if (target)
2039 {
2040 insert_idx = dest_tabs->GetIdxFromWindow(target);
2041 }
2042 }
2043 else
2044 {
2045 // If there is no tabframe at all, create one
2046 wxTabFrame* new_tabs = new wxTabFrame;
2047 new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
2048 new_tabs->m_tabs = new wxAuiTabCtrl(this,
2049 m_tab_id_counter++,
2050 wxDefaultPosition,
2051 wxDefaultSize,
2052 wxNO_BORDER);
2053 new_tabs->m_tabs->SetFlags(m_flags);
2054
2055 m_mgr.AddPane(new_tabs,
2056 wxAuiPaneInfo().Bottom().CaptionVisible(false),
2057 mouse_client_pt);
2058 m_mgr.Update();
2059 dest_tabs = new_tabs->m_tabs;
2060 }
2061
2062
2063
2064 // remove the page from the source tabs
2065 wxAuiNotebookPage page_info = src_tabs->GetPage(evt.GetSelection());
2066 page_info.active = false;
2067 src_tabs->RemovePage(page_info.window);
2068 if (src_tabs->GetPageCount() > 0)
2069 {
2070 src_tabs->SetActivePage((size_t)0);
2071 src_tabs->DoShowHide();
2072 src_tabs->Refresh();
2073 }
2074
2075
2076
2077 // add the page to the destination tabs
2078 if (insert_idx == -1)
2079 insert_idx = dest_tabs->GetPageCount();
2080 dest_tabs->InsertPage(page_info.window, page_info, insert_idx);
2081
2082 if (src_tabs->GetPageCount() == 0)
2083 {
2084 RemoveEmptyTabFrames();
2085 }
2086
2087 DoSizing();
2088 dest_tabs->DoShowHide();
2089 dest_tabs->Refresh();
2090
2091 SetSelection(m_tabs.GetIdxFromWindow(page_info.window));
2092 }
2093
2094
2095
2096 wxAuiTabCtrl* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint& pt)
2097 {
2098 // if we've just removed the last tab from the source
2099 // tab set, the remove the tab control completely
2100 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
2101 size_t i, pane_count = all_panes.GetCount();
2102 for (i = 0; i < pane_count; ++i)
2103 {
2104 if (all_panes.Item(i).name == wxT("dummy"))
2105 continue;
2106
2107 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
2108 if (tabframe->m_tab_rect.Contains(pt))
2109 return tabframe->m_tabs;
2110 }
2111
2112 return NULL;
2113 }
2114
2115 wxWindow* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow* tab_ctrl)
2116 {
2117 // if we've just removed the last tab from the source
2118 // tab set, the remove the tab control completely
2119 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
2120 size_t i, pane_count = all_panes.GetCount();
2121 for (i = 0; i < pane_count; ++i)
2122 {
2123 if (all_panes.Item(i).name == wxT("dummy"))
2124 continue;
2125
2126 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
2127 if (tabframe->m_tabs == tab_ctrl)
2128 {
2129 return tabframe;
2130 }
2131 }
2132
2133 return NULL;
2134 }
2135
2136 void wxAuiNotebook::RemoveEmptyTabFrames()
2137 {
2138 // if we've just removed the last tab from the source
2139 // tab set, the remove the tab control completely
2140 wxAuiPaneInfoArray all_panes = m_mgr.GetAllPanes();
2141 size_t i, pane_count = all_panes.GetCount();
2142 for (i = 0; i < pane_count; ++i)
2143 {
2144 if (all_panes.Item(i).name == wxT("dummy"))
2145 continue;
2146
2147 wxTabFrame* tab_frame = (wxTabFrame*)all_panes.Item(i).window;
2148 if (tab_frame->m_tabs->GetPageCount() == 0)
2149 {
2150 m_mgr.DetachPane(tab_frame);
2151
2152 // use pending delete because sometimes during
2153 // window closing, refreshs are pending
2154 if (!wxPendingDelete.Member(tab_frame->m_tabs))
2155 wxPendingDelete.Append(tab_frame->m_tabs);
2156 //tab_frame->m_tabs->Destroy();
2157
2158 delete tab_frame;
2159 }
2160 }
2161
2162
2163 // check to see if there is still a center pane;
2164 // if there isn't, make a frame the center pane
2165 wxAuiPaneInfoArray panes = m_mgr.GetAllPanes();
2166 pane_count = panes.GetCount();
2167 wxWindow* first_good = NULL;
2168 bool center_found = false;
2169 for (i = 0; i < pane_count; ++i)
2170 {
2171 if (panes.Item(i).name == wxT("dummy"))
2172 continue;
2173 if (panes.Item(i).dock_direction == wxAUI_DOCK_CENTRE)
2174 center_found = true;
2175 if (!first_good)
2176 first_good = panes.Item(i).window;
2177 }
2178
2179 if (!center_found && first_good)
2180 {
2181 m_mgr.GetPane(first_good).Centre();
2182 }
2183
2184 m_mgr.Update();
2185 }
2186
2187 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent& evt)
2188 {
2189 int idx = m_tabs.GetIdxFromWindow(evt.GetWindow());
2190 if (idx != -1 && idx != m_curpage)
2191 {
2192 SetSelection(idx);
2193 }
2194 }
2195
2196
2197 void wxAuiNotebook::OnTabButton(wxCommandEvent& command_evt)
2198 {
2199 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
2200 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
2201
2202 int button_id = evt.GetInt();
2203
2204 if (button_id == wxAUI_BUTTON_CLOSE)
2205 {
2206 int selection = tabs->GetActivePage();
2207
2208 if (selection != -1)
2209 {
2210 wxWindow* close_wnd = tabs->GetWindowFromIdx(selection);
2211
2212 if (close_wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
2213 {
2214 close_wnd->Close();
2215 }
2216 else
2217 {
2218 int main_idx = m_tabs.GetIdxFromWindow(close_wnd);
2219 DeletePage(main_idx);
2220 }
2221 }
2222 }
2223 }
2224
2225
2226
2227
2228 #endif // wxUSE_AUI