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