]> git.saurik.com Git - wxWidgets.git/blame - src/aui/auibook.cpp
use CPPUNIT_ASSERT_MESSAGE() to show which test exactly failed; use more CPPUNIT_ASSE...
[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"
2613e24d 32#include "wx/menu.h"
4444d148 33
cd05bf23
BW
34#include "wx/arrimpl.cpp"
35WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray)
36WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray)
37
3fd8c988 38DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE)
cd05bf23
BW
39DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING)
40DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED)
41DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON)
42DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG)
43DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG)
44DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION)
5d3aeb0f 45DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND)
cd05bf23
BW
46
47
0ce53f32 48IMPLEMENT_CLASS(wxAuiNotebook, wxControl)
5d3aeb0f 49IMPLEMENT_CLASS(wxAuiTabCtrl, wxControl)
cd05bf23
BW
50IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent, wxEvent)
51
cd05bf23
BW
52
53
cd05bf23
BW
54
55
56// This functions are here for this proof of concept
57// and will be factored out later. See dockart.cpp
58static wxColor StepColour(const wxColor& c, int percent)
59{
60 int r = c.Red(), g = c.Green(), b = c.Blue();
61 return wxColour((unsigned char)wxMin((r*percent)/100,255),
62 (unsigned char)wxMin((g*percent)/100,255),
63 (unsigned char)wxMin((b*percent)/100,255));
64}
65
66// This functions are here for this proof of concept
67// and will be factored out later. See dockart.cpp
68static wxBitmap BitmapFromBits(const unsigned char bits[], int w, int h,
69 const wxColour& color)
70{
71 wxImage img = wxBitmap((const char*)bits, w, h).ConvertToImage();
df00bdf7
RR
72 img.Replace(0,0,0,123,123,123);
73 img.Replace(255,255,255,color.Red(),color.Green(),color.Blue());
cd05bf23
BW
74 img.SetMaskColour(123,123,123);
75 return wxBitmap(img);
76}
77
b0d17f7c
BW
78static void DrawButtons(wxDC& dc,
79 const wxRect& _rect,
80 const wxBitmap& bmp,
81 const wxColour& bkcolour,
82 int button_state)
cd05bf23
BW
83{
84 wxRect rect = _rect;
85
86 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
87 {
88 rect.x++;
89 rect.y++;
90 }
91
92 if (button_state == wxAUI_BUTTON_STATE_HOVER ||
93 button_state == wxAUI_BUTTON_STATE_PRESSED)
94 {
95 dc.SetBrush(wxBrush(StepColour(bkcolour, 120)));
96 dc.SetPen(wxPen(StepColour(bkcolour, 70)));
97
98 // draw the background behind the button
99 dc.DrawRectangle(rect.x, rect.y, 15, 15);
100 }
101
102 // draw the button itself
103 dc.DrawBitmap(bmp, rect.x, rect.y, true);
104}
105
b0d17f7c
BW
106static void IndentPressedBitmap(wxRect* rect, int button_state)
107{
108 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
109 {
110 rect->x++;
111 rect->y++;
112 }
113}
114
115// chops the text so that it fits within |max_size| pixels.
116// Also adds an elipsis if necessary
117
118static wxString ChopText(wxDC& dc, const wxString& text, int max_size)
119{
120 wxCoord x,y;
121
122 // first check if the text fits with no problems
123 dc.GetTextExtent(text, &x, &y);
124 if (x <= max_size)
125 return text;
126
127 size_t i, len = text.Length();
128 size_t last_good_length = 0;
129 for (i = 0; i < len; ++i)
130 {
131 wxString s = text.Left(i);
132 s += wxT("...");
133
134 dc.GetTextExtent(s, &x, &y);
135 if (x > max_size)
136 break;
137
138 last_good_length = i;
139 }
140
141 wxString ret = text.Left(last_good_length);
142 ret += wxT("...");
143 return ret;
144}
145
146
147// -- GUI helper classes and functions --
148
149class wxAuiCommandCapture : public wxEvtHandler
150{
151public:
152
153 wxAuiCommandCapture() { m_last_id = 0; }
154 int GetCommandId() const { return m_last_id; }
155
156 bool ProcessEvent(wxEvent& evt)
157 {
158 if (evt.GetEventType() == wxEVT_COMMAND_MENU_SELECTED)
159 {
160 m_last_id = evt.GetId();
161 return true;
162 }
163
164 if (GetNextHandler())
165 return GetNextHandler()->ProcessEvent(evt);
166
167 return false;
168 }
169
170private:
171 int m_last_id;
172};
173
174
175// -- bitmaps --
176
177#if defined( __WXMAC__ )
178 static unsigned char close_bits[]={
179 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
180 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
181 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
6750264e
BW
182#elif defined( __WXGTK__)
183 static unsigned char close_bits[]={
184 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
185 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
186 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
b0d17f7c
BW
187#else
188 static unsigned char close_bits[]={
8896cb72
BW
189 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
190 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
191 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
b0d17f7c
BW
192#endif
193
194static unsigned char left_bits[] = {
195 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
196 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
197 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
198
199static unsigned char right_bits[] = {
200 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
201 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
202 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
203
204static unsigned char list_bits[] = {
205 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
206 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
207 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
208
209
210
211
212
213
214// -- wxAuiDefaultTabArt class implementation --
215
216wxAuiDefaultTabArt::wxAuiDefaultTabArt()
217{
218 m_normal_font = *wxNORMAL_FONT;
219 m_selected_font = *wxNORMAL_FONT;
220 m_selected_font.SetWeight(wxBOLD);
221 m_measuring_font = m_selected_font;
222
223 m_fixed_tab_width = 100;
2b9aac33 224 m_tab_ctrl_height = 0;
b0d17f7c
BW
225
226 wxColour base_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
227
228 wxColour background_colour = base_colour;
229 wxColour normaltab_colour = base_colour;
230 wxColour selectedtab_colour = base_colour;
231
232 m_bkbrush = wxBrush(background_colour);
233 m_normal_bkbrush = wxBrush(normaltab_colour);
234 m_normal_bkpen = wxPen(normaltab_colour);
235 m_selected_bkbrush = wxBrush(selectedtab_colour);
236 m_selected_bkpen = wxPen(selectedtab_colour);
237
238
239 m_active_close_bmp = BitmapFromBits(close_bits, 16, 16, *wxBLACK);
240 m_disabled_close_bmp = BitmapFromBits(close_bits, 16, 16, wxColour(128,128,128));
241
242 m_active_left_bmp = BitmapFromBits(left_bits, 16, 16, *wxBLACK);
243 m_disabled_left_bmp = BitmapFromBits(left_bits, 16, 16, wxColour(128,128,128));
244
245 m_active_right_bmp = BitmapFromBits(right_bits, 16, 16, *wxBLACK);
246 m_disabled_right_bmp = BitmapFromBits(right_bits, 16, 16, wxColour(128,128,128));
247
248 m_active_windowlist_bmp = BitmapFromBits(list_bits, 16, 16, *wxBLACK);
249 m_disabled_windowlist_bmp = BitmapFromBits(list_bits, 16, 16, wxColour(128,128,128));
250
251 m_flags = 0;
252}
253
254wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
255{
256}
257
258wxAuiTabArt* wxAuiDefaultTabArt::Clone()
259{
260 return static_cast<wxAuiTabArt*>(new wxAuiDefaultTabArt);
261}
262
263void wxAuiDefaultTabArt::SetFlags(unsigned int flags)
264{
265 m_flags = flags;
266}
267
268void wxAuiDefaultTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
269 size_t tab_count)
270{
271 m_fixed_tab_width = 100;
272
69685ee0 273 int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - 4;
b0d17f7c
BW
274 if (tab_count > 0)
275 {
276 m_fixed_tab_width = tot_width/(int)tab_count;
277 }
278
279
280 if (m_fixed_tab_width < 100)
281 m_fixed_tab_width = 100;
282
283 if (m_fixed_tab_width > tot_width/2)
284 m_fixed_tab_width = tot_width/2;
285
286 if (m_fixed_tab_width > 220)
287 m_fixed_tab_width = 220;
2b9aac33
BW
288
289 m_tab_ctrl_height = tab_ctrl_size.y;
b0d17f7c
BW
290}
291
292
293void wxAuiDefaultTabArt::DrawBackground(wxDC& dc,
294 wxWindow* WXUNUSED(wnd),
295 const wxRect& rect)
296{
297 // draw background
298 dc.SetBrush(m_bkbrush);
299 dc.SetPen(*wxTRANSPARENT_PEN);
300 dc.DrawRectangle(-1, -1, rect.GetWidth()+2, rect.GetHeight()+2);
301
302 // draw base lines
303 dc.SetPen(*wxGREY_PEN);
304 dc.DrawLine(0, rect.GetHeight()-4, rect.GetWidth(), rect.GetHeight()-4);
305 dc.DrawLine(0, rect.GetHeight()-1, rect.GetWidth(), rect.GetHeight()-1);
306}
307
308
309// DrawTab() draws an individual tab.
310//
311// dc - output dc
312// in_rect - rectangle the tab should be confined to
313// caption - tab's caption
314// active - whether or not the tab is active
315// out_rect - actual output rectangle
316// x_extent - the advance x; where the next tab should start
317
318void wxAuiDefaultTabArt::DrawTab(wxDC& dc,
319 wxWindow* wnd,
320 const wxRect& in_rect,
321 const wxString& caption_text,
2b9aac33 322 const wxBitmap& bitmap,
b0d17f7c
BW
323 bool active,
324 int close_button_state,
325 wxRect* out_tab_rect,
326 wxRect* out_button_rect,
327 int* x_extent)
328{
329 wxCoord normal_textx, normal_texty;
330 wxCoord selected_textx, selected_texty;
331 wxCoord textx, texty;
332
333 // if the caption is empty, measure some temporary text
334 wxString caption = caption_text;
335 if (caption_text.empty())
336 caption = wxT("Xj");
337
338 dc.SetFont(m_selected_font);
339 dc.GetTextExtent(caption, &selected_textx, &selected_texty);
340
341 dc.SetFont(m_normal_font);
342 dc.GetTextExtent(caption, &normal_textx, &normal_texty);
343
344 // figure out the size of the tab
2b9aac33
BW
345 wxSize tab_size = GetTabSize(dc,
346 wnd,
347 caption,
348 bitmap,
349 active,
350 close_button_state,
351 x_extent);
352
353 wxCoord tab_height = m_tab_ctrl_height - 3;
b0d17f7c
BW
354 wxCoord tab_width = tab_size.x;
355 wxCoord tab_x = in_rect.x;
356 wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
357
358
b965ffff 359 caption = caption_text;
b0d17f7c
BW
360
361 dc.SetClippingRegion(in_rect);
362
363
364
365 // select pen, brush and font for the tab to be drawn
366
367 if (active)
368 {
369 dc.SetPen(m_selected_bkpen);
370 dc.SetBrush(m_selected_bkbrush);
371 dc.SetFont(m_selected_font);
372 textx = selected_textx;
373 texty = selected_texty;
374 }
375 else
376 {
377 dc.SetPen(m_normal_bkpen);
378 dc.SetBrush(m_normal_bkbrush);
379 dc.SetFont(m_normal_font);
380 textx = normal_textx;
381 texty = normal_texty;
382 }
383
384
7c508bca 385 // create points that will make the tab outline
b0d17f7c
BW
386
387 wxPoint points[6];
388 points[0].x = tab_x;
389 points[0].y = tab_y + tab_height - 4;
390 points[1].x = tab_x;
391 points[1].y = tab_y + 2;
392 points[2].x = tab_x + 2;
393 points[2].y = tab_y;
394 points[3].x = tab_x + tab_width - 2;
395 points[3].y = tab_y;
396 points[4].x = tab_x + tab_width;
397 points[4].y = tab_y + 2;
398 points[5].x = tab_x + tab_width;
399 points[5].y = tab_y + tab_height - 4;
400
2b9aac33
BW
401 int drawn_tab_yoff = points[1].y;
402 int drawn_tab_height = points[0].y - points[1].y;
403
b0d17f7c 404
7c508bca 405 // draw gradient background
b0d17f7c 406 if (active)
3904a280 407 {
b0d17f7c
BW
408 wxColour c = m_bkbrush.GetColour();
409 dc.SetPen(wxPen(c));
410
7c508bca 411 int y, last_y = -1;
b0d17f7c
BW
412 for (y = points[0].y; y > points[2].y; --y)
413 {
414 if (y < tab_y+(tab_height*3/5) && y != last_y)
415 {
416 last_y = y;
417 c = StepColour(c, 102);
418 dc.SetPen(wxPen(c));
419 }
420
7c508bca 421 dc.DrawLine(points[0].x+1, y, points[5].x, y);
b0d17f7c
BW
422 }
423 }
424
7c508bca 425 // draw tab outline
b0d17f7c
BW
426 dc.SetPen(*wxGREY_PEN);
427 dc.SetBrush(*wxTRANSPARENT_BRUSH);
428 dc.DrawPolygon(6, points);
7c508bca
BW
429
430 // there are two horizontal grey lines at the bottom of the tab control,
431 // this gets rid of the top one of those lines in the tab control
b0d17f7c
BW
432 if (active)
433 {
434 wxColour c = m_bkbrush.GetColour();
435 dc.SetPen(wxPen(c));
3904a280 436 dc.DrawLine(points[0].x, points[0].y, points[5].x+1, points[5].y);
b0d17f7c
BW
437 }
438
b0d17f7c 439
2b9aac33 440 int text_offset = tab_x + 8;
b0d17f7c 441 int close_button_width = 0;
b0d17f7c
BW
442 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
443 {
444 close_button_width = m_active_close_bmp.GetWidth();
445 }
446
b0d17f7c 447
2b9aac33
BW
448 if (bitmap.IsOk())
449 {
450 int bitmap_offset = tab_x + 8;
451
452 // draw bitmap
453 dc.DrawBitmap(bitmap,
454 bitmap_offset,
455 drawn_tab_yoff + (drawn_tab_height/2) - (bitmap.GetHeight()/2) + 1,
456 true);
457
458 text_offset = bitmap_offset + bitmap.GetWidth();
459 text_offset += 3; // bitmap padding
460 }
461 else
462 {
463 text_offset = tab_x + 8;
464 }
465
b0d17f7c
BW
466
467 wxString draw_text = ChopText(dc,
468 caption,
469 tab_width - (text_offset-tab_x) - close_button_width);
470
471 // draw tab text
472 dc.DrawText(draw_text,
473 text_offset,
2b9aac33 474 drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1);
b0d17f7c
BW
475
476
477
478
479 // draw close button if necessary
480 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
481 {
482 wxBitmap bmp = m_disabled_close_bmp;
483
484 if (close_button_state == wxAUI_BUTTON_STATE_HOVER ||
485 close_button_state == wxAUI_BUTTON_STATE_PRESSED)
486 {
487 bmp = m_active_close_bmp;
488 }
489
490 wxRect rect(tab_x + tab_width - close_button_width - 1,
491 tab_y + (tab_height/2) - (bmp.GetHeight()/2),
492 close_button_width,
493 tab_height);
494 IndentPressedBitmap(&rect, close_button_state);
495 dc.DrawBitmap(bmp, rect.x, rect.y, true);
496
497 *out_button_rect = rect;
498 }
499
500 *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
501
502 dc.DestroyClippingRegion();
503}
504
505int wxAuiDefaultTabArt::GetIndentSize()
506{
507 return 5;
508}
509
510wxSize wxAuiDefaultTabArt::GetTabSize(wxDC& dc,
511 wxWindow* WXUNUSED(wnd),
512 const wxString& caption,
2b9aac33 513 const wxBitmap& bitmap,
b0d17f7c
BW
514 bool WXUNUSED(active),
515 int close_button_state,
516 int* x_extent)
517{
518 wxCoord measured_textx, measured_texty, tmp;
519
520 dc.SetFont(m_measuring_font);
521 dc.GetTextExtent(caption, &measured_textx, &measured_texty);
522
523 dc.GetTextExtent(wxT("ABCDEFXj"), &tmp, &measured_texty);
524
213e64e9 525 // add padding around the text
2b9aac33
BW
526 wxCoord tab_width = measured_textx;
527 wxCoord tab_height = measured_texty;
b0d17f7c 528
2b9aac33 529 // if the close button is showing, add space for it
b0d17f7c 530 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
213e64e9 531 tab_width += m_active_close_bmp.GetWidth() + 3;
b0d17f7c 532
2b9aac33
BW
533 // if there's a bitmap, add space for it
534 if (bitmap.IsOk())
535 {
536 tab_width += bitmap.GetWidth();
537 tab_width += 3; // right side bitmap padding
538 tab_height = wxMax(tab_height, bitmap.GetHeight());
539 }
540
541 // add padding
542 tab_width += 16;
543 tab_height += 10;
b0d17f7c
BW
544
545 if (m_flags & wxAUI_NB_TAB_FIXED_WIDTH)
546 {
547 tab_width = m_fixed_tab_width;
548 }
549
550 *x_extent = tab_width;
551
552 return wxSize(tab_width, tab_height);
553}
554
555
556void wxAuiDefaultTabArt::DrawButton(wxDC& dc,
557 wxWindow* WXUNUSED(wnd),
558 const wxRect& in_rect,
559 int bitmap_id,
560 int button_state,
561 int orientation,
562 const wxBitmap& bitmap_override,
563 wxRect* out_rect)
564{
565 wxBitmap bmp;
566 wxRect rect;
567
568 if (bitmap_override.IsOk())
569 {
570 bmp = bitmap_override;
571 }
572 else
573 {
574 switch (bitmap_id)
575 {
576 case wxAUI_BUTTON_CLOSE:
577 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
578 bmp = m_disabled_close_bmp;
579 else
580 bmp = m_active_close_bmp;
581 break;
582 case wxAUI_BUTTON_LEFT:
583 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
584 bmp = m_disabled_left_bmp;
585 else
586 bmp = m_active_left_bmp;
587 break;
588 case wxAUI_BUTTON_RIGHT:
589 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
590 bmp = m_disabled_right_bmp;
591 else
592 bmp = m_active_right_bmp;
593 break;
594 case wxAUI_BUTTON_WINDOWLIST:
595 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
596 bmp = m_disabled_windowlist_bmp;
597 else
598 bmp = m_active_windowlist_bmp;
599 break;
600 }
601 }
cd05bf23 602
b0d17f7c
BW
603 if (!bmp.IsOk())
604 return;
605
606 rect = in_rect;
607
608 if (orientation == wxLEFT)
609 {
610 rect.SetX(in_rect.x);
611 rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2));
612 rect.SetWidth(bmp.GetWidth());
613 rect.SetHeight(bmp.GetHeight());
614 }
615 else
616 {
617 rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
618 ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
619 bmp.GetWidth(), bmp.GetHeight());
620 }
621
622 IndentPressedBitmap(&rect, button_state);
623 dc.DrawBitmap(bmp, rect.x, rect.y, true);
624
625 *out_rect = rect;
626}
cd05bf23
BW
627
628
b0d17f7c
BW
629int wxAuiDefaultTabArt::ShowWindowList(wxWindow* wnd,
630 const wxArrayString& items,
631 int active_idx)
632{
633 wxMenu menuPopup;
3f69756e 634
b0d17f7c
BW
635 size_t i, count = items.GetCount();
636 for (i = 0; i < count; ++i)
637 {
638 menuPopup.AppendCheckItem(1000+i, items.Item(i));
639 }
640
641 if (active_idx != -1)
642 {
643 menuPopup.Check(1000+active_idx, true);
644 }
645
646 // find out where to put the popup menu of window
647 // items. Subtract 100 for now to center the menu
648 // a bit, until a better mechanism can be implemented
649 wxPoint pt = ::wxGetMousePosition();
650 pt = wnd->ScreenToClient(pt);
651 if (pt.x < 100)
652 pt.x = 0;
653 else
654 pt.x -= 100;
655
656 // find out the screen coordinate at the bottom of the tab ctrl
657 wxRect cli_rect = wnd->GetClientRect();
658 pt.y = cli_rect.y + cli_rect.height;
659
660 wxAuiCommandCapture* cc = new wxAuiCommandCapture;
661 wnd->PushEventHandler(cc);
662 wnd->PopupMenu(&menuPopup, pt);
663 int command = cc->GetCommandId();
664 wnd->PopEventHandler(true);
665
666 if (command >= 1000)
667 return command-1000;
668
669 return -1;
670}
3f69756e 671
2b9aac33
BW
672int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow* wnd,
673 wxAuiNotebookPageArray& pages)
b0d17f7c
BW
674{
675 wxClientDC dc(wnd);
676 dc.SetFont(m_measuring_font);
2b9aac33
BW
677
678 int max_y = 0;
679 size_t i, page_count = pages.GetCount();
680 for (i = 0; i < page_count; ++i)
681 {
682 wxAuiNotebookPage& page = pages.Item(i);
683
684 // we don't use the caption text because we don't
685 // want tab heights to be different in the case
686 // of a very short piece of text on one tab and a very
687 // tall piece of text on another tab
688 int x_ext = 0;
689 wxSize s = GetTabSize(dc,
690 wnd,
691 wxT("ABCDEFGHIj"),
692 page.bitmap,
693 true,
694 wxAUI_BUTTON_STATE_HIDDEN,
695 &x_ext);
696 max_y = wxMax(max_y, s.y);
697 }
698
699 return max_y+2;
b0d17f7c
BW
700}
701
702void wxAuiDefaultTabArt::SetNormalFont(const wxFont& font)
703{
704 m_normal_font = font;
705}
706
707void wxAuiDefaultTabArt::SetSelectedFont(const wxFont& font)
708{
709 m_selected_font = font;
710}
711
712void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont& font)
713{
714 m_measuring_font = font;
715}
716
717
718// -- wxAuiSimpleTabArt class implementation --
719
720wxAuiSimpleTabArt::wxAuiSimpleTabArt()
cd05bf23
BW
721{
722 m_normal_font = *wxNORMAL_FONT;
723 m_selected_font = *wxNORMAL_FONT;
724 m_selected_font.SetWeight(wxBOLD);
725 m_measuring_font = m_selected_font;
4444d148 726
b0d17f7c
BW
727 m_flags = 0;
728 m_fixed_tab_width = 100;
729
cd05bf23 730 wxColour base_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
4444d148 731
cd05bf23
BW
732 wxColour background_colour = StepColour(base_colour, 95);
733 wxColour normaltab_colour = base_colour;
734 wxColour selectedtab_colour = *wxWHITE;
4444d148 735
cd05bf23
BW
736 m_bkbrush = wxBrush(background_colour);
737 m_normal_bkbrush = wxBrush(normaltab_colour);
738 m_normal_bkpen = wxPen(normaltab_colour);
739 m_selected_bkbrush = wxBrush(selectedtab_colour);
740 m_selected_bkpen = wxPen(selectedtab_colour);
4953f8cf 741
4953f8cf
BW
742 m_active_close_bmp = BitmapFromBits(close_bits, 16, 16, *wxBLACK);
743 m_disabled_close_bmp = BitmapFromBits(close_bits, 16, 16, wxColour(128,128,128));
744
745 m_active_left_bmp = BitmapFromBits(left_bits, 16, 16, *wxBLACK);
746 m_disabled_left_bmp = BitmapFromBits(left_bits, 16, 16, wxColour(128,128,128));
747
748 m_active_right_bmp = BitmapFromBits(right_bits, 16, 16, *wxBLACK);
749 m_disabled_right_bmp = BitmapFromBits(right_bits, 16, 16, wxColour(128,128,128));
01372b8f
BW
750
751 m_active_windowlist_bmp = BitmapFromBits(list_bits, 16, 16, *wxBLACK);
752 m_disabled_windowlist_bmp = BitmapFromBits(list_bits, 16, 16, wxColour(128,128,128));
753
cd05bf23
BW
754}
755
b0d17f7c 756wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
488e50ee
BW
757{
758}
759
b0d17f7c
BW
760wxAuiTabArt* wxAuiSimpleTabArt::Clone()
761{
762 return static_cast<wxAuiTabArt*>(new wxAuiSimpleTabArt);
763}
764
765
766void wxAuiSimpleTabArt::SetFlags(unsigned int flags)
767{
768 m_flags = flags;
769}
770
771void wxAuiSimpleTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
772 size_t tab_count)
773{
774 m_fixed_tab_width = 100;
775
69685ee0 776 int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - 4;
b0d17f7c
BW
777 if (tab_count > 0)
778 {
779 m_fixed_tab_width = tot_width/(int)tab_count;
780 }
781
782
783 if (m_fixed_tab_width < 100)
784 m_fixed_tab_width = 100;
785
786 if (m_fixed_tab_width > tot_width/2)
787 m_fixed_tab_width = tot_width/2;
788
789 if (m_fixed_tab_width > 220)
790 m_fixed_tab_width = 220;
791}
792
793void wxAuiSimpleTabArt::DrawBackground(wxDC& dc,
794 wxWindow* WXUNUSED(wnd),
795 const wxRect& rect)
3f69756e
BW
796{
797 // draw background
a6b0e5bd
BW
798 dc.SetBrush(m_bkbrush);
799 dc.SetPen(*wxTRANSPARENT_PEN);
800 dc.DrawRectangle(-1, -1, rect.GetWidth()+2, rect.GetHeight()+2);
3f69756e
BW
801
802 // draw base line
a6b0e5bd
BW
803 dc.SetPen(*wxGREY_PEN);
804 dc.DrawLine(0, rect.GetHeight()-1, rect.GetWidth(), rect.GetHeight()-1);
3f69756e
BW
805}
806
4953f8cf 807
3f69756e
BW
808// DrawTab() draws an individual tab.
809//
810// dc - output dc
811// in_rect - rectangle the tab should be confined to
812// caption - tab's caption
813// active - whether or not the tab is active
814// out_rect - actual output rectangle
815// x_extent - the advance x; where the next tab should start
816
b0d17f7c
BW
817void wxAuiSimpleTabArt::DrawTab(wxDC& dc,
818 wxWindow* wnd,
819 const wxRect& in_rect,
820 const wxString& caption_text,
2b9aac33 821 const wxBitmap& bitmap,
b0d17f7c
BW
822 bool active,
823 int close_button_state,
824 wxRect* out_tab_rect,
825 wxRect* out_button_rect,
826 int* x_extent)
3f69756e
BW
827{
828 wxCoord normal_textx, normal_texty;
829 wxCoord selected_textx, selected_texty;
3f69756e 830 wxCoord textx, texty;
a4c8fc23 831
3f69756e
BW
832 // if the caption is empty, measure some temporary text
833 wxString caption = caption_text;
834 if (caption_text.empty())
835 caption = wxT("Xj");
a4c8fc23 836
a6b0e5bd
BW
837 dc.SetFont(m_selected_font);
838 dc.GetTextExtent(caption, &selected_textx, &selected_texty);
a4c8fc23 839
a6b0e5bd
BW
840 dc.SetFont(m_normal_font);
841 dc.GetTextExtent(caption, &normal_textx, &normal_texty);
a4c8fc23
BW
842
843 // figure out the size of the tab
2b9aac33
BW
844 wxSize tab_size = GetTabSize(dc,
845 wnd,
846 caption,
847 bitmap,
848 active,
849 close_button_state,
850 x_extent);
3f69756e 851
a4c8fc23
BW
852 wxCoord tab_height = tab_size.y;
853 wxCoord tab_width = tab_size.x;
3f69756e
BW
854 wxCoord tab_x = in_rect.x;
855 wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
856
b965ffff
BW
857 caption = caption_text;
858
3f69756e
BW
859 // select pen, brush and font for the tab to be drawn
860
861 if (active)
862 {
a6b0e5bd
BW
863 dc.SetPen(m_selected_bkpen);
864 dc.SetBrush(m_selected_bkbrush);
865 dc.SetFont(m_selected_font);
3f69756e
BW
866 textx = selected_textx;
867 texty = selected_texty;
868 }
869 else
870 {
a6b0e5bd
BW
871 dc.SetPen(m_normal_bkpen);
872 dc.SetBrush(m_normal_bkbrush);
873 dc.SetFont(m_normal_font);
3f69756e
BW
874 textx = normal_textx;
875 texty = normal_texty;
876 }
877
878
879 // -- draw line --
880
881 wxPoint points[7];
882 points[0].x = tab_x;
883 points[0].y = tab_y + tab_height - 1;
884 points[1].x = tab_x + tab_height - 3;
885 points[1].y = tab_y + 2;
886 points[2].x = tab_x + tab_height + 3;
887 points[2].y = tab_y;
888 points[3].x = tab_x + tab_width - 2;
889 points[3].y = tab_y;
890 points[4].x = tab_x + tab_width;
891 points[4].y = tab_y + 2;
892 points[5].x = tab_x + tab_width;
893 points[5].y = tab_y + tab_height - 1;
894 points[6] = points[0];
895
b0d17f7c 896 dc.SetClippingRegion(in_rect);
3f69756e 897
a6b0e5bd 898 dc.DrawPolygon(6, points);
3f69756e 899
a6b0e5bd 900 dc.SetPen(*wxGREY_PEN);
3f69756e 901
a6b0e5bd
BW
902 //dc.DrawLines(active ? 6 : 7, points);
903 dc.DrawLines(7, points);
3f69756e 904
3f69756e 905
702b1c7e
BW
906 int text_offset;
907
908 int close_button_width = 0;
41b76acd 909 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
702b1c7e
BW
910 {
911 close_button_width = m_active_close_bmp.GetWidth();
912 text_offset = tab_x + (tab_height/2) + ((tab_width-close_button_width)/2) - (textx/2);
913 }
914 else
915 {
916 text_offset = tab_x + (tab_height/3) + (tab_width/2) - (textx/2);
917 }
918
b0d17f7c
BW
919 // set minimum text offset
920 if (text_offset < tab_x + tab_height)
921 text_offset = tab_x + tab_height;
922
923 // chop text if necessary
924 wxString draw_text = ChopText(dc,
925 caption,
926 tab_width - (text_offset-tab_x) - close_button_width);
702b1c7e
BW
927
928 // draw tab text
b0d17f7c 929 dc.DrawText(draw_text,
702b1c7e 930 text_offset,
a4c8fc23 931 (tab_y + tab_height)/2 - (texty/2) + 1);
3f69756e 932
702b1c7e
BW
933
934 // draw close button if necessary
41b76acd 935 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
702b1c7e
BW
936 {
937 wxBitmap bmp;
938 if (active)
939 bmp = m_active_close_bmp;
940 else
941 bmp = m_disabled_close_bmp;
942
0b3d6ff9
BW
943 wxRect rect(tab_x + tab_width - close_button_width - 1,
944 tab_y + (tab_height/2) - (bmp.GetHeight()/2) + 1,
945 close_button_width,
946 tab_height - 1);
b0d17f7c 947 DrawButtons(dc, rect, bmp, *wxWHITE, close_button_state);
41b76acd
BW
948
949 *out_button_rect = rect;
702b1c7e
BW
950 }
951
952
41b76acd 953 *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
b0d17f7c
BW
954
955 dc.DestroyClippingRegion();
3f69756e
BW
956}
957
b0d17f7c
BW
958int wxAuiSimpleTabArt::GetIndentSize()
959{
960 return 0;
961}
3f69756e 962
b0d17f7c
BW
963wxSize wxAuiSimpleTabArt::GetTabSize(wxDC& dc,
964 wxWindow* WXUNUSED(wnd),
965 const wxString& caption,
2b9aac33 966 const wxBitmap& WXUNUSED(bitmap),
b0d17f7c
BW
967 bool WXUNUSED(active),
968 int close_button_state,
969 int* x_extent)
4953f8cf
BW
970{
971 wxCoord measured_textx, measured_texty;
972
a6b0e5bd
BW
973 dc.SetFont(m_measuring_font);
974 dc.GetTextExtent(caption, &measured_textx, &measured_texty);
4953f8cf
BW
975
976 wxCoord tab_height = measured_texty + 4;
977 wxCoord tab_width = measured_textx + tab_height + 5;
978
41b76acd 979 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
702b1c7e 980 tab_width += m_active_close_bmp.GetWidth();
b0d17f7c
BW
981
982 if (m_flags & wxAUI_NB_TAB_FIXED_WIDTH)
983 {
984 tab_width = m_fixed_tab_width;
985 }
986
4953f8cf
BW
987 *x_extent = tab_width - (tab_height/2) - 1;
988
989 return wxSize(tab_width, tab_height);
990}
991
992
b0d17f7c
BW
993void wxAuiSimpleTabArt::DrawButton(wxDC& dc,
994 wxWindow* WXUNUSED(wnd),
995 const wxRect& in_rect,
996 int bitmap_id,
997 int button_state,
998 int orientation,
999 const wxBitmap& bitmap_override,
1000 wxRect* out_rect)
4953f8cf
BW
1001{
1002 wxBitmap bmp;
1003 wxRect rect;
1004
1005 if (bitmap_override.IsOk())
1006 {
1007 bmp = bitmap_override;
1008 }
1009 else
1010 {
1011 switch (bitmap_id)
1012 {
1013 case wxAUI_BUTTON_CLOSE:
1014 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1015 bmp = m_disabled_close_bmp;
1016 else
1017 bmp = m_active_close_bmp;
1018 break;
1019 case wxAUI_BUTTON_LEFT:
1020 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1021 bmp = m_disabled_left_bmp;
1022 else
1023 bmp = m_active_left_bmp;
1024 break;
1025 case wxAUI_BUTTON_RIGHT:
1026 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1027 bmp = m_disabled_right_bmp;
1028 else
1029 bmp = m_active_right_bmp;
1030 break;
01372b8f
BW
1031 case wxAUI_BUTTON_WINDOWLIST:
1032 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1033 bmp = m_disabled_windowlist_bmp;
1034 else
1035 bmp = m_active_windowlist_bmp;
1036 break;
4953f8cf
BW
1037 }
1038 }
1039
1040 if (!bmp.IsOk())
1041 return;
1042
1043 rect = in_rect;
1044
1045 if (orientation == wxLEFT)
1046 {
25d7497c
BW
1047 rect.SetX(in_rect.x);
1048 rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2));
4953f8cf
BW
1049 rect.SetWidth(bmp.GetWidth());
1050 rect.SetHeight(bmp.GetHeight());
1051 }
1052 else
1053 {
25d7497c
BW
1054 rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
1055 ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
4953f8cf
BW
1056 bmp.GetWidth(), bmp.GetHeight());
1057 }
1058
1059
b0d17f7c 1060 DrawButtons(dc, rect, bmp, *wxWHITE, button_state);
4953f8cf
BW
1061
1062 *out_rect = rect;
1063}
1064
1065
b0d17f7c
BW
1066int wxAuiSimpleTabArt::ShowWindowList(wxWindow* wnd,
1067 const wxArrayString& items,
1068 int active_idx)
01372b8f
BW
1069{
1070 wxMenu menuPopup;
1071
1072 size_t i, count = items.GetCount();
1073 for (i = 0; i < count; ++i)
1074 {
1075 menuPopup.AppendCheckItem(1000+i, items.Item(i));
1076 }
1077
1078 if (active_idx != -1)
1079 {
1080 menuPopup.Check(1000+active_idx, true);
1081 }
1082
1083 // find out where to put the popup menu of window
1084 // items. Subtract 100 for now to center the menu
1085 // a bit, until a better mechanism can be implemented
1086 wxPoint pt = ::wxGetMousePosition();
1087 pt = wnd->ScreenToClient(pt);
1088 if (pt.x < 100)
1089 pt.x = 0;
1090 else
1091 pt.x -= 100;
1092
1093 // find out the screen coordinate at the bottom of the tab ctrl
1094 wxRect cli_rect = wnd->GetClientRect();
1095 pt.y = cli_rect.y + cli_rect.height;
1096
1097 wxAuiCommandCapture* cc = new wxAuiCommandCapture;
1098 wnd->PushEventHandler(cc);
1099 wnd->PopupMenu(&menuPopup, pt);
1100 int command = cc->GetCommandId();
1101 wnd->PopEventHandler(true);
1102
1103 if (command >= 1000)
1104 return command-1000;
1105
1106 return -1;
1107}
1108
2b9aac33
BW
1109int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow* wnd,
1110 wxAuiNotebookPageArray& WXUNUSED(pages))
a4c8fc23
BW
1111{
1112 wxClientDC dc(wnd);
1113 dc.SetFont(m_measuring_font);
1114 int x_ext = 0;
a6b0e5bd 1115 wxSize s = GetTabSize(dc,
01372b8f
BW
1116 wnd,
1117 wxT("ABCDEFGHIj"),
2b9aac33 1118 wxNullBitmap,
01372b8f
BW
1119 true,
1120 wxAUI_BUTTON_STATE_HIDDEN,
1121 &x_ext);
a4c8fc23
BW
1122 return s.y+3;
1123}
4953f8cf 1124
b0d17f7c 1125void wxAuiSimpleTabArt::SetNormalFont(const wxFont& font)
3f69756e
BW
1126{
1127 m_normal_font = font;
1128}
1129
b0d17f7c 1130void wxAuiSimpleTabArt::SetSelectedFont(const wxFont& font)
3f69756e
BW
1131{
1132 m_selected_font = font;
1133}
1134
b0d17f7c 1135void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont& font)
3f69756e
BW
1136{
1137 m_measuring_font = font;
1138}
1139
1140
1141
1142
3f69756e
BW
1143// -- wxAuiTabContainer class implementation --
1144
1145
1146// wxAuiTabContainer is a class which contains information about each
1147// tab. It also can render an entire tab control to a specified DC.
1148// It's not a window class itself, because this code will be used by
1149// the wxFrameMananger, where it is disadvantageous to have separate
1150// windows for each tab control in the case of "docked tabs"
1151
1152// A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1153// which can be used as a tab control in the normal sense.
1154
1155
1156wxAuiTabContainer::wxAuiTabContainer()
1157{
4953f8cf 1158 m_tab_offset = 0;
702b1c7e 1159 m_flags = 0;
a3a5df9d 1160 m_art = new wxAuiDefaultTabArt;
4953f8cf
BW
1161
1162 AddButton(wxAUI_BUTTON_LEFT, wxLEFT);
01372b8f
BW
1163 AddButton(wxAUI_BUTTON_RIGHT, wxRIGHT);
1164 AddButton(wxAUI_BUTTON_WINDOWLIST, wxRIGHT);
4953f8cf 1165 AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT);
3f69756e
BW
1166}
1167
fe498448
BW
1168wxAuiTabContainer::~wxAuiTabContainer()
1169{
3f69756e
BW
1170 delete m_art;
1171}
1172
a3a5df9d 1173void wxAuiTabContainer::SetArtProvider(wxAuiTabArt* art)
3f69756e
BW
1174{
1175 delete m_art;
1176 m_art = art;
b0d17f7c
BW
1177
1178 if (m_art)
1179 {
1180 m_art->SetFlags(m_flags);
1181 }
3f69756e
BW
1182}
1183
a3a5df9d 1184wxAuiTabArt* wxAuiTabContainer::GetArtProvider()
3f69756e
BW
1185{
1186 return m_art;
fe498448
BW
1187}
1188
702b1c7e
BW
1189void wxAuiTabContainer::SetFlags(unsigned int flags)
1190{
1191 m_flags = flags;
41b76acd
BW
1192
1193 // check for new close button settings
01372b8f
BW
1194 RemoveButton(wxAUI_BUTTON_LEFT);
1195 RemoveButton(wxAUI_BUTTON_RIGHT);
1196 RemoveButton(wxAUI_BUTTON_WINDOWLIST);
41b76acd 1197 RemoveButton(wxAUI_BUTTON_CLOSE);
01372b8f
BW
1198
1199
1200 if (flags & wxAUI_NB_SCROLL_BUTTONS)
1201 {
1202 AddButton(wxAUI_BUTTON_LEFT, wxLEFT);
1203 AddButton(wxAUI_BUTTON_RIGHT, wxRIGHT);
1204 }
1205
1206 if (flags & wxAUI_NB_WINDOWLIST_BUTTON)
1207 {
1208 AddButton(wxAUI_BUTTON_WINDOWLIST, wxRIGHT);
1209 }
1210
41b76acd
BW
1211 if (flags & wxAUI_NB_CLOSE_BUTTON)
1212 {
1213 AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT);
1214 }
b0d17f7c
BW
1215
1216 if (m_art)
1217 {
1218 m_art->SetFlags(m_flags);
1219 }
702b1c7e
BW
1220}
1221
1222unsigned int wxAuiTabContainer::GetFlags() const
1223{
1224 return m_flags;
1225}
1226
1227
cd05bf23
BW
1228void wxAuiTabContainer::SetNormalFont(const wxFont& font)
1229{
3f69756e 1230 m_art->SetNormalFont(font);
cd05bf23
BW
1231}
1232
1233void wxAuiTabContainer::SetSelectedFont(const wxFont& font)
1234{
3f69756e 1235 m_art->SetSelectedFont(font);
cd05bf23
BW
1236}
1237
1238void wxAuiTabContainer::SetMeasuringFont(const wxFont& font)
1239{
3f69756e 1240 m_art->SetMeasuringFont(font);
cd05bf23
BW
1241}
1242
1243void wxAuiTabContainer::SetRect(const wxRect& rect)
1244{
1245 m_rect = rect;
b0d17f7c
BW
1246
1247 if (m_art)
1248 {
1249 m_art->SetSizingInfo(rect.GetSize(), m_pages.GetCount());
1250 }
cd05bf23
BW
1251}
1252
1253bool wxAuiTabContainer::AddPage(wxWindow* page,
1254 const wxAuiNotebookPage& info)
1255{
1256 wxAuiNotebookPage page_info;
1257 page_info = info;
1258 page_info.window = page;
4444d148 1259
cd05bf23
BW
1260 m_pages.Add(page_info);
1261
b0d17f7c
BW
1262 // let the art provider know how many pages we have
1263 if (m_art)
1264 {
1265 m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
1266 }
1267
cd05bf23
BW
1268 return true;
1269}
1270
1271bool wxAuiTabContainer::InsertPage(wxWindow* page,
1272 const wxAuiNotebookPage& info,
1273 size_t idx)
1274{
1275 wxAuiNotebookPage page_info;
1276 page_info = info;
1277 page_info.window = page;
4444d148 1278
cd05bf23
BW
1279 if (idx >= m_pages.GetCount())
1280 m_pages.Add(page_info);
1281 else
1282 m_pages.Insert(page_info, idx);
1283
b0d17f7c
BW
1284 // let the art provider know how many pages we have
1285 if (m_art)
1286 {
1287 m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
1288 }
1289
cd05bf23
BW
1290 return true;
1291}
1292
2fadbbfd
BW
1293bool wxAuiTabContainer::MovePage(wxWindow* page,
1294 size_t new_idx)
1295{
1296 int idx = GetIdxFromWindow(page);
1297 if (idx == -1)
1298 return false;
1299
1300 // get page entry, make a copy of it
1301 wxAuiNotebookPage p = GetPage(idx);
1302
1303 // remove old page entry
1304 RemovePage(page);
1305
1306 // insert page where it should be
1307 InsertPage(page, p, new_idx);
1308
1309 return true;
1310}
1311
cd05bf23
BW
1312bool wxAuiTabContainer::RemovePage(wxWindow* wnd)
1313{
1314 size_t i, page_count = m_pages.GetCount();
1315 for (i = 0; i < page_count; ++i)
1316 {
1317 wxAuiNotebookPage& page = m_pages.Item(i);
1318 if (page.window == wnd)
1319 {
1320 m_pages.RemoveAt(i);
b0d17f7c
BW
1321
1322 // let the art provider know how many pages we have
1323 if (m_art)
1324 {
1325 m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
1326 }
1327
cd05bf23
BW
1328 return true;
1329 }
1330 }
4444d148 1331
cd05bf23
BW
1332 return false;
1333}
1334
1335bool wxAuiTabContainer::SetActivePage(wxWindow* wnd)
1336{
1337 bool found = false;
4444d148 1338
cd05bf23
BW
1339 size_t i, page_count = m_pages.GetCount();
1340 for (i = 0; i < page_count; ++i)
1341 {
1342 wxAuiNotebookPage& page = m_pages.Item(i);
1343 if (page.window == wnd)
1344 {
1345 page.active = true;
1346 found = true;
1347 }
1348 else
1349 {
1350 page.active = false;
1351 }
1352 }
4444d148 1353
cd05bf23
BW
1354 return found;
1355}
1356
1357void wxAuiTabContainer::SetNoneActive()
1358{
1359 size_t i, page_count = m_pages.GetCount();
1360 for (i = 0; i < page_count; ++i)
1361 {
1362 wxAuiNotebookPage& page = m_pages.Item(i);
1363 page.active = false;
1364 }
1365}
1366
1367bool wxAuiTabContainer::SetActivePage(size_t page)
1368{
1369 if (page >= m_pages.GetCount())
1370 return false;
4444d148 1371
cd05bf23
BW
1372 return SetActivePage(m_pages.Item(page).window);
1373}
4444d148 1374
cd05bf23
BW
1375int wxAuiTabContainer::GetActivePage() const
1376{
1377 size_t i, page_count = m_pages.GetCount();
1378 for (i = 0; i < page_count; ++i)
1379 {
1380 wxAuiNotebookPage& page = m_pages.Item(i);
1381 if (page.active)
1382 return i;
1383 }
4444d148 1384
cd05bf23
BW
1385 return -1;
1386}
1387
1388wxWindow* wxAuiTabContainer::GetWindowFromIdx(size_t idx) const
1389{
1390 if (idx >= m_pages.GetCount())
1391 return NULL;
4444d148 1392
cd05bf23
BW
1393 return m_pages[idx].window;
1394}
1395
1396int wxAuiTabContainer::GetIdxFromWindow(wxWindow* wnd) const
1397{
1398 size_t i, page_count = m_pages.GetCount();
1399 for (i = 0; i < page_count; ++i)
1400 {
1401 wxAuiNotebookPage& page = m_pages.Item(i);
1402 if (page.window == wnd)
1403 return i;
1404 }
1405 return -1;
1406}
1407
1408wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx)
1409{
1410 wxASSERT_MSG(idx < m_pages.GetCount(), wxT("Invalid Page index"));
1411
1412 return m_pages[idx];
1413}
1414
1415wxAuiNotebookPageArray& wxAuiTabContainer::GetPages()
1416{
1417 return m_pages;
1418}
1419
1420size_t wxAuiTabContainer::GetPageCount() const
1421{
1422 return m_pages.GetCount();
1423}
1424
4953f8cf
BW
1425void wxAuiTabContainer::AddButton(int id,
1426 int location,
1427 const wxBitmap& normal_bitmap,
1428 const wxBitmap& disabled_bitmap)
cd05bf23
BW
1429{
1430 wxAuiTabContainerButton button;
1431 button.id = id;
4953f8cf
BW
1432 button.bitmap = normal_bitmap;
1433 button.dis_bitmap = disabled_bitmap;
b6418695 1434 button.location = location;
cd05bf23 1435 button.cur_state = wxAUI_BUTTON_STATE_NORMAL;
4444d148 1436
cd05bf23
BW
1437 m_buttons.Add(button);
1438}
1439
41b76acd
BW
1440void wxAuiTabContainer::RemoveButton(int id)
1441{
1442 size_t i, button_count = m_buttons.GetCount();
1443
1444 for (i = 0; i < button_count; ++i)
1445 {
1446 if (m_buttons.Item(i).id == id)
1447 {
1448 m_buttons.RemoveAt(i);
1449 return;
1450 }
1451 }
1452}
1453
1454
1455
4953f8cf
BW
1456size_t wxAuiTabContainer::GetTabOffset() const
1457{
1458 return m_tab_offset;
1459}
cd05bf23 1460
4953f8cf
BW
1461void wxAuiTabContainer::SetTabOffset(size_t offset)
1462{
1463 m_tab_offset = offset;
1464}
cd05bf23 1465
b0d17f7c
BW
1466
1467
1468
cd05bf23
BW
1469// Render() renders the tab catalog to the specified DC
1470// It is a virtual function and can be overridden to
1471// provide custom drawing capabilities
01372b8f 1472void wxAuiTabContainer::Render(wxDC* raw_dc, wxWindow* wnd)
4444d148 1473{
a9eeb510
BW
1474 if (!raw_dc || !raw_dc->IsOk())
1475 return;
1476
cd05bf23
BW
1477 wxMemoryDC dc;
1478 wxBitmap bmp;
4953f8cf
BW
1479 size_t i;
1480 size_t page_count = m_pages.GetCount();
1481 size_t button_count = m_buttons.GetCount();
1482
1483 // create off-screen bitmap
cd05bf23
BW
1484 bmp.Create(m_rect.GetWidth(), m_rect.GetHeight());
1485 dc.SelectObject(bmp);
4444d148 1486
a9eeb510
BW
1487 if (!dc.IsOk())
1488 return;
4953f8cf
BW
1489
1490 // find out if size of tabs is larger than can be
1491 // afforded on screen
1492 int total_width = 0;
25d7497c 1493 int visible_width = 0;
4953f8cf
BW
1494 for (i = 0; i < page_count; ++i)
1495 {
1496 wxAuiNotebookPage& page = m_pages.Item(i);
702b1c7e
BW
1497
1498 // determine if a close button is on this tab
1499 bool close_button = false;
1500 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
1501 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
1502 {
1503 close_button = true;
1504 }
1505
1506
4953f8cf 1507 int x_extent = 0;
a6b0e5bd 1508 wxSize size = m_art->GetTabSize(dc,
01372b8f 1509 wnd,
41b76acd 1510 page.caption,
2b9aac33 1511 page.bitmap,
41b76acd
BW
1512 page.active,
1513 close_button ?
1514 wxAUI_BUTTON_STATE_NORMAL :
1515 wxAUI_BUTTON_STATE_HIDDEN,
1516 &x_extent);
25d7497c 1517
4953f8cf
BW
1518 if (i+1 < page_count)
1519 total_width += x_extent;
1520 else
1521 total_width += size.x;
25d7497c
BW
1522
1523 if (i >= m_tab_offset)
1524 {
1525 if (i+1 < page_count)
1526 visible_width += x_extent;
1527 else
1528 visible_width += size.x;
1529 }
4953f8cf
BW
1530 }
1531
b0d17f7c 1532 if (total_width > m_rect.GetWidth() || m_tab_offset != 0)
4953f8cf
BW
1533 {
1534 // show left/right buttons
1535 for (i = 0; i < button_count; ++i)
1536 {
1537 wxAuiTabContainerButton& button = m_buttons.Item(i);
1538 if (button.id == wxAUI_BUTTON_LEFT ||
1539 button.id == wxAUI_BUTTON_RIGHT)
1540 {
1541 button.cur_state &= ~wxAUI_BUTTON_STATE_HIDDEN;
1542 }
1543 }
1544 }
1545 else
1546 {
1547 // hide left/right buttons
1548 for (i = 0; i < button_count; ++i)
1549 {
1550 wxAuiTabContainerButton& button = m_buttons.Item(i);
1551 if (button.id == wxAUI_BUTTON_LEFT ||
1552 button.id == wxAUI_BUTTON_RIGHT)
1553 {
1554 button.cur_state |= wxAUI_BUTTON_STATE_HIDDEN;
1555 }
1556 }
1557 }
1558
25d7497c
BW
1559 // determine whether left button should be enabled
1560 for (i = 0; i < button_count; ++i)
1561 {
1562 wxAuiTabContainerButton& button = m_buttons.Item(i);
1563 if (button.id == wxAUI_BUTTON_LEFT)
1564 {
1565 if (m_tab_offset == 0)
1566 button.cur_state |= wxAUI_BUTTON_STATE_DISABLED;
1567 else
1568 button.cur_state &= ~wxAUI_BUTTON_STATE_DISABLED;
1569 }
1570 if (button.id == wxAUI_BUTTON_RIGHT)
1571 {
1572 if (visible_width < m_rect.GetWidth() - ((int)button_count*16))
1573 button.cur_state |= wxAUI_BUTTON_STATE_DISABLED;
1574 else
1575 button.cur_state &= ~wxAUI_BUTTON_STATE_DISABLED;
1576 }
1577 }
1578
4953f8cf
BW
1579
1580
1581 // draw background
a6b0e5bd 1582 m_art->DrawBackground(dc, wnd, m_rect);
4444d148 1583
4953f8cf
BW
1584 // draw buttons
1585 int left_buttons_width = 0;
1586 int right_buttons_width = 0;
1587
cd05bf23 1588 int offset = 0;
b6418695
BW
1589
1590 // draw the buttons on the right side
1591 offset = m_rect.x + m_rect.width;
b6418695
BW
1592 for (i = 0; i < button_count; ++i)
1593 {
1594 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
1595
1596 if (button.location != wxRIGHT)
1597 continue;
4953f8cf
BW
1598 if (button.cur_state & wxAUI_BUTTON_STATE_HIDDEN)
1599 continue;
1600
1601 wxRect button_rect = m_rect;
1602 button_rect.SetY(1);
1603 button_rect.SetWidth(offset);
1604
a6b0e5bd 1605 m_art->DrawButton(dc,
01372b8f 1606 wnd,
4953f8cf
BW
1607 button_rect,
1608 button.id,
1609 button.cur_state,
1610 wxRIGHT,
1611 wxNullBitmap,
1612 &button.rect);
1613
1614 offset -= button.rect.GetWidth();
1615 right_buttons_width += button.rect.GetWidth();
b6418695
BW
1616 }
1617
1618
1619
1620 offset = 0;
1621
1622 // draw the buttons on the left side
1623
1624 for (i = 0; i < button_count; ++i)
1625 {
1626 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
1627
1628 if (button.location != wxLEFT)
1629 continue;
4953f8cf
BW
1630 if (button.cur_state & wxAUI_BUTTON_STATE_HIDDEN)
1631 continue;
1632
1633 wxRect button_rect(offset, 1, 1000, m_rect.height);
1634
a6b0e5bd 1635 m_art->DrawButton(dc,
01372b8f 1636 wnd,
4953f8cf
BW
1637 button_rect,
1638 button.id,
1639 button.cur_state,
1640 wxLEFT,
1641 wxNullBitmap,
1642 &button.rect);
1643
1644 offset += button.rect.GetWidth();
1645 left_buttons_width += button.rect.GetWidth();
b6418695
BW
1646 }
1647
4953f8cf
BW
1648 offset = left_buttons_width;
1649
b0d17f7c
BW
1650 if (offset == 0)
1651 offset += m_art->GetIndentSize();
41b76acd
BW
1652
1653 // prepare the tab-close-button array
4abf84fb
BW
1654 while (m_tab_close_buttons.GetCount() > page_count)
1655 m_tab_close_buttons.RemoveAt(m_tab_close_buttons.GetCount()-1);
1656
41b76acd
BW
1657 while (m_tab_close_buttons.GetCount() < page_count)
1658 {
1659 wxAuiTabContainerButton tempbtn;
1660 tempbtn.id = wxAUI_BUTTON_CLOSE;
1661 tempbtn.location = wxCENTER;
1662 tempbtn.cur_state = wxAUI_BUTTON_STATE_HIDDEN;
1663 m_tab_close_buttons.Add(tempbtn);
1664 }
1665
4abf84fb
BW
1666
1667 // buttons before the tab offset must be set to hidden
41b76acd
BW
1668 for (i = 0; i < m_tab_offset; ++i)
1669 {
41b76acd
BW
1670 m_tab_close_buttons.Item(i).cur_state = wxAUI_BUTTON_STATE_HIDDEN;
1671 }
1672
4953f8cf 1673
b6418695 1674 // draw the tabs
cd05bf23
BW
1675
1676 size_t active = 999;
1677 int active_offset = 0;
b0d17f7c 1678 wxRect active_rect;
4444d148 1679
cd05bf23
BW
1680 int x_extent = 0;
1681 wxRect rect = m_rect;
1682 rect.y = 0;
cd05bf23 1683 rect.height = m_rect.height;
4444d148 1684
4953f8cf 1685 for (i = m_tab_offset; i < page_count; ++i)
cd05bf23
BW
1686 {
1687 wxAuiNotebookPage& page = m_pages.Item(i);
41b76acd 1688 wxAuiTabContainerButton& tab_button = m_tab_close_buttons.Item(i);
4444d148 1689
702b1c7e
BW
1690 // determine if a close button is on this tab
1691 bool close_button = false;
1692 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
1693 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
1694 {
1695 close_button = true;
41b76acd
BW
1696 if (tab_button.cur_state == wxAUI_BUTTON_STATE_HIDDEN)
1697 {
1698 tab_button.id = wxAUI_BUTTON_CLOSE;
1699 tab_button.cur_state = wxAUI_BUTTON_STATE_NORMAL;
1700 tab_button.location = wxCENTER;
1701 }
1702 }
1703 else
1704 {
1705 tab_button.cur_state = wxAUI_BUTTON_STATE_HIDDEN;
702b1c7e
BW
1706 }
1707
cd05bf23 1708 rect.x = offset;
b0d17f7c
BW
1709 rect.width = m_rect.width - right_buttons_width - offset - 2;
1710
47b6bebb
BW
1711 if (rect.width <= 0)
1712 break;
1713
a6b0e5bd 1714 m_art->DrawTab(dc,
01372b8f
BW
1715 wnd,
1716 rect,
1717 page.caption,
2b9aac33 1718 page.bitmap,
01372b8f
BW
1719 page.active,
1720 tab_button.cur_state,
1721 &page.rect,
1722 &tab_button.rect,
1723 &x_extent);
4444d148 1724
cd05bf23
BW
1725 if (page.active)
1726 {
1727 active = i;
1728 active_offset = offset;
b0d17f7c 1729 active_rect = rect;
cd05bf23 1730 }
41b76acd 1731
cd05bf23
BW
1732 offset += x_extent;
1733 }
4444d148 1734
4abf84fb
BW
1735
1736 // make sure to deactivate buttons which are off the screen to the right
1737 for (++i; i < m_tab_close_buttons.GetCount(); ++i)
1738 {
1739 m_tab_close_buttons.Item(i).cur_state = wxAUI_BUTTON_STATE_HIDDEN;
1740 }
1741
1742
cd05bf23 1743 // draw the active tab again so it stands in the foreground
4953f8cf 1744 if (active >= m_tab_offset && active < m_pages.GetCount())
cd05bf23
BW
1745 {
1746 wxAuiNotebookPage& page = m_pages.Item(active);
1747
41b76acd
BW
1748 wxAuiTabContainerButton& tab_button = m_tab_close_buttons.Item(active);
1749
702b1c7e
BW
1750 // determine if a close button is on this tab
1751 bool close_button = false;
1752 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
1753 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
1754 {
1755 close_button = true;
1756 }
1757
cd05bf23 1758 rect.x = active_offset;
a6b0e5bd 1759 m_art->DrawTab(dc,
01372b8f 1760 wnd,
b0d17f7c 1761 active_rect,
01372b8f 1762 page.caption,
2b9aac33 1763 page.bitmap,
01372b8f
BW
1764 page.active,
1765 tab_button.cur_state,
1766 &page.rect,
1767 &tab_button.rect,
1768 &x_extent);
cd05bf23 1769 }
4444d148 1770
4953f8cf
BW
1771
1772 raw_dc->Blit(m_rect.x, m_rect.y,
1773 m_rect.GetWidth(), m_rect.GetHeight(),
1774 &dc, 0, 0);
cd05bf23
BW
1775}
1776
1777
1778// TabHitTest() tests if a tab was hit, passing the window pointer
1779// back if that condition was fulfilled. The function returns
1780// true if a tab was hit, otherwise false
1781bool wxAuiTabContainer::TabHitTest(int x, int y, wxWindow** hit) const
1782{
22a35096 1783 if (!m_rect.Contains(x,y))
cd05bf23 1784 return false;
4953f8cf 1785
41b76acd
BW
1786 wxAuiTabContainerButton* btn = NULL;
1787 if (ButtonHitTest(x, y, &btn))
1788 {
1789 if (m_buttons.Index(*btn) != wxNOT_FOUND)
1790 return false;
1791 }
4444d148 1792
cd05bf23 1793 size_t i, page_count = m_pages.GetCount();
4444d148 1794
4953f8cf 1795 for (i = m_tab_offset; i < page_count; ++i)
cd05bf23
BW
1796 {
1797 wxAuiNotebookPage& page = m_pages.Item(i);
22a35096 1798 if (page.rect.Contains(x,y))
cd05bf23 1799 {
4953f8cf
BW
1800 if (hit)
1801 *hit = page.window;
cd05bf23
BW
1802 return true;
1803 }
1804 }
4444d148 1805
cd05bf23
BW
1806 return false;
1807}
1808
1809// ButtonHitTest() tests if a button was hit. The function returns
1810// true if a button was hit, otherwise false
1811bool wxAuiTabContainer::ButtonHitTest(int x, int y,
1812 wxAuiTabContainerButton** hit) const
1813{
22a35096 1814 if (!m_rect.Contains(x,y))
cd05bf23 1815 return false;
4444d148 1816
41b76acd
BW
1817 size_t i, button_count;
1818
1819
1820 button_count = m_buttons.GetCount();
cd05bf23
BW
1821 for (i = 0; i < button_count; ++i)
1822 {
1823 wxAuiTabContainerButton& button = m_buttons.Item(i);
9b405ab3
BW
1824 if (button.rect.Contains(x,y) &&
1825 !(button.cur_state & (wxAUI_BUTTON_STATE_HIDDEN |
1826 wxAUI_BUTTON_STATE_DISABLED)))
cd05bf23 1827 {
4953f8cf
BW
1828 if (hit)
1829 *hit = &button;
cd05bf23
BW
1830 return true;
1831 }
1832 }
41b76acd
BW
1833
1834 button_count = m_tab_close_buttons.GetCount();
1835 for (i = 0; i < button_count; ++i)
1836 {
1837 wxAuiTabContainerButton& button = m_tab_close_buttons.Item(i);
9b405ab3
BW
1838 if (button.rect.Contains(x,y) &&
1839 !(button.cur_state & (wxAUI_BUTTON_STATE_HIDDEN |
1840 wxAUI_BUTTON_STATE_DISABLED)))
41b76acd
BW
1841 {
1842 if (hit)
1843 *hit = &button;
1844 return true;
1845 }
1846 }
1847
cd05bf23
BW
1848 return false;
1849}
1850
1851
1852
1853// the utility function ShowWnd() is the same as show,
a3a5df9d 1854// except it handles wxAuiMDIChildFrame windows as well,
cd05bf23
BW
1855// as the Show() method on this class is "unplugged"
1856static void ShowWnd(wxWindow* wnd, bool show)
1857{
a3a5df9d 1858 if (wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
cd05bf23 1859 {
a3a5df9d 1860 wxAuiMDIChildFrame* cf = (wxAuiMDIChildFrame*)wnd;
cd05bf23
BW
1861 cf->DoShow(show);
1862 }
1863 else
1864 {
1865 wnd->Show(show);
1866 }
1867}
1868
1869
1870// DoShowHide() this function shows the active window, then
1871// hides all of the other windows (in that order)
1872void wxAuiTabContainer::DoShowHide()
1873{
1874 wxAuiNotebookPageArray& pages = GetPages();
1875 size_t i, page_count = pages.GetCount();
1876
1877 // show new active page first
1878 for (i = 0; i < page_count; ++i)
1879 {
1880 wxAuiNotebookPage& page = pages.Item(i);
1881 if (page.active)
1882 {
1883 ShowWnd(page.window, true);
1884 break;
1885 }
1886 }
1887
1888 // hide all other pages
1889 for (i = 0; i < page_count; ++i)
1890 {
1891 wxAuiNotebookPage& page = pages.Item(i);
1892 ShowWnd(page.window, page.active);
1893 }
1894}
1895
1896
1897
1898
1899
1900
1901// -- wxAuiTabCtrl class implementation --
1902
1903
cd05bf23
BW
1904
1905BEGIN_EVENT_TABLE(wxAuiTabCtrl, wxControl)
1906 EVT_PAINT(wxAuiTabCtrl::OnPaint)
1907 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground)
1908 EVT_SIZE(wxAuiTabCtrl::OnSize)
1909 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown)
1910 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp)
1911 EVT_MOTION(wxAuiTabCtrl::OnMotion)
1912 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow)
4953f8cf 1913 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton)
cd05bf23
BW
1914END_EVENT_TABLE()
1915
1916
1917wxAuiTabCtrl::wxAuiTabCtrl(wxWindow* parent,
1918 wxWindowID id,
1919 const wxPoint& pos,
1920 const wxSize& size,
4444d148 1921 long style) : wxControl(parent, id, pos, size, style)
cd05bf23
BW
1922{
1923 m_click_pt = wxDefaultPosition;
1924 m_is_dragging = false;
1925 m_hover_button = NULL;
9b3f654a 1926 m_pressed_button = NULL;
cd05bf23
BW
1927}
1928
26da5e4f
BW
1929wxAuiTabCtrl::~wxAuiTabCtrl()
1930{
1931}
cd05bf23
BW
1932
1933void wxAuiTabCtrl::OnPaint(wxPaintEvent&)
1934{
1935 wxPaintDC dc(this);
4444d148 1936
cd05bf23 1937 dc.SetFont(GetFont());
4444d148 1938
cd05bf23 1939 if (GetPageCount() > 0)
01372b8f 1940 Render(&dc, this);
cd05bf23
BW
1941}
1942
1943void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
1944{
1945}
1946
1947void wxAuiTabCtrl::OnSize(wxSizeEvent& evt)
1948{
1949 wxSize s = evt.GetSize();
1950 wxRect r(0, 0, s.GetWidth(), s.GetHeight());
1951 SetRect(r);
1952}
1953
1954void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt)
1955{
1956 CaptureMouse();
1957 m_click_pt = wxDefaultPosition;
1958 m_is_dragging = false;
08c068a4 1959 m_click_tab = NULL;
9b3f654a 1960 m_pressed_button = NULL;
4444d148 1961
760d3542 1962
cd05bf23
BW
1963 wxWindow* wnd;
1964 if (TabHitTest(evt.m_x, evt.m_y, &wnd))
9b405ab3 1965 {
cd05bf23
BW
1966 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1967 e.SetSelection(GetIdxFromWindow(wnd));
1968 e.SetOldSelection(GetActivePage());
1969 e.SetEventObject(this);
1970 GetEventHandler()->ProcessEvent(e);
4444d148 1971
cd05bf23
BW
1972 m_click_pt.x = evt.m_x;
1973 m_click_pt.y = evt.m_y;
08c068a4 1974 m_click_tab = wnd;
cd05bf23 1975 }
760d3542 1976
cd05bf23
BW
1977 if (m_hover_button)
1978 {
9b3f654a
BW
1979 m_pressed_button = m_hover_button;
1980 m_pressed_button->cur_state = wxAUI_BUTTON_STATE_PRESSED;
cd05bf23
BW
1981 Refresh();
1982 Update();
1983 }
1984}
1985
9b3f654a 1986void wxAuiTabCtrl::OnLeftUp(wxMouseEvent& evt)
cd05bf23
BW
1987{
1988 if (GetCapture() == this)
1989 ReleaseMouse();
4444d148 1990
cd05bf23
BW
1991 if (m_is_dragging)
1992 {
1993 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, m_windowId);
08c068a4
BW
1994 evt.SetSelection(GetIdxFromWindow(m_click_tab));
1995 evt.SetOldSelection(evt.GetSelection());
cd05bf23
BW
1996 evt.SetEventObject(this);
1997 GetEventHandler()->ProcessEvent(evt);
1998 return;
1999 }
4444d148 2000
9b3f654a 2001 if (m_pressed_button)
cd05bf23 2002 {
9b3f654a
BW
2003 // make sure we're still clicking the button
2004 wxAuiTabContainerButton* button = NULL;
2005 if (!ButtonHitTest(evt.m_x, evt.m_y, &button))
2006 return;
2007
2008 if (button != m_pressed_button)
2009 {
2010 m_pressed_button = NULL;
2011 return;
2012 }
2013
cd05bf23
BW
2014 Refresh();
2015 Update();
4444d148 2016
9b3f654a 2017 if (!(m_pressed_button->cur_state & wxAUI_BUTTON_STATE_DISABLED))
25d7497c
BW
2018 {
2019 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_windowId);
9b3f654a 2020 evt.SetInt(m_pressed_button->id);
25d7497c
BW
2021 evt.SetEventObject(this);
2022 GetEventHandler()->ProcessEvent(evt);
2023 }
9b3f654a
BW
2024
2025 m_pressed_button = NULL;
cd05bf23 2026 }
4444d148 2027
cd05bf23
BW
2028 m_click_pt = wxDefaultPosition;
2029 m_is_dragging = false;
08c068a4 2030 m_click_tab = NULL;
cd05bf23
BW
2031}
2032
2033void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt)
2034{
2035 wxPoint pos = evt.GetPosition();
2036
2037 // check if the mouse is hovering above a button
2038 wxAuiTabContainerButton* button;
2039 if (ButtonHitTest(pos.x, pos.y, &button))
2040 {
b6418695
BW
2041 if (m_hover_button && button != m_hover_button)
2042 {
2043 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
2044 m_hover_button = NULL;
2045 Refresh();
2046 Update();
2047 }
2048
cd05bf23
BW
2049 if (button->cur_state != wxAUI_BUTTON_STATE_HOVER)
2050 {
2051 button->cur_state = wxAUI_BUTTON_STATE_HOVER;
2052 Refresh();
2053 Update();
2054 m_hover_button = button;
2055 return;
2056 }
2057 }
2058 else
2059 {
2060 if (m_hover_button)
2061 {
2062 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
2063 m_hover_button = NULL;
2064 Refresh();
2065 Update();
2066 }
2067 }
4444d148
WS
2068
2069
cd05bf23
BW
2070 if (!evt.LeftIsDown() || m_click_pt == wxDefaultPosition)
2071 return;
4444d148 2072
cd05bf23
BW
2073 if (m_is_dragging)
2074 {
2075 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, m_windowId);
08c068a4
BW
2076 evt.SetSelection(GetIdxFromWindow(m_click_tab));
2077 evt.SetOldSelection(evt.GetSelection());
cd05bf23
BW
2078 evt.SetEventObject(this);
2079 GetEventHandler()->ProcessEvent(evt);
2080 return;
4444d148
WS
2081 }
2082
2083
cd05bf23
BW
2084 int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
2085 int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
2086
2087 if (abs(pos.x - m_click_pt.x) > drag_x_threshold ||
2088 abs(pos.y - m_click_pt.y) > drag_y_threshold)
2089 {
2090 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, m_windowId);
08c068a4
BW
2091 evt.SetSelection(GetIdxFromWindow(m_click_tab));
2092 evt.SetOldSelection(evt.GetSelection());
cd05bf23
BW
2093 evt.SetEventObject(this);
2094 GetEventHandler()->ProcessEvent(evt);
4444d148 2095
cd05bf23
BW
2096 m_is_dragging = true;
2097 }
2098}
2099
2100void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event))
2101{
2102 if (m_hover_button)
2103 {
2104 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
2105 m_hover_button = NULL;
2106 Refresh();
2107 Update();
2108 }
2109}
2110
4953f8cf
BW
2111void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent& event)
2112{
2113 int button = event.GetInt();
2114
2115 if (button == wxAUI_BUTTON_LEFT || button == wxAUI_BUTTON_RIGHT)
2116 {
2117 if (button == wxAUI_BUTTON_LEFT)
2118 {
2119 if (GetTabOffset() > 0)
2120 {
2121 SetTabOffset(GetTabOffset()-1);
2122 Refresh();
2123 Update();
2124 }
2125 }
2126 else
2127 {
2128 SetTabOffset(GetTabOffset()+1);
2129 Refresh();
2130 Update();
2131 }
01372b8f
BW
2132 }
2133 else if (button == wxAUI_BUTTON_WINDOWLIST)
2134 {
2135 wxArrayString as;
2136
2137 size_t i, page_count = m_pages.GetCount();
2138 for (i = 0; i < page_count; ++i)
2139 {
2140 wxAuiNotebookPage& page = m_pages.Item(i);
2141 as.Add(page.caption);
2142 }
2143
2144 int idx = GetArtProvider()->ShowWindowList(this, as, GetActivePage());
2145
2146 if (idx != -1)
2147 {
2148 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
2149 e.SetSelection(idx);
2150 e.SetOldSelection(GetActivePage());
2151 e.SetEventObject(this);
2152 GetEventHandler()->ProcessEvent(e);
2153 }
4953f8cf
BW
2154 }
2155 else
2156 {
2157 event.Skip();
2158 }
2159}
cd05bf23
BW
2160
2161// wxTabFrame is an interesting case. It's important that all child pages
2162// of the multi-notebook control are all actually children of that control
2163// (and not grandchildren). wxTabFrame facilitates this. There is one
2164// instance of wxTabFrame for each tab control inside the multi-notebook.
2165// It's important to know that wxTabFrame is not a real window, but it merely
2166// used to capture the dimensions/positioning of the internal tab control and
2167// it's managed page windows
2168
2169class wxTabFrame : public wxWindow
2170{
2171public:
2172
2173 wxTabFrame()
2174 {
2175 m_tabs = NULL;
2176 m_rect = wxRect(0,0,200,200);
da5e85d9
BW
2177 m_tab_ctrl_height = 20;
2178 }
4444d148 2179
da5e85d9
BW
2180 void SetTabCtrlHeight(int h)
2181 {
2182 m_tab_ctrl_height = h;
cd05bf23 2183 }
4444d148 2184
cd05bf23
BW
2185 void DoSetSize(int x, int y,
2186 int width, int height,
2187 int WXUNUSED(sizeFlags = wxSIZE_AUTO))
2188 {
2189 m_rect = wxRect(x, y, width, height);
2190 DoSizing();
2191 }
4444d148 2192
cd05bf23
BW
2193 void DoGetClientSize(int* x, int* y) const
2194 {
2195 *x = m_rect.width;
2196 *y = m_rect.height;
2197 }
4f450f41
RD
2198
2199 bool Show( bool WXUNUSED(show = true) ) { return false; }
4444d148 2200
cd05bf23
BW
2201 void DoSizing()
2202 {
2203 if (!m_tabs)
2204 return;
4444d148 2205
b0d17f7c
BW
2206 m_tab_rect = wxRect(m_rect.x, m_rect.y, m_rect.width, m_tab_ctrl_height);
2207 m_tabs->SetSize(m_rect.x, m_rect.y, m_rect.width, m_tab_ctrl_height);
2208 m_tabs->SetRect(wxRect(0, 0, m_rect.width, m_tab_ctrl_height));
cd05bf23 2209 m_tabs->Refresh();
9d59bf68 2210 m_tabs->Update();
4444d148 2211
cd05bf23
BW
2212 wxAuiNotebookPageArray& pages = m_tabs->GetPages();
2213 size_t i, page_count = pages.GetCount();
4444d148 2214
cd05bf23
BW
2215 for (i = 0; i < page_count; ++i)
2216 {
2217 wxAuiNotebookPage& page = pages.Item(i);
b0d17f7c
BW
2218 page.window->SetSize(m_rect.x, m_rect.y + m_tab_ctrl_height,
2219 m_rect.width, m_rect.height - m_tab_ctrl_height);
4444d148 2220
a3a5df9d 2221 if (page.window->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
cd05bf23 2222 {
a3a5df9d 2223 wxAuiMDIChildFrame* wnd = (wxAuiMDIChildFrame*)page.window;
cd05bf23
BW
2224 wnd->ApplyMDIChildFrameRect();
2225 }
2226 }
2227 }
2228
134e83cb
BW
2229 void DoGetSize(int* x, int* y) const
2230 {
2231 if (x)
2232 *x = m_rect.GetWidth();
2233 if (y)
2234 *y = m_rect.GetHeight();
2235 }
4444d148 2236
134e83cb
BW
2237 void Update()
2238 {
2239 // does nothing
2240 }
4444d148 2241
cd05bf23
BW
2242public:
2243
2244 wxRect m_rect;
2245 wxRect m_tab_rect;
2246 wxAuiTabCtrl* m_tabs;
da5e85d9 2247 int m_tab_ctrl_height;
cd05bf23
BW
2248};
2249
2250
2251
2252
2253
a3a5df9d 2254// -- wxAuiNotebook class implementation --
cd05bf23 2255
a3a5df9d
BW
2256BEGIN_EVENT_TABLE(wxAuiNotebook, wxControl)
2257 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
2258 //EVT_SIZE(wxAuiNotebook::OnSize)
2259 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
2260 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus)
cd05bf23
BW
2261 EVT_COMMAND_RANGE(10000, 10100,
2262 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING,
a3a5df9d 2263 wxAuiNotebook::OnTabClicked)
cd05bf23
BW
2264 EVT_COMMAND_RANGE(10000, 10100,
2265 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG,
a3a5df9d 2266 wxAuiNotebook::OnTabBeginDrag)
cd05bf23
BW
2267 EVT_COMMAND_RANGE(10000, 10100,
2268 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG,
a3a5df9d 2269 wxAuiNotebook::OnTabEndDrag)
cd05bf23
BW
2270 EVT_COMMAND_RANGE(10000, 10100,
2271 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION,
a3a5df9d 2272 wxAuiNotebook::OnTabDragMotion)
cd05bf23
BW
2273 EVT_COMMAND_RANGE(10000, 10100,
2274 wxEVT_COMMAND_AUINOTEBOOK_BUTTON,
a3a5df9d 2275 wxAuiNotebook::OnTabButton)
cd05bf23
BW
2276END_EVENT_TABLE()
2277
a3a5df9d 2278wxAuiNotebook::wxAuiNotebook()
cd05bf23
BW
2279{
2280 m_curpage = -1;
2281 m_tab_id_counter = 10000;
2282 m_dummy_wnd = NULL;
da5e85d9 2283 m_tab_ctrl_height = 20;
cd05bf23
BW
2284}
2285
a3a5df9d 2286wxAuiNotebook::wxAuiNotebook(wxWindow *parent,
cd05bf23
BW
2287 wxWindowID id,
2288 const wxPoint& pos,
2289 const wxSize& size,
2290 long style) : wxControl(parent, id, pos, size, style)
2291{
702b1c7e 2292 InitNotebook(style);
cd05bf23
BW
2293}
2294
a3a5df9d 2295bool wxAuiNotebook::Create(wxWindow* parent,
cd05bf23
BW
2296 wxWindowID id,
2297 const wxPoint& pos,
2298 const wxSize& size,
2299 long style)
2300{
2301 if (!wxControl::Create(parent, id, pos, size, style))
2302 return false;
4444d148 2303
702b1c7e 2304 InitNotebook(style);
4444d148 2305
cd05bf23
BW
2306 return true;
2307}
2308
2309// InitNotebook() contains common initialization
2310// code called by all constructors
a3a5df9d 2311void wxAuiNotebook::InitNotebook(long style)
cd05bf23 2312{
da5e85d9
BW
2313 m_curpage = -1;
2314 m_tab_id_counter = 10000;
2315 m_dummy_wnd = NULL;
2316 m_tab_ctrl_height = 20;
702b1c7e
BW
2317 m_flags = (unsigned int)style;
2318
cd05bf23
BW
2319 m_normal_font = *wxNORMAL_FONT;
2320 m_selected_font = *wxNORMAL_FONT;
2321 m_selected_font.SetWeight(wxBOLD);
4444d148 2322
b0d17f7c 2323 SetArtProvider(new wxAuiDefaultTabArt);
4444d148
WS
2324
2325 m_dummy_wnd = new wxWindow(this, wxID_ANY, wxPoint(0,0), wxSize(0,0));
cd05bf23
BW
2326 m_dummy_wnd->SetSize(200, 200);
2327 m_dummy_wnd->Show(false);
4444d148 2328
cd05bf23 2329 m_mgr.SetManagedWindow(this);
4444d148 2330
cd05bf23 2331 m_mgr.AddPane(m_dummy_wnd,
a3a5df9d 2332 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
4444d148 2333
cd05bf23
BW
2334 m_mgr.Update();
2335}
2336
a3a5df9d 2337wxAuiNotebook::~wxAuiNotebook()
cd05bf23
BW
2338{
2339 m_mgr.UnInit();
2340}
2341
a3a5df9d 2342void wxAuiNotebook::SetArtProvider(wxAuiTabArt* art)
3f69756e
BW
2343{
2344 m_tabs.SetArtProvider(art);
b0d17f7c 2345
2b9aac33
BW
2346 SetTabCtrlHeight(CalculateTabCtrlHeight());
2347}
2348
2349void wxAuiNotebook::SetTabCtrlHeight(int height)
2350{
2351 // if the tab control height needs to change, update
2352 // all of our tab controls with the new height
2353 if (m_tab_ctrl_height != height)
b0d17f7c 2354 {
2b9aac33
BW
2355 wxAuiTabArt* art = m_tabs.GetArtProvider();
2356
2357 m_tab_ctrl_height = height;
2358
2359 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
2360 size_t i, pane_count = all_panes.GetCount();
2361 for (i = 0; i < pane_count; ++i)
2362 {
2363 wxAuiPaneInfo& pane = all_panes.Item(i);
2364 if (pane.name == wxT("dummy"))
2365 continue;
2366 wxTabFrame* tab_frame = (wxTabFrame*)pane.window;
2367 wxAuiTabCtrl* tabctrl = tab_frame->m_tabs;
2368 tab_frame->SetTabCtrlHeight(m_tab_ctrl_height);
2369 tabctrl->SetArtProvider(art->Clone());
2370 tab_frame->DoSizing();
2371 }
b0d17f7c 2372 }
3f69756e
BW
2373}
2374
2b9aac33
BW
2375int wxAuiNotebook::CalculateTabCtrlHeight()
2376{
2377 // find out new best tab height
2378 wxAuiTabArt* art = m_tabs.GetArtProvider();
2379
2380 return art->GetBestTabCtrlSize(this, m_tabs.GetPages());
2381}
2382
2383
a3a5df9d 2384wxAuiTabArt* wxAuiNotebook::GetArtProvider()
3f69756e
BW
2385{
2386 return m_tabs.GetArtProvider();
2387}
2388
0ce53f32
BW
2389void wxAuiNotebook::SetWindowStyleFlag(long style)
2390{
2391 wxControl::SetWindowStyleFlag(style);
2392
2393 m_flags = (unsigned int)style;
2394
2395 // if the control is already initialized
2396 if (m_mgr.GetManagedWindow() == (wxWindow*)this)
2397 {
2398 // let all of the tab children know about the new style
2399
2400 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
2401 size_t i, pane_count = all_panes.GetCount();
2402 for (i = 0; i < pane_count; ++i)
2403 {
2404 wxAuiPaneInfo& pane = all_panes.Item(i);
2405 if (pane.name == wxT("dummy"))
2406 continue;
2407 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
2408 tabctrl->SetFlags(m_flags);
2409 tabctrl->Refresh();
2410 tabctrl->Update();
2411 }
2412 }
2413}
2414
2415
a3a5df9d 2416bool wxAuiNotebook::AddPage(wxWindow* page,
cd05bf23
BW
2417 const wxString& caption,
2418 bool select,
2419 const wxBitmap& bitmap)
2420{
2421 return InsertPage(GetPageCount(), page, caption, select, bitmap);
2422}
4444d148 2423
a3a5df9d 2424bool wxAuiNotebook::InsertPage(size_t page_idx,
cd05bf23
BW
2425 wxWindow* page,
2426 const wxString& caption,
2427 bool select,
2428 const wxBitmap& bitmap)
2429{
2430 wxAuiNotebookPage info;
2431 info.window = page;
2432 info.caption = caption;
2433 info.bitmap = bitmap;
2434 info.active = false;
2435
2436 // if there are currently no tabs, the first added
2437 // tab must be active
2438 if (m_tabs.GetPageCount() == 0)
2439 info.active = true;
2440
2441 m_tabs.InsertPage(page, info, page_idx);
2442
2443 wxAuiTabCtrl* active_tabctrl = GetActiveTabCtrl();
2444 if (page_idx >= active_tabctrl->GetPageCount())
2445 active_tabctrl->AddPage(page, info);
2446 else
2447 active_tabctrl->InsertPage(page, info, page_idx);
4444d148 2448
2b9aac33 2449 SetTabCtrlHeight(CalculateTabCtrlHeight());
cd05bf23
BW
2450 DoSizing();
2451 active_tabctrl->DoShowHide();
4444d148 2452
cd05bf23
BW
2453 if (select)
2454 {
2455 int idx = m_tabs.GetIdxFromWindow(page);
a3a5df9d 2456 wxASSERT_MSG(idx != -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
4444d148 2457
cd05bf23
BW
2458 SetSelection(idx);
2459 }
4444d148 2460
cd05bf23
BW
2461 return true;
2462}
2463
2464
2465// DeletePage() removes a tab from the multi-notebook,
2466// and destroys the window as well
a3a5df9d 2467bool wxAuiNotebook::DeletePage(size_t page_idx)
ae4558e0 2468{
4444d148 2469 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
5d3aeb0f
BW
2470
2471 if (!RemovePage(page_idx))
2472 return false;
2473
2474
2475 // actually destroy the window now
2476 if (wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
2477 {
2478 // delete the child frame with pending delete, as is
2479 // customary with frame windows
2480 if (!wxPendingDelete.Member(wnd))
2481 wxPendingDelete.Append(wnd);
2482 }
2483 else
2484 {
2485 wnd->Destroy();
2486 }
2487
2488 return true;
cd05bf23
BW
2489}
2490
2491
2492
2493// RemovePage() removes a tab from the multi-notebook,
2494// but does not destroy the window
a3a5df9d 2495bool wxAuiNotebook::RemovePage(size_t page_idx)
cd05bf23 2496{
cd05bf23 2497 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
5d3aeb0f 2498 wxWindow* new_active = NULL;
4444d148 2499
5d3aeb0f 2500 // find out which onscreen tab ctrl owns this tab
cd05bf23
BW
2501 wxAuiTabCtrl* ctrl;
2502 int ctrl_idx;
5d3aeb0f
BW
2503 if (!FindTab(wnd, &ctrl, &ctrl_idx))
2504 return false;
2505
2506 // find a new page and set it as active
2507 int new_idx = ctrl_idx+1;
2508 if (new_idx >= (int)ctrl->GetPageCount())
2509 new_idx = ctrl_idx-1;
2510
2511 if (new_idx >= 0 && new_idx < (int)ctrl->GetPageCount())
cd05bf23 2512 {
5d3aeb0f
BW
2513 new_active = ctrl->GetWindowFromIdx(new_idx);
2514 }
2515 else
2516 {
2517 // set the active page to the first page that
2518 // isn't the one being deleted
2519 size_t i, page_count = m_tabs.GetPageCount();
2520 for (i = 0; i < page_count; ++i)
2521 {
2522 wxWindow* w = m_tabs.GetWindowFromIdx(i);
2523 if (wnd != w)
2524 {
2525 new_active = m_tabs.GetWindowFromIdx(i);
2526 break;
2527 }
2528 }
cd05bf23 2529 }
4444d148 2530
5d3aeb0f
BW
2531 // remove the tab from main catalog
2532 if (!m_tabs.RemovePage(wnd))
2533 return false;
2534
2535 // remove the tab from the onscreen tab ctrl
2536 ctrl->RemovePage(wnd);
2537
2538
2539 RemoveEmptyTabFrames();
2540
2541 // set new active pane
2542 if (new_active)
2543 {
2544 m_curpage = -1;
2545 SetSelection(m_tabs.GetIdxFromWindow(new_active));
2546 }
2547
2548 return true;
cd05bf23
BW
2549}
2550
2551// SetPageText() changes the tab caption of the specified page
a3a5df9d 2552bool wxAuiNotebook::SetPageText(size_t page_idx, const wxString& text)
4444d148 2553{
cd05bf23
BW
2554 if (page_idx >= m_tabs.GetPageCount())
2555 return false;
4444d148 2556
cd05bf23
BW
2557 // update our own tab catalog
2558 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
2559 page_info.caption = text;
4444d148 2560
cd05bf23
BW
2561 // update what's on screen
2562 wxAuiTabCtrl* ctrl;
2563 int ctrl_idx;
2564 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
2565 {
2566 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
2567 info.caption = text;
2568 ctrl->Refresh();
639a4f7b 2569 ctrl->Update();
cd05bf23 2570 }
4444d148 2571
cd05bf23
BW
2572 return true;
2573}
2574
2575// GetSelection() returns the index of the currently active page
a3a5df9d 2576int wxAuiNotebook::GetSelection() const
cd05bf23
BW
2577{
2578 return m_curpage;
2579}
2580
2581// SetSelection() sets the currently active page
a3a5df9d 2582size_t wxAuiNotebook::SetSelection(size_t new_page)
cd05bf23
BW
2583{
2584 wxWindow* wnd = m_tabs.GetWindowFromIdx(new_page);
2585 if (!wnd)
2586 return m_curpage;
4444d148 2587
cd05bf23
BW
2588 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
2589 evt.SetSelection(new_page);
2590 evt.SetOldSelection(m_curpage);
2591 evt.SetEventObject(this);
2592 if (!GetEventHandler()->ProcessEvent(evt) || evt.IsAllowed())
2593 {
2594 // program allows the page change
2595 evt.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED);
2596 (void)GetEventHandler()->ProcessEvent(evt);
2597
2598
2599
2600 wxAuiTabCtrl* ctrl;
2601 int ctrl_idx;
2602 if (FindTab(wnd, &ctrl, &ctrl_idx))
4444d148 2603 {
cd05bf23 2604 m_tabs.SetActivePage(wnd);
4444d148 2605
cd05bf23
BW
2606 ctrl->SetActivePage(ctrl_idx);
2607 DoSizing();
2608 ctrl->DoShowHide();
4444d148 2609
cd05bf23
BW
2610 int old_curpage = m_curpage;
2611 m_curpage = new_page;
2612
2613
2614 // set fonts
a3a5df9d 2615 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
2616 size_t i, pane_count = all_panes.GetCount();
2617 for (i = 0; i < pane_count; ++i)
2618 {
a3a5df9d 2619 wxAuiPaneInfo& pane = all_panes.Item(i);
cd05bf23
BW
2620 if (pane.name == wxT("dummy"))
2621 continue;
2622 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
2623 if (tabctrl != ctrl)
2624 tabctrl->SetSelectedFont(m_normal_font);
2625 else
2626 tabctrl->SetSelectedFont(m_selected_font);
2627 tabctrl->Refresh();
2628 }
2629
2630 wnd->SetFocus();
4444d148 2631
cd05bf23
BW
2632 return old_curpage;
2633 }
2634 }
2635
2636 return m_curpage;
2637}
2638
2639// GetPageCount() returns the total number of
2640// pages managed by the multi-notebook
a3a5df9d 2641size_t wxAuiNotebook::GetPageCount() const
cd05bf23
BW
2642{
2643 return m_tabs.GetPageCount();
2644}
2645
2646// GetPage() returns the wxWindow pointer of the
2647// specified page
a3a5df9d 2648wxWindow* wxAuiNotebook::GetPage(size_t page_idx) const
cd05bf23
BW
2649{
2650 wxASSERT(page_idx < m_tabs.GetPageCount());
4444d148 2651
cd05bf23
BW
2652 return m_tabs.GetWindowFromIdx(page_idx);
2653}
2654
2655// DoSizing() performs all sizing operations in each tab control
a3a5df9d 2656void wxAuiNotebook::DoSizing()
cd05bf23 2657{
a3a5df9d 2658 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
2659 size_t i, pane_count = all_panes.GetCount();
2660 for (i = 0; i < pane_count; ++i)
2661 {
2662 if (all_panes.Item(i).name == wxT("dummy"))
2663 continue;
2664
2665 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
2666 tabframe->DoSizing();
2667 }
2668}
2669
2670// GetActiveTabCtrl() returns the active tab control. It is
2671// called to determine which control gets new windows being added
a3a5df9d 2672wxAuiTabCtrl* wxAuiNotebook::GetActiveTabCtrl()
cd05bf23
BW
2673{
2674 if (m_curpage >= 0 && m_curpage < (int)m_tabs.GetPageCount())
2675 {
2676 wxAuiTabCtrl* ctrl;
2677 int idx;
4444d148 2678
cd05bf23
BW
2679 // find the tab ctrl with the current page
2680 if (FindTab(m_tabs.GetPage(m_curpage).window,
2681 &ctrl, &idx))
4444d148 2682 {
cd05bf23
BW
2683 return ctrl;
2684 }
2685 }
4444d148 2686
cd05bf23 2687 // no current page, just find the first tab ctrl
a3a5df9d 2688 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
2689 size_t i, pane_count = all_panes.GetCount();
2690 for (i = 0; i < pane_count; ++i)
2691 {
2692 if (all_panes.Item(i).name == wxT("dummy"))
2693 continue;
4444d148 2694
cd05bf23
BW
2695 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
2696 return tabframe->m_tabs;
2697 }
4444d148 2698
cd05bf23
BW
2699 // If there is no tabframe at all, create one
2700 wxTabFrame* tabframe = new wxTabFrame;
da5e85d9 2701 tabframe->SetTabCtrlHeight(m_tab_ctrl_height);
cd05bf23
BW
2702 tabframe->m_tabs = new wxAuiTabCtrl(this,
2703 m_tab_id_counter++,
2704 wxDefaultPosition,
2705 wxDefaultSize,
2706 wxNO_BORDER);
702b1c7e 2707 tabframe->m_tabs->SetFlags(m_flags);
b0d17f7c 2708 tabframe->m_tabs->SetArtProvider(m_tabs.GetArtProvider()->Clone());
cd05bf23 2709 m_mgr.AddPane(tabframe,
a3a5df9d 2710 wxAuiPaneInfo().Center().CaptionVisible(false));
4444d148 2711
cd05bf23 2712 m_mgr.Update();
4444d148 2713
cd05bf23
BW
2714 return tabframe->m_tabs;
2715}
2716
2717// FindTab() finds the tab control that currently contains the window as well
2718// as the index of the window in the tab control. It returns true if the
2719// window was found, otherwise false.
a3a5df9d 2720bool wxAuiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx)
cd05bf23 2721{
a3a5df9d 2722 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
2723 size_t i, pane_count = all_panes.GetCount();
2724 for (i = 0; i < pane_count; ++i)
2725 {
2726 if (all_panes.Item(i).name == wxT("dummy"))
2727 continue;
4444d148 2728
cd05bf23 2729 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
4444d148 2730
cd05bf23
BW
2731 int page_idx = tabframe->m_tabs->GetIdxFromWindow(page);
2732 if (page_idx != -1)
2733 {
2734 *ctrl = tabframe->m_tabs;
2735 *idx = page_idx;
2736 return true;
2737 }
2738 }
4444d148 2739
cd05bf23
BW
2740 return false;
2741}
2742
2743
a3a5df9d 2744void wxAuiNotebook::OnEraseBackground(wxEraseEvent&)
cd05bf23
BW
2745{
2746}
2747
a3a5df9d 2748void wxAuiNotebook::OnSize(wxSizeEvent&)
cd05bf23
BW
2749{
2750}
2751
a3a5df9d 2752void wxAuiNotebook::OnTabClicked(wxCommandEvent& command_evt)
cd05bf23
BW
2753{
2754 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
4444d148 2755
cd05bf23
BW
2756 wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject();
2757 wxASSERT(ctrl != NULL);
4444d148 2758
cd05bf23
BW
2759 wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection());
2760 wxASSERT(wnd != NULL);
4444d148 2761
cd05bf23
BW
2762 int idx = m_tabs.GetIdxFromWindow(wnd);
2763 wxASSERT(idx != -1);
4444d148 2764
cd05bf23
BW
2765 SetSelection(idx);
2766}
2767
a3a5df9d 2768void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent&)
cd05bf23 2769{
08c068a4 2770 m_last_drag_x = 0;
cd05bf23
BW
2771}
2772
a3a5df9d 2773void wxAuiNotebook::OnTabDragMotion(wxCommandEvent& evt)
cd05bf23
BW
2774{
2775 wxPoint screen_pt = ::wxGetMousePosition();
2776 wxPoint client_pt = ScreenToClient(screen_pt);
2777 wxPoint zero(0,0);
4444d148 2778
cd05bf23 2779 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
08c068a4 2780 wxAuiTabCtrl* dest_tabs = GetTabCtrlFromPoint(client_pt);
5d3aeb0f 2781
08c068a4 2782 if (dest_tabs == src_tabs)
cd05bf23 2783 {
3941df70
BW
2784 if (src_tabs)
2785 {
2786 src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
2787 }
2788
08c068a4 2789 // always hide the hint for inner-tabctrl drag
cd05bf23 2790 m_mgr.HideHint();
695c0088
BW
2791
2792 // if tab moving is not allowed, leave
2793 if (!(m_flags & wxAUI_NB_TAB_MOVE))
2794 {
2795 return;
2796 }
08c068a4
BW
2797
2798 wxPoint pt = dest_tabs->ScreenToClient(screen_pt);
2799 wxWindow* dest_location_tab;
2800
2801 // this is an inner-tab drag/reposition
2802 if (dest_tabs->TabHitTest(pt.x, pt.y, &dest_location_tab))
2803 {
2804 int src_idx = evt.GetSelection();
2805 int dest_idx = dest_tabs->GetIdxFromWindow(dest_location_tab);
2806
2807 // prevent jumpy drag
2808 if ((src_idx == dest_idx) || dest_idx == -1 ||
2809 (src_idx > dest_idx && m_last_drag_x <= pt.x) ||
2810 (src_idx < dest_idx && m_last_drag_x >= pt.x))
2811 {
2812 m_last_drag_x = pt.x;
2813 return;
2814 }
2815
2816
2817 wxWindow* src_tab = dest_tabs->GetWindowFromIdx(src_idx);
2818 dest_tabs->MovePage(src_tab, dest_idx);
2819 dest_tabs->SetActivePage((size_t)dest_idx);
2820 dest_tabs->DoShowHide();
2821 dest_tabs->Refresh();
2822 m_last_drag_x = pt.x;
2823
2824 }
2825
cd05bf23
BW
2826 return;
2827 }
4444d148 2828
695c0088 2829
5d3aeb0f
BW
2830 // if external drag is allowed, check if the tab is being dragged
2831 // over a different wxAuiNotebook control
2832 if (m_flags & wxAUI_NB_TAB_EXTERNAL_MOVE)
2833 {
2834 wxWindow* tab_ctrl = ::wxFindWindowAtPoint(screen_pt);
2835
87e5fe69
BW
2836 // if we aren't over any window, stop here
2837 if (!tab_ctrl)
2838 return;
2839
13d0b605 2840 // make sure we are not over the hint window
87e5fe69 2841 if (!tab_ctrl->IsKindOf(CLASSINFO(wxFrame)))
5d3aeb0f 2842 {
13d0b605 2843 while (tab_ctrl)
5d3aeb0f 2844 {
13d0b605
BW
2845 if (tab_ctrl->IsKindOf(CLASSINFO(wxAuiTabCtrl)))
2846 break;
2847 tab_ctrl = tab_ctrl->GetParent();
5d3aeb0f
BW
2848 }
2849
13d0b605
BW
2850 if (tab_ctrl)
2851 {
2852 wxAuiNotebook* nb = (wxAuiNotebook*)tab_ctrl->GetParent();
2853
2854 if (nb != this)
2855 {
87e5fe69 2856 wxRect hint_rect = tab_ctrl->GetClientRect();
13d0b605
BW
2857 tab_ctrl->ClientToScreen(&hint_rect.x, &hint_rect.y);
2858 m_mgr.ShowHint(hint_rect);
2859 return;
2860 }
87e5fe69
BW
2861 }
2862 }
2863 else
2864 {
2865 if (!dest_tabs)
2866 {
2867 // we are either over a hint window, or not over a tab
2868 // window, and there is no where to drag to, so exit
2869 return;
13d0b605 2870 }
5d3aeb0f
BW
2871 }
2872 }
2873
2874
69685ee0
BW
2875 // if there are less than two panes, split can't happen, so leave
2876 if (m_tabs.GetPageCount() < 2)
2877 return;
2878
695c0088
BW
2879 // if tab moving is not allowed, leave
2880 if (!(m_flags & wxAUI_NB_TAB_SPLIT))
695c0088 2881 return;
695c0088 2882
3941df70
BW
2883
2884 if (src_tabs)
2885 {
2886 src_tabs->SetCursor(wxCursor(wxCURSOR_SIZING));
2887 }
2888
2889
08c068a4 2890 if (dest_tabs)
cd05bf23 2891 {
08c068a4 2892 wxRect hint_rect = dest_tabs->GetRect();
cd05bf23
BW
2893 ClientToScreen(&hint_rect.x, &hint_rect.y);
2894 m_mgr.ShowHint(hint_rect);
2895 }
2896 else
2897 {
2898 m_mgr.DrawHintRect(m_dummy_wnd, client_pt, zero);
2899 }
2900}
2901
2902
2903
a3a5df9d 2904void wxAuiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
cd05bf23
BW
2905{
2906 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
2907
2908 m_mgr.HideHint();
4444d148 2909
695c0088 2910
3941df70 2911 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
5d3aeb0f 2912 wxAuiTabCtrl* dest_tabs = NULL;
3941df70
BW
2913 if (src_tabs)
2914 {
5d3aeb0f 2915 // set cursor back to an arrow
3941df70
BW
2916 src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
2917 }
2918
cd05bf23
BW
2919 // get the mouse position, which will be used to determine the drop point
2920 wxPoint mouse_screen_pt = ::wxGetMousePosition();
2921 wxPoint mouse_client_pt = ScreenToClient(mouse_screen_pt);
2922
2923
4444d148 2924
5d3aeb0f
BW
2925 // check for an external move
2926 if (m_flags & wxAUI_NB_TAB_EXTERNAL_MOVE)
cd05bf23 2927 {
5d3aeb0f 2928 wxWindow* tab_ctrl = ::wxFindWindowAtPoint(mouse_screen_pt);
c69532f7 2929
5d3aeb0f 2930 while (tab_ctrl)
c69532f7 2931 {
5d3aeb0f
BW
2932 if (tab_ctrl->IsKindOf(CLASSINFO(wxAuiTabCtrl)))
2933 break;
2934 tab_ctrl = tab_ctrl->GetParent();
c69532f7 2935 }
5d3aeb0f
BW
2936
2937 if (tab_ctrl)
2938 {
2939 wxAuiNotebook* nb = (wxAuiNotebook*)tab_ctrl->GetParent();
2940
2941 if (nb != this)
2942 {
2943 // find out from the destination control
2944 // if it's ok to drop this tab here
2945 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, m_windowId);
2946 e.SetSelection(evt.GetSelection());
2947 e.SetOldSelection(evt.GetSelection());
2948 e.SetEventObject(this);
2949 e.SetDragSource(this);
2950 e.Veto(); // dropping must be explicitly approved by control owner
2951
2952 nb->GetEventHandler()->ProcessEvent(e);
2953
2954 if (!e.IsAllowed())
2955 {
2956 // no answer or negative answer
2957 m_mgr.HideHint();
2958 return;
2959 }
2960
2961 // drop was allowed
2962 int src_idx = evt.GetSelection();
2963 wxWindow* src_page = src_tabs->GetWindowFromIdx(src_idx);
2964
2965 // get main index of the page
2966 int main_idx = m_tabs.GetIdxFromWindow(src_page);
2967
2968 // make a copy of the page info
2969 wxAuiNotebookPage page_info = m_tabs.GetPage((size_t)main_idx);
2970
2971 // remove the page from the source notebook
2972 RemovePage(main_idx);
2973
2974 // reparent the page
2975 src_page->Reparent(nb);
2976
2977
2978 // found out the insert idx
2979 wxAuiTabCtrl* dest_tabs = (wxAuiTabCtrl*)tab_ctrl;
2980 wxPoint pt = dest_tabs->ScreenToClient(mouse_screen_pt);
2981
2982 wxWindow* target = NULL;
2983 int insert_idx = -1;
2984 dest_tabs->TabHitTest(pt.x, pt.y, &target);
2985 if (target)
2986 {
2987 insert_idx = dest_tabs->GetIdxFromWindow(target);
2988 }
702b1c7e 2989
5d3aeb0f
BW
2990
2991 // add the page to the new notebook
2992 if (insert_idx == -1)
2993 insert_idx = dest_tabs->GetPageCount();
2994 dest_tabs->InsertPage(page_info.window, page_info, insert_idx);
2995 nb->m_tabs.AddPage(page_info.window, page_info);
2996
2997 nb->DoSizing();
2998 dest_tabs->DoShowHide();
2999 dest_tabs->Refresh();
3000
3001 // set the selection in the destination tab control
3002 nb->SetSelection(nb->m_tabs.GetIdxFromWindow(page_info.window));
3003
3004 return;
3005 }
3006 }
cd05bf23 3007 }
4444d148
WS
3008
3009
3010
5d3aeb0f
BW
3011
3012 // only perform a tab split if it's allowed
69685ee0 3013 if ((m_flags & wxAUI_NB_TAB_SPLIT) && m_tabs.GetPageCount() >= 2)
cd05bf23 3014 {
5d3aeb0f
BW
3015 // If the pointer is in an existing tab frame, do a tab insert
3016 wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt);
3017 wxTabFrame* tab_frame = (wxTabFrame*)GetTabFrameFromTabCtrl(hit_wnd);
3018 int insert_idx = -1;
3019 if (tab_frame)
3020 {
3021 dest_tabs = tab_frame->m_tabs;
cd05bf23 3022
5d3aeb0f
BW
3023 if (dest_tabs == src_tabs)
3024 return;
3025
3026
3027 wxPoint pt = dest_tabs->ScreenToClient(mouse_screen_pt);
3028 wxWindow* target = NULL;
3029 dest_tabs->TabHitTest(pt.x, pt.y, &target);
3030 if (target)
3031 {
3032 insert_idx = dest_tabs->GetIdxFromWindow(target);
3033 }
3034 }
3035 else
3036 {
3037 // If there is no tabframe at all, create one
3038 wxTabFrame* new_tabs = new wxTabFrame;
3039 new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
3040 new_tabs->m_tabs = new wxAuiTabCtrl(this,
3041 m_tab_id_counter++,
3042 wxDefaultPosition,
3043 wxDefaultSize,
3044 wxNO_BORDER);
b0d17f7c 3045 new_tabs->m_tabs->SetArtProvider(m_tabs.GetArtProvider()->Clone());
5d3aeb0f
BW
3046 new_tabs->m_tabs->SetFlags(m_flags);
3047
3048 m_mgr.AddPane(new_tabs,
3049 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3050 mouse_client_pt);
3051 m_mgr.Update();
3052 dest_tabs = new_tabs->m_tabs;
3053 }
4444d148
WS
3054
3055
4444d148 3056
5d3aeb0f
BW
3057 // remove the page from the source tabs
3058 wxAuiNotebookPage page_info = src_tabs->GetPage(evt.GetSelection());
3059 page_info.active = false;
3060 src_tabs->RemovePage(page_info.window);
3061 if (src_tabs->GetPageCount() > 0)
3062 {
3063 src_tabs->SetActivePage((size_t)0);
3064 src_tabs->DoShowHide();
3065 src_tabs->Refresh();
3066 }
4444d148 3067
cd05bf23 3068
5d3aeb0f
BW
3069
3070 // add the page to the destination tabs
3071 if (insert_idx == -1)
3072 insert_idx = dest_tabs->GetPageCount();
3073 dest_tabs->InsertPage(page_info.window, page_info, insert_idx);
3074
3075 if (src_tabs->GetPageCount() == 0)
3076 {
3077 RemoveEmptyTabFrames();
3078 }
3079
3080 DoSizing();
3081 dest_tabs->DoShowHide();
3082 dest_tabs->Refresh();
3083
3084 SetSelection(m_tabs.GetIdxFromWindow(page_info.window));
3085 }
cd05bf23
BW
3086}
3087
3941df70
BW
3088
3089
a3a5df9d 3090wxAuiTabCtrl* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint& pt)
cd05bf23
BW
3091{
3092 // if we've just removed the last tab from the source
3093 // tab set, the remove the tab control completely
a3a5df9d 3094 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
3095 size_t i, pane_count = all_panes.GetCount();
3096 for (i = 0; i < pane_count; ++i)
3097 {
3098 if (all_panes.Item(i).name == wxT("dummy"))
3099 continue;
4444d148 3100
cd05bf23 3101 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
22a35096 3102 if (tabframe->m_tab_rect.Contains(pt))
cd05bf23
BW
3103 return tabframe->m_tabs;
3104 }
4444d148 3105
cd05bf23
BW
3106 return NULL;
3107}
3108
a3a5df9d 3109wxWindow* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow* tab_ctrl)
cd05bf23
BW
3110{
3111 // if we've just removed the last tab from the source
3112 // tab set, the remove the tab control completely
a3a5df9d 3113 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
3114 size_t i, pane_count = all_panes.GetCount();
3115 for (i = 0; i < pane_count; ++i)
3116 {
3117 if (all_panes.Item(i).name == wxT("dummy"))
3118 continue;
4444d148 3119
cd05bf23
BW
3120 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
3121 if (tabframe->m_tabs == tab_ctrl)
3122 {
3123 return tabframe;
3124 }
3125 }
4444d148 3126
cd05bf23
BW
3127 return NULL;
3128}
3129
a3a5df9d 3130void wxAuiNotebook::RemoveEmptyTabFrames()
cd05bf23 3131{
cd05bf23
BW
3132 // if we've just removed the last tab from the source
3133 // tab set, the remove the tab control completely
a3a5df9d 3134 wxAuiPaneInfoArray all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
3135 size_t i, pane_count = all_panes.GetCount();
3136 for (i = 0; i < pane_count; ++i)
3137 {
3138 if (all_panes.Item(i).name == wxT("dummy"))
3139 continue;
3140
3141 wxTabFrame* tab_frame = (wxTabFrame*)all_panes.Item(i).window;
3142 if (tab_frame->m_tabs->GetPageCount() == 0)
3143 {
3144 m_mgr.DetachPane(tab_frame);
4444d148 3145
cd05bf23
BW
3146 // use pending delete because sometimes during
3147 // window closing, refreshs are pending
3148 if (!wxPendingDelete.Member(tab_frame->m_tabs))
4444d148 3149 wxPendingDelete.Append(tab_frame->m_tabs);
cd05bf23 3150 //tab_frame->m_tabs->Destroy();
4444d148 3151
cd05bf23 3152 delete tab_frame;
cd05bf23
BW
3153 }
3154 }
4444d148
WS
3155
3156
cd05bf23
BW
3157 // check to see if there is still a center pane;
3158 // if there isn't, make a frame the center pane
a3a5df9d 3159 wxAuiPaneInfoArray panes = m_mgr.GetAllPanes();
cd05bf23
BW
3160 pane_count = panes.GetCount();
3161 wxWindow* first_good = NULL;
3162 bool center_found = false;
3163 for (i = 0; i < pane_count; ++i)
3164 {
3165 if (panes.Item(i).name == wxT("dummy"))
3166 continue;
3167 if (panes.Item(i).dock_direction == wxAUI_DOCK_CENTRE)
3168 center_found = true;
3169 if (!first_good)
3170 first_good = panes.Item(i).window;
3171 }
3172
3173 if (!center_found && first_good)
3174 {
3175 m_mgr.GetPane(first_good).Centre();
cd05bf23
BW
3176 }
3177
4444d148 3178 m_mgr.Update();
cd05bf23
BW
3179}
3180
a3a5df9d 3181void wxAuiNotebook::OnChildFocus(wxChildFocusEvent& evt)
cd05bf23
BW
3182{
3183 int idx = m_tabs.GetIdxFromWindow(evt.GetWindow());
3184 if (idx != -1 && idx != m_curpage)
3185 {
4444d148 3186 SetSelection(idx);
cd05bf23
BW
3187 }
3188}
3189
3190
a3a5df9d 3191void wxAuiNotebook::OnTabButton(wxCommandEvent& command_evt)
cd05bf23
BW
3192{
3193 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
3194 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4444d148 3195
cd05bf23 3196 int button_id = evt.GetInt();
4444d148 3197
4953f8cf 3198 if (button_id == wxAUI_BUTTON_CLOSE)
cd05bf23
BW
3199 {
3200 int selection = tabs->GetActivePage();
4444d148 3201
cd05bf23
BW
3202 if (selection != -1)
3203 {
3204 wxWindow* close_wnd = tabs->GetWindowFromIdx(selection);
4444d148 3205
3fd8c988
BW
3206
3207 // ask owner if it's ok to close the tab
3208 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, m_windowId);
3209 e.SetSelection(m_tabs.GetIdxFromWindow(close_wnd));
3210 e.SetOldSelection(evt.GetSelection());
3211 e.SetEventObject(this);
3212 GetEventHandler()->ProcessEvent(e);
3213 if (!e.IsAllowed())
3214 return;
3215
3216
a3a5df9d 3217 if (close_wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
cd05bf23
BW
3218 {
3219 close_wnd->Close();
3220 }
3221 else
3222 {
3223 int main_idx = m_tabs.GetIdxFromWindow(close_wnd);
3224 DeletePage(main_idx);
3225 }
3226 }
3227 }
3228}
3229
3230
3231
3232
3233#endif // wxUSE_AUI