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