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