]> git.saurik.com Git - wxWidgets.git/blame - src/aui/auibook.cpp
Make wxSpinCtrlGeneric usable as wxDVC editor control.
[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
a0c2e4a0
JS
34#include "wx/renderer.h"
35
a51dc103 36#ifdef __WXMAC__
efdea9c3 37#include "wx/osx/private.h"
a51dc103
JS
38#endif
39
cd05bf23
BW
40#include "wx/arrimpl.cpp"
41WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray)
42WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray)
43
3c778901
VZ
44wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEvent);
45wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, wxAuiNotebookEvent);
46wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, wxAuiNotebookEvent);
47wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEvent);
48wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, wxAuiNotebookEvent);
49wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, wxAuiNotebookEvent);
50wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, wxAuiNotebookEvent);
51wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, wxAuiNotebookEvent);
52wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, wxAuiNotebookEvent);
53wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, wxAuiNotebookEvent);
54wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, wxAuiNotebookEvent);
55wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, wxAuiNotebookEvent);
56wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, wxAuiNotebookEvent);
57wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, wxAuiNotebookEvent);
58wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, wxAuiNotebookEvent);
cd05bf23 59
0ce53f32 60IMPLEMENT_CLASS(wxAuiNotebook, wxControl)
5d3aeb0f 61IMPLEMENT_CLASS(wxAuiTabCtrl, wxControl)
cd05bf23
BW
62IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent, wxEvent)
63
cd05bf23
BW
64
65
cd05bf23
BW
66
67
a500c7ed
BW
68// these functions live in dockart.cpp -- they'll eventually
69// be moved to a new utility cpp file
cd05bf23 70
a500c7ed
BW
71wxBitmap wxAuiBitmapFromBits(const unsigned char bits[], int w, int h,
72 const wxColour& color);
73
74wxString wxAuiChopText(wxDC& dc, const wxString& text, int max_size);
cd05bf23 75
b0d17f7c
BW
76static void DrawButtons(wxDC& dc,
77 const wxRect& _rect,
78 const wxBitmap& bmp,
79 const wxColour& bkcolour,
80 int button_state)
cd05bf23
BW
81{
82 wxRect rect = _rect;
83
84 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
85 {
86 rect.x++;
87 rect.y++;
88 }
89
90 if (button_state == wxAUI_BUTTON_STATE_HOVER ||
91 button_state == wxAUI_BUTTON_STATE_PRESSED)
92 {
a310c91c
VZ
93 dc.SetBrush(wxBrush(bkcolour.ChangeLightness(120)));
94 dc.SetPen(wxPen(bkcolour.ChangeLightness(75)));
cd05bf23
BW
95
96 // draw the background behind the button
97 dc.DrawRectangle(rect.x, rect.y, 15, 15);
98 }
99
100 // draw the button itself
101 dc.DrawBitmap(bmp, rect.x, rect.y, true);
102}
103
b0d17f7c
BW
104static void IndentPressedBitmap(wxRect* rect, int button_state)
105{
106 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
107 {
108 rect->x++;
109 rect->y++;
110 }
111}
112
b0d17f7c
BW
113
114
115// -- GUI helper classes and functions --
116
117class wxAuiCommandCapture : public wxEvtHandler
118{
119public:
7baac3cb 120
b0d17f7c
BW
121 wxAuiCommandCapture() { m_last_id = 0; }
122 int GetCommandId() const { return m_last_id; }
123
124 bool ProcessEvent(wxEvent& evt)
125 {
126 if (evt.GetEventType() == wxEVT_COMMAND_MENU_SELECTED)
127 {
128 m_last_id = evt.GetId();
129 return true;
130 }
7baac3cb 131
b0d17f7c
BW
132 if (GetNextHandler())
133 return GetNextHandler()->ProcessEvent(evt);
134
135 return false;
136 }
7baac3cb 137
b0d17f7c
BW
138private:
139 int m_last_id;
140};
141
142
143// -- bitmaps --
144
145#if defined( __WXMAC__ )
a243da29 146 static const unsigned char close_bits[]={
b0d17f7c
BW
147 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
148 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
149 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
7baac3cb 150#elif defined( __WXGTK__)
a243da29 151 static const unsigned char close_bits[]={
7baac3cb
VZ
152 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
153 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
154 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
b0d17f7c 155#else
a243da29 156 static const unsigned char close_bits[]={
8896cb72
BW
157 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
158 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
159 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
b0d17f7c
BW
160#endif
161
a243da29 162static const unsigned char left_bits[] = {
b0d17f7c
BW
163 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
164 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
165 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
166
a243da29 167static const unsigned char right_bits[] = {
b0d17f7c
BW
168 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
169 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
170 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
171
a243da29 172static const unsigned char list_bits[] = {
b0d17f7c
BW
173 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
174 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
175 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
176
177
178
179
180
181
182// -- wxAuiDefaultTabArt class implementation --
183
184wxAuiDefaultTabArt::wxAuiDefaultTabArt()
185{
186 m_normal_font = *wxNORMAL_FONT;
187 m_selected_font = *wxNORMAL_FONT;
188 m_selected_font.SetWeight(wxBOLD);
189 m_measuring_font = m_selected_font;
7baac3cb 190
b0d17f7c 191 m_fixed_tab_width = 100;
2b9aac33 192 m_tab_ctrl_height = 0;
b0d17f7c 193
efdea9c3 194#if defined( __WXMAC__ ) && wxOSX_USE_COCOA_OR_CARBON
4ae3fe39 195 wxColor base_colour = wxColour( wxMacCreateCGColorFromHITheme(kThemeBrushToolbarBackground));
003cf4ef
BW
196#else
197 wxColor base_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
198#endif
199
3f7fce73
BW
200 // the base_colour is too pale to use as our base colour,
201 // so darken it a bit --
202 if ((255-base_colour.Red()) +
203 (255-base_colour.Green()) +
204 (255-base_colour.Blue()) < 60)
205 {
a310c91c 206 base_colour = base_colour.ChangeLightness(92);
3f7fce73 207 }
c58ba15f 208
ceb9b8db 209 m_active_colour = base_colour;
003cf4ef 210 m_base_colour = base_colour;
a310c91c 211 wxColor border_colour = base_colour.ChangeLightness(75);
7baac3cb 212
8096c425 213 m_border_pen = wxPen(border_colour);
1750e8e2
BW
214 m_base_colour_pen = wxPen(m_base_colour);
215 m_base_colour_brush = wxBrush(m_base_colour);
7baac3cb 216
a500c7ed
BW
217 m_active_close_bmp = wxAuiBitmapFromBits(close_bits, 16, 16, *wxBLACK);
218 m_disabled_close_bmp = wxAuiBitmapFromBits(close_bits, 16, 16, wxColour(128,128,128));
7baac3cb 219
a500c7ed
BW
220 m_active_left_bmp = wxAuiBitmapFromBits(left_bits, 16, 16, *wxBLACK);
221 m_disabled_left_bmp = wxAuiBitmapFromBits(left_bits, 16, 16, wxColour(128,128,128));
7baac3cb 222
a500c7ed
BW
223 m_active_right_bmp = wxAuiBitmapFromBits(right_bits, 16, 16, *wxBLACK);
224 m_disabled_right_bmp = wxAuiBitmapFromBits(right_bits, 16, 16, wxColour(128,128,128));
7baac3cb 225
a500c7ed
BW
226 m_active_windowlist_bmp = wxAuiBitmapFromBits(list_bits, 16, 16, *wxBLACK);
227 m_disabled_windowlist_bmp = wxAuiBitmapFromBits(list_bits, 16, 16, wxColour(128,128,128));
7baac3cb 228
b0d17f7c
BW
229 m_flags = 0;
230}
231
232wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
233{
234}
235
236wxAuiTabArt* wxAuiDefaultTabArt::Clone()
237{
9a7963a9 238 return new wxAuiDefaultTabArt(*this);
b0d17f7c
BW
239}
240
241void wxAuiDefaultTabArt::SetFlags(unsigned int flags)
242{
243 m_flags = flags;
244}
245
246void wxAuiDefaultTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
247 size_t tab_count)
248{
249 m_fixed_tab_width = 100;
7baac3cb 250
69685ee0 251 int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - 4;
c58ba15f 252
97ac2d5e
BW
253 if (m_flags & wxAUI_NB_CLOSE_BUTTON)
254 tot_width -= m_active_close_bmp.GetWidth();
255 if (m_flags & wxAUI_NB_WINDOWLIST_BUTTON)
256 tot_width -= m_active_windowlist_bmp.GetWidth();
257
b0d17f7c
BW
258 if (tab_count > 0)
259 {
260 m_fixed_tab_width = tot_width/(int)tab_count;
261 }
7baac3cb
VZ
262
263
b0d17f7c
BW
264 if (m_fixed_tab_width < 100)
265 m_fixed_tab_width = 100;
7baac3cb 266
b0d17f7c
BW
267 if (m_fixed_tab_width > tot_width/2)
268 m_fixed_tab_width = tot_width/2;
7baac3cb 269
b0d17f7c
BW
270 if (m_fixed_tab_width > 220)
271 m_fixed_tab_width = 220;
7baac3cb 272
2b9aac33 273 m_tab_ctrl_height = tab_ctrl_size.y;
b0d17f7c 274}
7baac3cb
VZ
275
276
b0d17f7c
BW
277void wxAuiDefaultTabArt::DrawBackground(wxDC& dc,
278 wxWindow* WXUNUSED(wnd),
279 const wxRect& rect)
280{
281 // draw background
134198f1 282
a310c91c
VZ
283 wxColor top_color = m_base_colour.ChangeLightness(90);
284 wxColor bottom_color = m_base_colour.ChangeLightness(170);
134198f1
JS
285 wxRect r;
286
287 if (m_flags &wxAUI_NB_BOTTOM)
288 r = wxRect(rect.x, rect.y, rect.width+2, rect.height);
289 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
290 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
291 else //for wxAUI_NB_TOP
292 r = wxRect(rect.x, rect.y, rect.width+2, rect.height-3);
293
6a93539e 294 dc.GradientFillLinear(r, top_color, bottom_color, wxSOUTH);
7baac3cb 295
134198f1
JS
296
297 // draw base lines
298
299 dc.SetPen(m_border_pen);
300 int y = rect.GetHeight();
301 int w = rect.GetWidth();
302
303 if (m_flags &wxAUI_NB_BOTTOM)
304 {
305 dc.SetBrush(wxBrush(bottom_color));
306 dc.DrawRectangle(-1, 0, w+2, 4);
307 }
308 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
309 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
310 else //for wxAUI_NB_TOP
311 {
312 dc.SetBrush(m_base_colour_brush);
313 dc.DrawRectangle(-1, y-4, w+2, 4);
314 }
b0d17f7c
BW
315}
316
317
318// DrawTab() draws an individual tab.
319//
320// dc - output dc
321// in_rect - rectangle the tab should be confined to
322// caption - tab's caption
323// active - whether or not the tab is active
324// out_rect - actual output rectangle
325// x_extent - the advance x; where the next tab should start
326
327void wxAuiDefaultTabArt::DrawTab(wxDC& dc,
328 wxWindow* wnd,
793d4365 329 const wxAuiNotebookPage& page,
b0d17f7c 330 const wxRect& in_rect,
b0d17f7c
BW
331 int close_button_state,
332 wxRect* out_tab_rect,
333 wxRect* out_button_rect,
334 int* x_extent)
335{
336 wxCoord normal_textx, normal_texty;
337 wxCoord selected_textx, selected_texty;
cedd7b22 338 wxCoord texty;
7baac3cb 339
b0d17f7c 340 // if the caption is empty, measure some temporary text
793d4365
BW
341 wxString caption = page.caption;
342 if (caption.empty())
b0d17f7c 343 caption = wxT("Xj");
7baac3cb 344
b0d17f7c
BW
345 dc.SetFont(m_selected_font);
346 dc.GetTextExtent(caption, &selected_textx, &selected_texty);
7baac3cb 347
b0d17f7c
BW
348 dc.SetFont(m_normal_font);
349 dc.GetTextExtent(caption, &normal_textx, &normal_texty);
7baac3cb 350
b0d17f7c 351 // figure out the size of the tab
2b9aac33
BW
352 wxSize tab_size = GetTabSize(dc,
353 wnd,
793d4365
BW
354 page.caption,
355 page.bitmap,
356 page.active,
2b9aac33
BW
357 close_button_state,
358 x_extent);
359
360 wxCoord tab_height = m_tab_ctrl_height - 3;
b0d17f7c
BW
361 wxCoord tab_width = tab_size.x;
362 wxCoord tab_x = in_rect.x;
363 wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
364
365
793d4365 366 caption = page.caption;
b0d17f7c 367
b0d17f7c
BW
368
369 // select pen, brush and font for the tab to be drawn
370
793d4365 371 if (page.active)
b0d17f7c 372 {
b0d17f7c 373 dc.SetFont(m_selected_font);
b0d17f7c
BW
374 texty = selected_texty;
375 }
cedd7b22 376 else
b0d17f7c 377 {
b0d17f7c 378 dc.SetFont(m_normal_font);
b0d17f7c
BW
379 texty = normal_texty;
380 }
381
7baac3cb 382
7c508bca 383 // create points that will make the tab outline
7baac3cb 384
519337de
BW
385 int clip_width = tab_width;
386 if (tab_x + clip_width > in_rect.x + in_rect.width)
387 clip_width = (in_rect.x + in_rect.width) - tab_x;
7baac3cb 388
8096c425 389/*
003cf4ef 390 wxPoint clip_points[6];
519337de
BW
391 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
392 clip_points[1] = wxPoint(tab_x, tab_y+2);
393 clip_points[2] = wxPoint(tab_x+2, tab_y);
394 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
395 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
396 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
003cf4ef 397
eab9751b 398 // FIXME: these ports don't provide wxRegion ctor from array of points
0197bcdd 399#if !defined(__WXDFB__) && !defined(__WXCOCOA__)
003cf4ef 400 // set the clipping region for the tab --
7baac3cb 401 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
003cf4ef 402 dc.SetClippingRegion(clipping_region);
0197bcdd 403#endif // !wxDFB && !wxCocoa
8096c425
BW
404*/
405 // since the above code above doesn't play well with WXDFB or WXCOCOA,
406 // we'll just use a rectangle for the clipping region for now --
407 dc.SetClippingRegion(tab_x, tab_y, clip_width+1, tab_height-3);
003cf4ef 408
c58ba15f 409
003cf4ef 410 wxPoint border_points[6];
134198f1
JS
411 if (m_flags &wxAUI_NB_BOTTOM)
412 {
413 border_points[0] = wxPoint(tab_x, tab_y);
414 border_points[1] = wxPoint(tab_x, tab_y+tab_height-6);
415 border_points[2] = wxPoint(tab_x+2, tab_y+tab_height-4);
416 border_points[3] = wxPoint(tab_x+tab_width-2, tab_y+tab_height-4);
417 border_points[4] = wxPoint(tab_x+tab_width, tab_y+tab_height-6);
418 border_points[5] = wxPoint(tab_x+tab_width, tab_y);
419 }
420 else //if (m_flags & wxAUI_NB_TOP) {}
421 {
422 border_points[0] = wxPoint(tab_x, tab_y+tab_height-4);
423 border_points[1] = wxPoint(tab_x, tab_y+2);
424 border_points[2] = wxPoint(tab_x+2, tab_y);
425 border_points[3] = wxPoint(tab_x+tab_width-2, tab_y);
426 border_points[4] = wxPoint(tab_x+tab_width, tab_y+2);
427 border_points[5] = wxPoint(tab_x+tab_width, tab_y+tab_height-4);
428 }
429 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
430 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
7baac3cb 431
003cf4ef
BW
432 int drawn_tab_yoff = border_points[1].y;
433 int drawn_tab_height = border_points[0].y - border_points[1].y;
434
2b9aac33 435
793d4365 436 if (page.active)
003cf4ef 437 {
7baac3cb
VZ
438 // draw active tab
439
1750e8e2 440 // draw base background color
003cf4ef 441 wxRect r(tab_x, tab_y, tab_width, tab_height);
ceb9b8db
VZ
442 dc.SetPen(wxPen(m_active_colour));
443 dc.SetBrush(wxBrush(m_active_colour));
8096c425 444 dc.DrawRectangle(r.x+1, r.y+1, r.width-1, r.height-4);
7baac3cb 445
003cf4ef 446 // this white helps fill out the gradient at the top of the tab
1750e8e2
BW
447 dc.SetPen(*wxWHITE_PEN);
448 dc.SetBrush(*wxWHITE_BRUSH);
8096c425 449 dc.DrawRectangle(r.x+2, r.y+1, r.width-3, r.height-4);
7baac3cb 450
003cf4ef 451 // these two points help the rounded corners appear more antialiased
ceb9b8db 452 dc.SetPen(wxPen(m_active_colour));
6a93539e
BW
453 dc.DrawPoint(r.x+2, r.y+1);
454 dc.DrawPoint(r.x+r.width-2, r.y+1);
7baac3cb 455
1750e8e2
BW
456 // set rectangle down a bit for gradient drawing
457 r.SetHeight(r.GetHeight()/2);
003cf4ef 458 r.x += 2;
4bd9bdf3 459 r.width -= 3;
1750e8e2 460 r.y += r.height;
6a93539e 461 r.y -= 2;
7baac3cb 462
1750e8e2 463 // draw gradient background
6a93539e 464 wxColor top_color = *wxWHITE;
ceb9b8db 465 wxColor bottom_color = m_active_colour;
6a93539e 466 dc.GradientFillLinear(r, bottom_color, top_color, wxNORTH);
b0d17f7c 467 }
cedd7b22 468 else
1750e8e2
BW
469 {
470 // draw inactive tab
7baac3cb 471
1750e8e2 472 wxRect r(tab_x, tab_y+1, tab_width, tab_height-3);
7baac3cb 473
1750e8e2
BW
474 // start the gradent up a bit and leave the inside border inset
475 // by a pixel for a 3D look. Only the top half of the inactive
476 // tab will have a slight gradient
6a93539e
BW
477 r.x += 3;
478 r.y++;
479 r.width -= 4;
1750e8e2 480 r.height /= 2;
6a93539e 481 r.height--;
c58ba15f 482
6a93539e 483 // -- draw top gradient fill for glossy look
1750e8e2 484 wxColor top_color = m_base_colour;
a310c91c 485 wxColor bottom_color = top_color.ChangeLightness(160);
1750e8e2 486 dc.GradientFillLinear(r, bottom_color, top_color, wxNORTH);
c58ba15f 487
6a93539e
BW
488 r.y += r.height;
489 r.y--;
c58ba15f 490
6a93539e
BW
491 // -- draw bottom fill for glossy look
492 top_color = m_base_colour;
493 bottom_color = m_base_colour;
494 dc.GradientFillLinear(r, top_color, bottom_color, wxSOUTH);
1750e8e2 495 }
7baac3cb
VZ
496
497 // draw tab outline
003cf4ef 498 dc.SetPen(m_border_pen);
b0d17f7c 499 dc.SetBrush(*wxTRANSPARENT_BRUSH);
7baac3cb
VZ
500 dc.DrawPolygon(WXSIZEOF(border_points), border_points);
501
7c508bca
BW
502 // there are two horizontal grey lines at the bottom of the tab control,
503 // this gets rid of the top one of those lines in the tab control
793d4365 504 if (page.active)
b0d17f7c 505 {
134198f1 506 if (m_flags &wxAUI_NB_BOTTOM)
a310c91c 507 dc.SetPen(wxPen(m_base_colour.ChangeLightness(170)));
134198f1
JS
508 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
509 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
510 else //for wxAUI_NB_TOP
511 dc.SetPen(m_base_colour_pen);
6a93539e 512 dc.DrawLine(border_points[0].x+1,
003cf4ef 513 border_points[0].y,
6a93539e 514 border_points[5].x,
003cf4ef 515 border_points[5].y);
b0d17f7c 516 }
7baac3cb 517
b0d17f7c 518
2b9aac33 519 int text_offset = tab_x + 8;
b0d17f7c 520 int close_button_width = 0;
b0d17f7c
BW
521 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
522 {
523 close_button_width = m_active_close_bmp.GetWidth();
524 }
7baac3cb 525
a0c2e4a0 526 int bitmap_offset = 0;
793d4365 527 if (page.bitmap.IsOk())
2b9aac33 528 {
a0c2e4a0 529 bitmap_offset = tab_x + 8;
7baac3cb 530
2b9aac33 531 // draw bitmap
793d4365 532 dc.DrawBitmap(page.bitmap,
2b9aac33 533 bitmap_offset,
793d4365 534 drawn_tab_yoff + (drawn_tab_height/2) - (page.bitmap.GetHeight()/2),
2b9aac33 535 true);
7baac3cb 536
793d4365 537 text_offset = bitmap_offset + page.bitmap.GetWidth();
2b9aac33 538 text_offset += 3; // bitmap padding
a0c2e4a0 539
2b9aac33 540 }
cedd7b22 541 else
2b9aac33
BW
542 {
543 text_offset = tab_x + 8;
544 }
7baac3cb 545
b0d17f7c 546
a500c7ed 547 wxString draw_text = wxAuiChopText(dc,
b0d17f7c
BW
548 caption,
549 tab_width - (text_offset-tab_x) - close_button_width);
7baac3cb 550
b0d17f7c
BW
551 // draw tab text
552 dc.DrawText(draw_text,
553 text_offset,
2b9aac33 554 drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1);
b0d17f7c 555
a0c2e4a0
JS
556 // draw focus rectangle
557 if (page.active && (wnd->FindFocus() == wnd))
558 {
559 wxRect focusRectText(text_offset, (drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1),
560 selected_textx, selected_texty);
561
562 wxRect focusRect;
563 wxRect focusRectBitmap;
b0d17f7c 564
a0c2e4a0
JS
565 if (page.bitmap.IsOk())
566 focusRectBitmap = wxRect(bitmap_offset, drawn_tab_yoff + (drawn_tab_height/2) - (page.bitmap.GetHeight()/2),
567 page.bitmap.GetWidth(), page.bitmap.GetHeight());
b0d17f7c 568
a0c2e4a0
JS
569 if (page.bitmap.IsOk() && draw_text.IsEmpty())
570 focusRect = focusRectBitmap;
571 else if (!page.bitmap.IsOk() && !draw_text.IsEmpty())
572 focusRect = focusRectText;
573 else if (page.bitmap.IsOk() && !draw_text.IsEmpty())
574 focusRect = focusRectText.Union(focusRectBitmap);
575
576 focusRect.Inflate(2, 2);
577
578 wxRendererNative::Get().DrawFocusRect(wnd, dc, focusRect, 0);
579 }
b0d17f7c
BW
580
581 // draw close button if necessary
582 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
583 {
584 wxBitmap bmp = m_disabled_close_bmp;
585
586 if (close_button_state == wxAUI_BUTTON_STATE_HOVER ||
587 close_button_state == wxAUI_BUTTON_STATE_PRESSED)
588 {
589 bmp = m_active_close_bmp;
590 }
7baac3cb 591
9a3551d3
JS
592 int offsetY = tab_y-1;
593 if (m_flags & wxAUI_NB_BOTTOM)
594 offsetY = 1;
595
b0d17f7c 596 wxRect rect(tab_x + tab_width - close_button_width - 1,
9a3551d3 597 offsetY + (tab_height/2) - (bmp.GetHeight()/2),
b0d17f7c
BW
598 close_button_width,
599 tab_height);
9a3551d3 600
b0d17f7c
BW
601 IndentPressedBitmap(&rect, close_button_state);
602 dc.DrawBitmap(bmp, rect.x, rect.y, true);
7baac3cb 603
b0d17f7c
BW
604 *out_button_rect = rect;
605 }
7baac3cb 606
b0d17f7c 607 *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
7baac3cb 608
b0d17f7c
BW
609 dc.DestroyClippingRegion();
610}
611
612int wxAuiDefaultTabArt::GetIndentSize()
613{
614 return 5;
615}
616
617wxSize wxAuiDefaultTabArt::GetTabSize(wxDC& dc,
618 wxWindow* WXUNUSED(wnd),
619 const wxString& caption,
2b9aac33 620 const wxBitmap& bitmap,
b0d17f7c
BW
621 bool WXUNUSED(active),
622 int close_button_state,
623 int* x_extent)
624{
625 wxCoord measured_textx, measured_texty, tmp;
7baac3cb 626
b0d17f7c
BW
627 dc.SetFont(m_measuring_font);
628 dc.GetTextExtent(caption, &measured_textx, &measured_texty);
7baac3cb 629
b0d17f7c 630 dc.GetTextExtent(wxT("ABCDEFXj"), &tmp, &measured_texty);
7baac3cb 631
213e64e9 632 // add padding around the text
2b9aac33
BW
633 wxCoord tab_width = measured_textx;
634 wxCoord tab_height = measured_texty;
b0d17f7c 635
2b9aac33 636 // if the close button is showing, add space for it
b0d17f7c 637 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
213e64e9 638 tab_width += m_active_close_bmp.GetWidth() + 3;
b0d17f7c 639
2b9aac33
BW
640 // if there's a bitmap, add space for it
641 if (bitmap.IsOk())
642 {
643 tab_width += bitmap.GetWidth();
644 tab_width += 3; // right side bitmap padding
645 tab_height = wxMax(tab_height, bitmap.GetHeight());
646 }
647
648 // add padding
649 tab_width += 16;
650 tab_height += 10;
b0d17f7c
BW
651
652 if (m_flags & wxAUI_NB_TAB_FIXED_WIDTH)
653 {
654 tab_width = m_fixed_tab_width;
655 }
7baac3cb 656
b0d17f7c 657 *x_extent = tab_width;
7baac3cb 658
b0d17f7c
BW
659 return wxSize(tab_width, tab_height);
660}
661
662
663void wxAuiDefaultTabArt::DrawButton(wxDC& dc,
664 wxWindow* WXUNUSED(wnd),
665 const wxRect& in_rect,
666 int bitmap_id,
667 int button_state,
668 int orientation,
b0d17f7c
BW
669 wxRect* out_rect)
670{
671 wxBitmap bmp;
672 wxRect rect;
7baac3cb 673
793d4365 674 switch (bitmap_id)
b0d17f7c 675 {
793d4365
BW
676 case wxAUI_BUTTON_CLOSE:
677 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
678 bmp = m_disabled_close_bmp;
cedd7b22 679 else
793d4365
BW
680 bmp = m_active_close_bmp;
681 break;
682 case wxAUI_BUTTON_LEFT:
683 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
684 bmp = m_disabled_left_bmp;
cedd7b22 685 else
793d4365
BW
686 bmp = m_active_left_bmp;
687 break;
688 case wxAUI_BUTTON_RIGHT:
689 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
690 bmp = m_disabled_right_bmp;
cedd7b22 691 else
793d4365
BW
692 bmp = m_active_right_bmp;
693 break;
694 case wxAUI_BUTTON_WINDOWLIST:
695 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
696 bmp = m_disabled_windowlist_bmp;
cedd7b22 697 else
793d4365
BW
698 bmp = m_active_windowlist_bmp;
699 break;
b0d17f7c 700 }
cd05bf23 701
793d4365 702
b0d17f7c
BW
703 if (!bmp.IsOk())
704 return;
7baac3cb 705
b0d17f7c 706 rect = in_rect;
7baac3cb 707
b0d17f7c
BW
708 if (orientation == wxLEFT)
709 {
710 rect.SetX(in_rect.x);
711 rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2));
712 rect.SetWidth(bmp.GetWidth());
713 rect.SetHeight(bmp.GetHeight());
714 }
cedd7b22 715 else
b0d17f7c
BW
716 {
717 rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
718 ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
719 bmp.GetWidth(), bmp.GetHeight());
720 }
7baac3cb 721
b0d17f7c
BW
722 IndentPressedBitmap(&rect, button_state);
723 dc.DrawBitmap(bmp, rect.x, rect.y, true);
7baac3cb 724
b0d17f7c
BW
725 *out_rect = rect;
726}
cd05bf23 727
793d4365
BW
728int wxAuiDefaultTabArt::ShowDropDown(wxWindow* wnd,
729 const wxAuiNotebookPageArray& pages,
17dd0e05 730 int /*active_idx*/)
b0d17f7c 731{
c58ba15f 732 wxMenu menuPopup;
3f69756e 733
793d4365 734 size_t i, count = pages.GetCount();
b0d17f7c
BW
735 for (i = 0; i < count; ++i)
736 {
793d4365 737 const wxAuiNotebookPage& page = pages.Item(i);
d51beb88
BW
738 wxString caption = page.caption;
739
740 // if there is no caption, make it a space. This will prevent
741 // an assert in the menu code.
742 if (caption.IsEmpty())
743 caption = wxT(" ");
744
17dd0e05
VZ
745 wxMenuItem* item = new wxMenuItem(NULL, 1000+i, caption);
746 if (page.bitmap.IsOk())
747 item->SetBitmap(page.bitmap);
748 menuPopup.Append(item);
b0d17f7c 749 }
7baac3cb 750
7f1e1468 751 // find out where to put the popup menu of window items
b0d17f7c
BW
752 wxPoint pt = ::wxGetMousePosition();
753 pt = wnd->ScreenToClient(pt);
7baac3cb 754
b0d17f7c
BW
755 // find out the screen coordinate at the bottom of the tab ctrl
756 wxRect cli_rect = wnd->GetClientRect();
757 pt.y = cli_rect.y + cli_rect.height;
7baac3cb 758
b0d17f7c
BW
759 wxAuiCommandCapture* cc = new wxAuiCommandCapture;
760 wnd->PushEventHandler(cc);
761 wnd->PopupMenu(&menuPopup, pt);
762 int command = cc->GetCommandId();
763 wnd->PopEventHandler(true);
7baac3cb 764
b0d17f7c
BW
765 if (command >= 1000)
766 return command-1000;
7baac3cb 767
b0d17f7c
BW
768 return -1;
769}
3f69756e 770
2b9aac33 771int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow* wnd,
793d4365 772 const wxAuiNotebookPageArray& pages,
9fbb7d80 773 const wxSize& required_bmp_size)
b0d17f7c
BW
774{
775 wxClientDC dc(wnd);
776 dc.SetFont(m_measuring_font);
7baac3cb 777
9fbb7d80
BW
778 // sometimes a standard bitmap size needs to be enforced, especially
779 // if some tabs have bitmaps and others don't. This is important because
780 // it prevents the tab control from resizing when tabs are added.
781 wxBitmap measure_bmp;
782 if (required_bmp_size.IsFullySpecified())
783 {
784 measure_bmp.Create(required_bmp_size.x,
785 required_bmp_size.y);
786 }
c58ba15f 787
9fbb7d80 788
2b9aac33
BW
789 int max_y = 0;
790 size_t i, page_count = pages.GetCount();
791 for (i = 0; i < page_count; ++i)
792 {
793 wxAuiNotebookPage& page = pages.Item(i);
794
9fbb7d80
BW
795 wxBitmap bmp;
796 if (measure_bmp.IsOk())
797 bmp = measure_bmp;
cedd7b22 798 else
9fbb7d80
BW
799 bmp = page.bitmap;
800
2b9aac33
BW
801 // we don't use the caption text because we don't
802 // want tab heights to be different in the case
803 // of a very short piece of text on one tab and a very
804 // tall piece of text on another tab
805 int x_ext = 0;
806 wxSize s = GetTabSize(dc,
807 wnd,
808 wxT("ABCDEFGHIj"),
9fbb7d80 809 bmp,
2b9aac33
BW
810 true,
811 wxAUI_BUTTON_STATE_HIDDEN,
812 &x_ext);
c58ba15f 813
2b9aac33
BW
814 max_y = wxMax(max_y, s.y);
815 }
7baac3cb 816
2b9aac33 817 return max_y+2;
b0d17f7c
BW
818}
819
820void wxAuiDefaultTabArt::SetNormalFont(const wxFont& font)
821{
822 m_normal_font = font;
823}
824
825void wxAuiDefaultTabArt::SetSelectedFont(const wxFont& font)
826{
827 m_selected_font = font;
828}
829
830void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont& font)
831{
832 m_measuring_font = font;
833}
834
ceb9b8db
VZ
835void wxAuiDefaultTabArt::SetColour(const wxColour& colour)
836{
837 m_base_colour = colour;
838 m_border_pen = wxPen(m_base_colour.ChangeLightness(75));
839 m_base_colour_pen = wxPen(m_base_colour);
840 m_base_colour_brush = wxBrush(m_base_colour);
841}
842
843void wxAuiDefaultTabArt::SetActiveColour(const wxColour& colour)
844{
845 m_active_colour = colour;
846}
b0d17f7c
BW
847
848// -- wxAuiSimpleTabArt class implementation --
849
850wxAuiSimpleTabArt::wxAuiSimpleTabArt()
cd05bf23
BW
851{
852 m_normal_font = *wxNORMAL_FONT;
853 m_selected_font = *wxNORMAL_FONT;
854 m_selected_font.SetWeight(wxBOLD);
855 m_measuring_font = m_selected_font;
4444d148 856
b0d17f7c
BW
857 m_flags = 0;
858 m_fixed_tab_width = 100;
859
cd05bf23 860 wxColour base_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
4444d148 861
8096c425 862 wxColour background_colour = base_colour;
cd05bf23
BW
863 wxColour normaltab_colour = base_colour;
864 wxColour selectedtab_colour = *wxWHITE;
4444d148 865
cd05bf23
BW
866 m_bkbrush = wxBrush(background_colour);
867 m_normal_bkbrush = wxBrush(normaltab_colour);
868 m_normal_bkpen = wxPen(normaltab_colour);
869 m_selected_bkbrush = wxBrush(selectedtab_colour);
870 m_selected_bkpen = wxPen(selectedtab_colour);
7baac3cb 871
a500c7ed
BW
872 m_active_close_bmp = wxAuiBitmapFromBits(close_bits, 16, 16, *wxBLACK);
873 m_disabled_close_bmp = wxAuiBitmapFromBits(close_bits, 16, 16, wxColour(128,128,128));
7baac3cb 874
a500c7ed
BW
875 m_active_left_bmp = wxAuiBitmapFromBits(left_bits, 16, 16, *wxBLACK);
876 m_disabled_left_bmp = wxAuiBitmapFromBits(left_bits, 16, 16, wxColour(128,128,128));
7baac3cb 877
a500c7ed
BW
878 m_active_right_bmp = wxAuiBitmapFromBits(right_bits, 16, 16, *wxBLACK);
879 m_disabled_right_bmp = wxAuiBitmapFromBits(right_bits, 16, 16, wxColour(128,128,128));
7baac3cb 880
a500c7ed
BW
881 m_active_windowlist_bmp = wxAuiBitmapFromBits(list_bits, 16, 16, *wxBLACK);
882 m_disabled_windowlist_bmp = wxAuiBitmapFromBits(list_bits, 16, 16, wxColour(128,128,128));
7baac3cb 883
cd05bf23
BW
884}
885
b0d17f7c 886wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
488e50ee
BW
887{
888}
889
b0d17f7c
BW
890wxAuiTabArt* wxAuiSimpleTabArt::Clone()
891{
ceb9b8db 892 return new wxAuiSimpleTabArt(*this);
b0d17f7c
BW
893}
894
b0d17f7c
BW
895void wxAuiSimpleTabArt::SetFlags(unsigned int flags)
896{
897 m_flags = flags;
898}
899
900void wxAuiSimpleTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
901 size_t tab_count)
902{
903 m_fixed_tab_width = 100;
7baac3cb 904
69685ee0 905 int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - 4;
97ac2d5e
BW
906
907 if (m_flags & wxAUI_NB_CLOSE_BUTTON)
908 tot_width -= m_active_close_bmp.GetWidth();
909 if (m_flags & wxAUI_NB_WINDOWLIST_BUTTON)
910 tot_width -= m_active_windowlist_bmp.GetWidth();
911
b0d17f7c
BW
912 if (tab_count > 0)
913 {
914 m_fixed_tab_width = tot_width/(int)tab_count;
915 }
7baac3cb
VZ
916
917
b0d17f7c
BW
918 if (m_fixed_tab_width < 100)
919 m_fixed_tab_width = 100;
7baac3cb 920
b0d17f7c
BW
921 if (m_fixed_tab_width > tot_width/2)
922 m_fixed_tab_width = tot_width/2;
7baac3cb 923
b0d17f7c
BW
924 if (m_fixed_tab_width > 220)
925 m_fixed_tab_width = 220;
926}
927
ceb9b8db
VZ
928void wxAuiSimpleTabArt::SetColour(const wxColour& colour)
929{
930 m_bkbrush = wxBrush(colour);
931 m_normal_bkbrush = wxBrush(colour);
932 m_normal_bkpen = wxPen(colour);
933}
934
935void wxAuiSimpleTabArt::SetActiveColour(const wxColour& colour)
936{
937 m_selected_bkbrush = wxBrush(colour);
938 m_selected_bkpen = wxPen(colour);
939}
940
b0d17f7c
BW
941void wxAuiSimpleTabArt::DrawBackground(wxDC& dc,
942 wxWindow* WXUNUSED(wnd),
943 const wxRect& rect)
3f69756e
BW
944{
945 // draw background
a6b0e5bd
BW
946 dc.SetBrush(m_bkbrush);
947 dc.SetPen(*wxTRANSPARENT_PEN);
948 dc.DrawRectangle(-1, -1, rect.GetWidth()+2, rect.GetHeight()+2);
3f69756e
BW
949
950 // draw base line
a6b0e5bd
BW
951 dc.SetPen(*wxGREY_PEN);
952 dc.DrawLine(0, rect.GetHeight()-1, rect.GetWidth(), rect.GetHeight()-1);
3f69756e
BW
953}
954
4953f8cf 955
3f69756e
BW
956// DrawTab() draws an individual tab.
957//
958// dc - output dc
959// in_rect - rectangle the tab should be confined to
960// caption - tab's caption
961// active - whether or not the tab is active
962// out_rect - actual output rectangle
963// x_extent - the advance x; where the next tab should start
964
b0d17f7c
BW
965void wxAuiSimpleTabArt::DrawTab(wxDC& dc,
966 wxWindow* wnd,
793d4365 967 const wxAuiNotebookPage& page,
b0d17f7c 968 const wxRect& in_rect,
b0d17f7c
BW
969 int close_button_state,
970 wxRect* out_tab_rect,
971 wxRect* out_button_rect,
972 int* x_extent)
3f69756e
BW
973{
974 wxCoord normal_textx, normal_texty;
975 wxCoord selected_textx, selected_texty;
3f69756e 976 wxCoord textx, texty;
7baac3cb 977
3f69756e 978 // if the caption is empty, measure some temporary text
793d4365
BW
979 wxString caption = page.caption;
980 if (caption.empty())
3f69756e 981 caption = wxT("Xj");
7baac3cb 982
a6b0e5bd
BW
983 dc.SetFont(m_selected_font);
984 dc.GetTextExtent(caption, &selected_textx, &selected_texty);
7baac3cb 985
a6b0e5bd
BW
986 dc.SetFont(m_normal_font);
987 dc.GetTextExtent(caption, &normal_textx, &normal_texty);
7baac3cb 988
a4c8fc23 989 // figure out the size of the tab
2b9aac33
BW
990 wxSize tab_size = GetTabSize(dc,
991 wnd,
793d4365
BW
992 page.caption,
993 page.bitmap,
994 page.active,
2b9aac33
BW
995 close_button_state,
996 x_extent);
3f69756e 997
a4c8fc23
BW
998 wxCoord tab_height = tab_size.y;
999 wxCoord tab_width = tab_size.x;
3f69756e
BW
1000 wxCoord tab_x = in_rect.x;
1001 wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
1002
793d4365 1003 caption = page.caption;
b965ffff 1004
3f69756e
BW
1005 // select pen, brush and font for the tab to be drawn
1006
793d4365 1007 if (page.active)
3f69756e 1008 {
a6b0e5bd
BW
1009 dc.SetPen(m_selected_bkpen);
1010 dc.SetBrush(m_selected_bkbrush);
1011 dc.SetFont(m_selected_font);
3f69756e
BW
1012 textx = selected_textx;
1013 texty = selected_texty;
1014 }
cedd7b22 1015 else
3f69756e 1016 {
a6b0e5bd
BW
1017 dc.SetPen(m_normal_bkpen);
1018 dc.SetBrush(m_normal_bkbrush);
1019 dc.SetFont(m_normal_font);
3f69756e
BW
1020 textx = normal_textx;
1021 texty = normal_texty;
1022 }
1023
1024
1025 // -- draw line --
1026
1027 wxPoint points[7];
1028 points[0].x = tab_x;
1029 points[0].y = tab_y + tab_height - 1;
1030 points[1].x = tab_x + tab_height - 3;
1031 points[1].y = tab_y + 2;
1032 points[2].x = tab_x + tab_height + 3;
1033 points[2].y = tab_y;
1034 points[3].x = tab_x + tab_width - 2;
1035 points[3].y = tab_y;
1036 points[4].x = tab_x + tab_width;
1037 points[4].y = tab_y + 2;
1038 points[5].x = tab_x + tab_width;
1039 points[5].y = tab_y + tab_height - 1;
1040 points[6] = points[0];
1041
b0d17f7c 1042 dc.SetClippingRegion(in_rect);
3f69756e 1043
7baac3cb 1044 dc.DrawPolygon(WXSIZEOF(points) - 1, points);
3f69756e 1045
a6b0e5bd 1046 dc.SetPen(*wxGREY_PEN);
3f69756e 1047
7baac3cb
VZ
1048 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
1049 dc.DrawLines(WXSIZEOF(points), points);
3f69756e 1050
3f69756e 1051
702b1c7e
BW
1052 int text_offset;
1053
1054 int close_button_width = 0;
41b76acd 1055 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
702b1c7e
BW
1056 {
1057 close_button_width = m_active_close_bmp.GetWidth();
1058 text_offset = tab_x + (tab_height/2) + ((tab_width-close_button_width)/2) - (textx/2);
1059 }
cedd7b22 1060 else
702b1c7e
BW
1061 {
1062 text_offset = tab_x + (tab_height/3) + (tab_width/2) - (textx/2);
1063 }
7baac3cb 1064
b0d17f7c
BW
1065 // set minimum text offset
1066 if (text_offset < tab_x + tab_height)
1067 text_offset = tab_x + tab_height;
1068
1069 // chop text if necessary
a500c7ed 1070 wxString draw_text = wxAuiChopText(dc,
b0d17f7c
BW
1071 caption,
1072 tab_width - (text_offset-tab_x) - close_button_width);
702b1c7e
BW
1073
1074 // draw tab text
b0d17f7c 1075 dc.DrawText(draw_text,
702b1c7e 1076 text_offset,
a4c8fc23 1077 (tab_y + tab_height)/2 - (texty/2) + 1);
3f69756e 1078
702b1c7e 1079
a0c2e4a0
JS
1080 // draw focus rectangle
1081 if (page.active && (wnd->FindFocus() == wnd))
1082 {
1083 wxRect focusRect(text_offset, ((tab_y + tab_height)/2 - (texty/2) + 1),
1084 selected_textx, selected_texty);
1085
1086 focusRect.Inflate(2, 2);
1087
1088 wxRendererNative::Get().DrawFocusRect(wnd, dc, focusRect, 0);
1089 }
1090
702b1c7e 1091 // draw close button if necessary
41b76acd 1092 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
702b1c7e
BW
1093 {
1094 wxBitmap bmp;
793d4365 1095 if (page.active)
702b1c7e 1096 bmp = m_active_close_bmp;
cedd7b22 1097 else
702b1c7e 1098 bmp = m_disabled_close_bmp;
7baac3cb 1099
0b3d6ff9
BW
1100 wxRect rect(tab_x + tab_width - close_button_width - 1,
1101 tab_y + (tab_height/2) - (bmp.GetHeight()/2) + 1,
1102 close_button_width,
1103 tab_height - 1);
b0d17f7c 1104 DrawButtons(dc, rect, bmp, *wxWHITE, close_button_state);
7baac3cb 1105
41b76acd 1106 *out_button_rect = rect;
702b1c7e
BW
1107 }
1108
1109
41b76acd 1110 *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
7baac3cb 1111
b0d17f7c 1112 dc.DestroyClippingRegion();
3f69756e
BW
1113}
1114
b0d17f7c
BW
1115int wxAuiSimpleTabArt::GetIndentSize()
1116{
1117 return 0;
1118}
3f69756e 1119
b0d17f7c
BW
1120wxSize wxAuiSimpleTabArt::GetTabSize(wxDC& dc,
1121 wxWindow* WXUNUSED(wnd),
1122 const wxString& caption,
2b9aac33 1123 const wxBitmap& WXUNUSED(bitmap),
b0d17f7c
BW
1124 bool WXUNUSED(active),
1125 int close_button_state,
1126 int* x_extent)
4953f8cf
BW
1127{
1128 wxCoord measured_textx, measured_texty;
7baac3cb 1129
a6b0e5bd
BW
1130 dc.SetFont(m_measuring_font);
1131 dc.GetTextExtent(caption, &measured_textx, &measured_texty);
7baac3cb 1132
4953f8cf
BW
1133 wxCoord tab_height = measured_texty + 4;
1134 wxCoord tab_width = measured_textx + tab_height + 5;
1135
41b76acd 1136 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
702b1c7e 1137 tab_width += m_active_close_bmp.GetWidth();
7baac3cb 1138
b0d17f7c
BW
1139 if (m_flags & wxAUI_NB_TAB_FIXED_WIDTH)
1140 {
1141 tab_width = m_fixed_tab_width;
1142 }
7baac3cb 1143
4953f8cf
BW
1144 *x_extent = tab_width - (tab_height/2) - 1;
1145
1146 return wxSize(tab_width, tab_height);
1147}
1148
1149
b0d17f7c
BW
1150void wxAuiSimpleTabArt::DrawButton(wxDC& dc,
1151 wxWindow* WXUNUSED(wnd),
1152 const wxRect& in_rect,
1153 int bitmap_id,
1154 int button_state,
1155 int orientation,
b0d17f7c 1156 wxRect* out_rect)
4953f8cf
BW
1157{
1158 wxBitmap bmp;
1159 wxRect rect;
7baac3cb 1160
793d4365 1161 switch (bitmap_id)
4953f8cf 1162 {
793d4365
BW
1163 case wxAUI_BUTTON_CLOSE:
1164 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1165 bmp = m_disabled_close_bmp;
cedd7b22 1166 else
793d4365
BW
1167 bmp = m_active_close_bmp;
1168 break;
1169 case wxAUI_BUTTON_LEFT:
1170 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1171 bmp = m_disabled_left_bmp;
cedd7b22 1172 else
793d4365
BW
1173 bmp = m_active_left_bmp;
1174 break;
1175 case wxAUI_BUTTON_RIGHT:
1176 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1177 bmp = m_disabled_right_bmp;
cedd7b22 1178 else
793d4365
BW
1179 bmp = m_active_right_bmp;
1180 break;
1181 case wxAUI_BUTTON_WINDOWLIST:
1182 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1183 bmp = m_disabled_windowlist_bmp;
cedd7b22 1184 else
793d4365
BW
1185 bmp = m_active_windowlist_bmp;
1186 break;
4953f8cf
BW
1187 }
1188
1189 if (!bmp.IsOk())
1190 return;
7baac3cb 1191
4953f8cf 1192 rect = in_rect;
7baac3cb 1193
4953f8cf
BW
1194 if (orientation == wxLEFT)
1195 {
25d7497c
BW
1196 rect.SetX(in_rect.x);
1197 rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2));
4953f8cf
BW
1198 rect.SetWidth(bmp.GetWidth());
1199 rect.SetHeight(bmp.GetHeight());
1200 }
cedd7b22 1201 else
4953f8cf 1202 {
25d7497c
BW
1203 rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
1204 ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
4953f8cf
BW
1205 bmp.GetWidth(), bmp.GetHeight());
1206 }
7baac3cb
VZ
1207
1208
b0d17f7c 1209 DrawButtons(dc, rect, bmp, *wxWHITE, button_state);
7baac3cb 1210
4953f8cf
BW
1211 *out_rect = rect;
1212}
1213
793d4365
BW
1214int wxAuiSimpleTabArt::ShowDropDown(wxWindow* wnd,
1215 const wxAuiNotebookPageArray& pages,
1216 int active_idx)
01372b8f 1217{
c58ba15f 1218 wxMenu menuPopup;
01372b8f 1219
793d4365 1220 size_t i, count = pages.GetCount();
01372b8f
BW
1221 for (i = 0; i < count; ++i)
1222 {
793d4365
BW
1223 const wxAuiNotebookPage& page = pages.Item(i);
1224 menuPopup.AppendCheckItem(1000+i, page.caption);
01372b8f 1225 }
7baac3cb 1226
01372b8f
BW
1227 if (active_idx != -1)
1228 {
1229 menuPopup.Check(1000+active_idx, true);
1230 }
7baac3cb 1231
01372b8f
BW
1232 // find out where to put the popup menu of window
1233 // items. Subtract 100 for now to center the menu
1234 // a bit, until a better mechanism can be implemented
1235 wxPoint pt = ::wxGetMousePosition();
1236 pt = wnd->ScreenToClient(pt);
1237 if (pt.x < 100)
1238 pt.x = 0;
cedd7b22 1239 else
01372b8f 1240 pt.x -= 100;
7baac3cb 1241
01372b8f
BW
1242 // find out the screen coordinate at the bottom of the tab ctrl
1243 wxRect cli_rect = wnd->GetClientRect();
1244 pt.y = cli_rect.y + cli_rect.height;
7baac3cb 1245
01372b8f
BW
1246 wxAuiCommandCapture* cc = new wxAuiCommandCapture;
1247 wnd->PushEventHandler(cc);
1248 wnd->PopupMenu(&menuPopup, pt);
1249 int command = cc->GetCommandId();
1250 wnd->PopEventHandler(true);
7baac3cb 1251
01372b8f
BW
1252 if (command >= 1000)
1253 return command-1000;
7baac3cb 1254
01372b8f
BW
1255 return -1;
1256}
1257
2b9aac33 1258int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow* wnd,
793d4365 1259 const wxAuiNotebookPageArray& WXUNUSED(pages),
9fbb7d80 1260 const wxSize& WXUNUSED(required_bmp_size))
a4c8fc23
BW
1261{
1262 wxClientDC dc(wnd);
1263 dc.SetFont(m_measuring_font);
1264 int x_ext = 0;
a6b0e5bd 1265 wxSize s = GetTabSize(dc,
01372b8f
BW
1266 wnd,
1267 wxT("ABCDEFGHIj"),
2b9aac33 1268 wxNullBitmap,
01372b8f
BW
1269 true,
1270 wxAUI_BUTTON_STATE_HIDDEN,
1271 &x_ext);
a4c8fc23
BW
1272 return s.y+3;
1273}
4953f8cf 1274
b0d17f7c 1275void wxAuiSimpleTabArt::SetNormalFont(const wxFont& font)
3f69756e
BW
1276{
1277 m_normal_font = font;
1278}
1279
b0d17f7c 1280void wxAuiSimpleTabArt::SetSelectedFont(const wxFont& font)
3f69756e
BW
1281{
1282 m_selected_font = font;
1283}
1284
b0d17f7c 1285void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont& font)
3f69756e
BW
1286{
1287 m_measuring_font = font;
1288}
1289
1290
1291
1292
3f69756e
BW
1293// -- wxAuiTabContainer class implementation --
1294
1295
1296// wxAuiTabContainer is a class which contains information about each
1297// tab. It also can render an entire tab control to a specified DC.
1298// It's not a window class itself, because this code will be used by
1299// the wxFrameMananger, where it is disadvantageous to have separate
1300// windows for each tab control in the case of "docked tabs"
1301
1302// A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1303// which can be used as a tab control in the normal sense.
1304
1305
1306wxAuiTabContainer::wxAuiTabContainer()
1307{
4953f8cf 1308 m_tab_offset = 0;
702b1c7e 1309 m_flags = 0;
a3a5df9d 1310 m_art = new wxAuiDefaultTabArt;
7baac3cb
VZ
1311
1312 AddButton(wxAUI_BUTTON_LEFT, wxLEFT);
01372b8f
BW
1313 AddButton(wxAUI_BUTTON_RIGHT, wxRIGHT);
1314 AddButton(wxAUI_BUTTON_WINDOWLIST, wxRIGHT);
4953f8cf 1315 AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT);
3f69756e
BW
1316}
1317
fe498448
BW
1318wxAuiTabContainer::~wxAuiTabContainer()
1319{
3f69756e
BW
1320 delete m_art;
1321}
1322
a3a5df9d 1323void wxAuiTabContainer::SetArtProvider(wxAuiTabArt* art)
3f69756e
BW
1324{
1325 delete m_art;
1326 m_art = art;
7baac3cb 1327
b0d17f7c
BW
1328 if (m_art)
1329 {
1330 m_art->SetFlags(m_flags);
1331 }
3f69756e
BW
1332}
1333
e0dc13d4 1334wxAuiTabArt* wxAuiTabContainer::GetArtProvider() const
3f69756e
BW
1335{
1336 return m_art;
fe498448
BW
1337}
1338
702b1c7e
BW
1339void wxAuiTabContainer::SetFlags(unsigned int flags)
1340{
1341 m_flags = flags;
7baac3cb 1342
41b76acd 1343 // check for new close button settings
7baac3cb 1344 RemoveButton(wxAUI_BUTTON_LEFT);
01372b8f
BW
1345 RemoveButton(wxAUI_BUTTON_RIGHT);
1346 RemoveButton(wxAUI_BUTTON_WINDOWLIST);
41b76acd 1347 RemoveButton(wxAUI_BUTTON_CLOSE);
7baac3cb
VZ
1348
1349
01372b8f
BW
1350 if (flags & wxAUI_NB_SCROLL_BUTTONS)
1351 {
7baac3cb 1352 AddButton(wxAUI_BUTTON_LEFT, wxLEFT);
01372b8f
BW
1353 AddButton(wxAUI_BUTTON_RIGHT, wxRIGHT);
1354 }
1355
1356 if (flags & wxAUI_NB_WINDOWLIST_BUTTON)
1357 {
1358 AddButton(wxAUI_BUTTON_WINDOWLIST, wxRIGHT);
1359 }
7baac3cb 1360
41b76acd
BW
1361 if (flags & wxAUI_NB_CLOSE_BUTTON)
1362 {
1363 AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT);
1364 }
7baac3cb 1365
b0d17f7c
BW
1366 if (m_art)
1367 {
1368 m_art->SetFlags(m_flags);
1369 }
702b1c7e
BW
1370}
1371
1372unsigned int wxAuiTabContainer::GetFlags() const
1373{
1374 return m_flags;
1375}
1376
1377
cd05bf23
BW
1378void wxAuiTabContainer::SetNormalFont(const wxFont& font)
1379{
3f69756e 1380 m_art->SetNormalFont(font);
cd05bf23
BW
1381}
1382
1383void wxAuiTabContainer::SetSelectedFont(const wxFont& font)
1384{
3f69756e 1385 m_art->SetSelectedFont(font);
cd05bf23
BW
1386}
1387
1388void wxAuiTabContainer::SetMeasuringFont(const wxFont& font)
1389{
3f69756e 1390 m_art->SetMeasuringFont(font);
cd05bf23
BW
1391}
1392
ceb9b8db
VZ
1393void wxAuiTabContainer::SetColour(const wxColour& colour)
1394{
1395 m_art->SetColour(colour);
1396}
1397
1398void wxAuiTabContainer::SetActiveColour(const wxColour& colour)
1399{
1400 m_art->SetActiveColour(colour);
1401}
1402
cd05bf23
BW
1403void wxAuiTabContainer::SetRect(const wxRect& rect)
1404{
1405 m_rect = rect;
7baac3cb 1406
b0d17f7c
BW
1407 if (m_art)
1408 {
1409 m_art->SetSizingInfo(rect.GetSize(), m_pages.GetCount());
1410 }
cd05bf23
BW
1411}
1412
1413bool wxAuiTabContainer::AddPage(wxWindow* page,
1414 const wxAuiNotebookPage& info)
1415{
1416 wxAuiNotebookPage page_info;
1417 page_info = info;
1418 page_info.window = page;
4444d148 1419
cd05bf23
BW
1420 m_pages.Add(page_info);
1421
b0d17f7c
BW
1422 // let the art provider know how many pages we have
1423 if (m_art)
1424 {
1425 m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
1426 }
7baac3cb 1427
cd05bf23
BW
1428 return true;
1429}
1430
1431bool wxAuiTabContainer::InsertPage(wxWindow* page,
1432 const wxAuiNotebookPage& info,
1433 size_t idx)
1434{
1435 wxAuiNotebookPage page_info;
1436 page_info = info;
1437 page_info.window = page;
4444d148 1438
cd05bf23
BW
1439 if (idx >= m_pages.GetCount())
1440 m_pages.Add(page_info);
cedd7b22 1441 else
cd05bf23
BW
1442 m_pages.Insert(page_info, idx);
1443
b0d17f7c
BW
1444 // let the art provider know how many pages we have
1445 if (m_art)
1446 {
1447 m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
1448 }
7baac3cb 1449
cd05bf23
BW
1450 return true;
1451}
1452
2fadbbfd
BW
1453bool wxAuiTabContainer::MovePage(wxWindow* page,
1454 size_t new_idx)
1455{
1456 int idx = GetIdxFromWindow(page);
1457 if (idx == -1)
1458 return false;
7baac3cb 1459
2fadbbfd
BW
1460 // get page entry, make a copy of it
1461 wxAuiNotebookPage p = GetPage(idx);
7baac3cb 1462
2fadbbfd
BW
1463 // remove old page entry
1464 RemovePage(page);
7baac3cb 1465
2fadbbfd
BW
1466 // insert page where it should be
1467 InsertPage(page, p, new_idx);
7baac3cb 1468
2fadbbfd
BW
1469 return true;
1470}
1471
cd05bf23
BW
1472bool wxAuiTabContainer::RemovePage(wxWindow* wnd)
1473{
1474 size_t i, page_count = m_pages.GetCount();
1475 for (i = 0; i < page_count; ++i)
1476 {
1477 wxAuiNotebookPage& page = m_pages.Item(i);
1478 if (page.window == wnd)
1479 {
1480 m_pages.RemoveAt(i);
7baac3cb 1481
b0d17f7c
BW
1482 // let the art provider know how many pages we have
1483 if (m_art)
1484 {
1485 m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
1486 }
7baac3cb 1487
cd05bf23
BW
1488 return true;
1489 }
1490 }
4444d148 1491
cd05bf23
BW
1492 return false;
1493}
1494
1495bool wxAuiTabContainer::SetActivePage(wxWindow* wnd)
1496{
1497 bool found = false;
4444d148 1498
cd05bf23
BW
1499 size_t i, page_count = m_pages.GetCount();
1500 for (i = 0; i < page_count; ++i)
1501 {
1502 wxAuiNotebookPage& page = m_pages.Item(i);
1503 if (page.window == wnd)
1504 {
1505 page.active = true;
1506 found = true;
1507 }
cedd7b22 1508 else
cd05bf23
BW
1509 {
1510 page.active = false;
1511 }
1512 }
4444d148 1513
cd05bf23
BW
1514 return found;
1515}
1516
1517void wxAuiTabContainer::SetNoneActive()
1518{
1519 size_t i, page_count = m_pages.GetCount();
1520 for (i = 0; i < page_count; ++i)
1521 {
1522 wxAuiNotebookPage& page = m_pages.Item(i);
1523 page.active = false;
1524 }
1525}
1526
1527bool wxAuiTabContainer::SetActivePage(size_t page)
1528{
1529 if (page >= m_pages.GetCount())
1530 return false;
4444d148 1531
cd05bf23
BW
1532 return SetActivePage(m_pages.Item(page).window);
1533}
4444d148 1534
cd05bf23
BW
1535int wxAuiTabContainer::GetActivePage() const
1536{
1537 size_t i, page_count = m_pages.GetCount();
1538 for (i = 0; i < page_count; ++i)
1539 {
1540 wxAuiNotebookPage& page = m_pages.Item(i);
1541 if (page.active)
1542 return i;
1543 }
4444d148 1544
cd05bf23
BW
1545 return -1;
1546}
1547
1548wxWindow* wxAuiTabContainer::GetWindowFromIdx(size_t idx) const
1549{
1550 if (idx >= m_pages.GetCount())
1551 return NULL;
4444d148 1552
cd05bf23
BW
1553 return m_pages[idx].window;
1554}
1555
1556int wxAuiTabContainer::GetIdxFromWindow(wxWindow* wnd) const
1557{
849c353a
VZ
1558 const size_t page_count = m_pages.GetCount();
1559 for ( size_t i = 0; i < page_count; ++i )
cd05bf23
BW
1560 {
1561 wxAuiNotebookPage& page = m_pages.Item(i);
1562 if (page.window == wnd)
1563 return i;
1564 }
849c353a 1565 return wxNOT_FOUND;
cd05bf23
BW
1566}
1567
1568wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx)
1569{
1570 wxASSERT_MSG(idx < m_pages.GetCount(), wxT("Invalid Page index"));
1571
1572 return m_pages[idx];
1573}
1574
c3e016e4
JS
1575const wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx) const
1576{
1577 wxASSERT_MSG(idx < m_pages.GetCount(), wxT("Invalid Page index"));
1578
1579 return m_pages[idx];
1580}
1581
cd05bf23
BW
1582wxAuiNotebookPageArray& wxAuiTabContainer::GetPages()
1583{
1584 return m_pages;
1585}
1586
1587size_t wxAuiTabContainer::GetPageCount() const
1588{
1589 return m_pages.GetCount();
1590}
1591
4953f8cf
BW
1592void wxAuiTabContainer::AddButton(int id,
1593 int location,
1594 const wxBitmap& normal_bitmap,
1595 const wxBitmap& disabled_bitmap)
cd05bf23
BW
1596{
1597 wxAuiTabContainerButton button;
1598 button.id = id;
4953f8cf
BW
1599 button.bitmap = normal_bitmap;
1600 button.dis_bitmap = disabled_bitmap;
b6418695 1601 button.location = location;
cd05bf23 1602 button.cur_state = wxAUI_BUTTON_STATE_NORMAL;
4444d148 1603
cd05bf23
BW
1604 m_buttons.Add(button);
1605}
1606
41b76acd
BW
1607void wxAuiTabContainer::RemoveButton(int id)
1608{
1609 size_t i, button_count = m_buttons.GetCount();
1610
1611 for (i = 0; i < button_count; ++i)
1612 {
1613 if (m_buttons.Item(i).id == id)
1614 {
1615 m_buttons.RemoveAt(i);
1616 return;
1617 }
1618 }
1619}
1620
1621
1622
4953f8cf
BW
1623size_t wxAuiTabContainer::GetTabOffset() const
1624{
1625 return m_tab_offset;
1626}
cd05bf23 1627
4953f8cf
BW
1628void wxAuiTabContainer::SetTabOffset(size_t offset)
1629{
1630 m_tab_offset = offset;
1631}
cd05bf23 1632
b0d17f7c
BW
1633
1634
1635
cd05bf23
BW
1636// Render() renders the tab catalog to the specified DC
1637// It is a virtual function and can be overridden to
1638// provide custom drawing capabilities
01372b8f 1639void wxAuiTabContainer::Render(wxDC* raw_dc, wxWindow* wnd)
4444d148 1640{
a9eeb510
BW
1641 if (!raw_dc || !raw_dc->IsOk())
1642 return;
1643
cd05bf23 1644 wxMemoryDC dc;
ef329166
VZ
1645
1646 // use the same layout direction as the window DC uses to ensure that the
1647 // text is rendered correctly
1648 dc.SetLayoutDirection(raw_dc->GetLayoutDirection());
1649
cd05bf23 1650 wxBitmap bmp;
4953f8cf
BW
1651 size_t i;
1652 size_t page_count = m_pages.GetCount();
1653 size_t button_count = m_buttons.GetCount();
1654
1655 // create off-screen bitmap
cd05bf23
BW
1656 bmp.Create(m_rect.GetWidth(), m_rect.GetHeight());
1657 dc.SelectObject(bmp);
4444d148 1658
a9eeb510
BW
1659 if (!dc.IsOk())
1660 return;
4953f8cf
BW
1661
1662 // find out if size of tabs is larger than can be
1663 // afforded on screen
1664 int total_width = 0;
25d7497c 1665 int visible_width = 0;
4953f8cf
BW
1666 for (i = 0; i < page_count; ++i)
1667 {
1668 wxAuiNotebookPage& page = m_pages.Item(i);
7baac3cb 1669
702b1c7e
BW
1670 // determine if a close button is on this tab
1671 bool close_button = false;
1672 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
1673 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
1674 {
1675 close_button = true;
1676 }
7baac3cb
VZ
1677
1678
4953f8cf 1679 int x_extent = 0;
a6b0e5bd 1680 wxSize size = m_art->GetTabSize(dc,
01372b8f 1681 wnd,
41b76acd 1682 page.caption,
2b9aac33 1683 page.bitmap,
41b76acd
BW
1684 page.active,
1685 close_button ?
1686 wxAUI_BUTTON_STATE_NORMAL :
1687 wxAUI_BUTTON_STATE_HIDDEN,
1688 &x_extent);
7baac3cb 1689
4953f8cf
BW
1690 if (i+1 < page_count)
1691 total_width += x_extent;
cedd7b22 1692 else
4953f8cf 1693 total_width += size.x;
7baac3cb 1694
25d7497c
BW
1695 if (i >= m_tab_offset)
1696 {
1697 if (i+1 < page_count)
1698 visible_width += x_extent;
cedd7b22 1699 else
25d7497c
BW
1700 visible_width += size.x;
1701 }
4953f8cf 1702 }
7baac3cb 1703
b0d17f7c 1704 if (total_width > m_rect.GetWidth() || m_tab_offset != 0)
4953f8cf
BW
1705 {
1706 // show left/right buttons
1707 for (i = 0; i < button_count; ++i)
1708 {
1709 wxAuiTabContainerButton& button = m_buttons.Item(i);
1710 if (button.id == wxAUI_BUTTON_LEFT ||
1711 button.id == wxAUI_BUTTON_RIGHT)
1712 {
1713 button.cur_state &= ~wxAUI_BUTTON_STATE_HIDDEN;
1714 }
1715 }
1716 }
cedd7b22 1717 else
4953f8cf
BW
1718 {
1719 // hide left/right buttons
1720 for (i = 0; i < button_count; ++i)
1721 {
1722 wxAuiTabContainerButton& button = m_buttons.Item(i);
1723 if (button.id == wxAUI_BUTTON_LEFT ||
1724 button.id == wxAUI_BUTTON_RIGHT)
1725 {
1726 button.cur_state |= wxAUI_BUTTON_STATE_HIDDEN;
1727 }
1728 }
1729 }
1730
25d7497c
BW
1731 // determine whether left button should be enabled
1732 for (i = 0; i < button_count; ++i)
1733 {
1734 wxAuiTabContainerButton& button = m_buttons.Item(i);
1735 if (button.id == wxAUI_BUTTON_LEFT)
1736 {
1737 if (m_tab_offset == 0)
1738 button.cur_state |= wxAUI_BUTTON_STATE_DISABLED;
cedd7b22 1739 else
25d7497c
BW
1740 button.cur_state &= ~wxAUI_BUTTON_STATE_DISABLED;
1741 }
1742 if (button.id == wxAUI_BUTTON_RIGHT)
1743 {
1744 if (visible_width < m_rect.GetWidth() - ((int)button_count*16))
1745 button.cur_state |= wxAUI_BUTTON_STATE_DISABLED;
cedd7b22 1746 else
25d7497c
BW
1747 button.cur_state &= ~wxAUI_BUTTON_STATE_DISABLED;
1748 }
1749 }
1750
4953f8cf
BW
1751
1752
1753 // draw background
a6b0e5bd 1754 m_art->DrawBackground(dc, wnd, m_rect);
4444d148 1755
4953f8cf
BW
1756 // draw buttons
1757 int left_buttons_width = 0;
1758 int right_buttons_width = 0;
7baac3cb 1759
cd05bf23 1760 int offset = 0;
b6418695
BW
1761
1762 // draw the buttons on the right side
1763 offset = m_rect.x + m_rect.width;
b6418695
BW
1764 for (i = 0; i < button_count; ++i)
1765 {
1766 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
7baac3cb 1767
b6418695
BW
1768 if (button.location != wxRIGHT)
1769 continue;
4953f8cf
BW
1770 if (button.cur_state & wxAUI_BUTTON_STATE_HIDDEN)
1771 continue;
7baac3cb 1772
4953f8cf
BW
1773 wxRect button_rect = m_rect;
1774 button_rect.SetY(1);
1775 button_rect.SetWidth(offset);
1776
a6b0e5bd 1777 m_art->DrawButton(dc,
01372b8f 1778 wnd,
4953f8cf
BW
1779 button_rect,
1780 button.id,
1781 button.cur_state,
1782 wxRIGHT,
4953f8cf
BW
1783 &button.rect);
1784
1785 offset -= button.rect.GetWidth();
1786 right_buttons_width += button.rect.GetWidth();
b6418695
BW
1787 }
1788
1789
1790
1791 offset = 0;
7baac3cb 1792
b6418695
BW
1793 // draw the buttons on the left side
1794
1795 for (i = 0; i < button_count; ++i)
1796 {
1797 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
7baac3cb 1798
b6418695
BW
1799 if (button.location != wxLEFT)
1800 continue;
4953f8cf
BW
1801 if (button.cur_state & wxAUI_BUTTON_STATE_HIDDEN)
1802 continue;
7baac3cb 1803
4953f8cf
BW
1804 wxRect button_rect(offset, 1, 1000, m_rect.height);
1805
a6b0e5bd 1806 m_art->DrawButton(dc,
01372b8f 1807 wnd,
4953f8cf
BW
1808 button_rect,
1809 button.id,
1810 button.cur_state,
1811 wxLEFT,
4953f8cf 1812 &button.rect);
7baac3cb 1813
4953f8cf
BW
1814 offset += button.rect.GetWidth();
1815 left_buttons_width += button.rect.GetWidth();
b6418695
BW
1816 }
1817
4953f8cf 1818 offset = left_buttons_width;
7baac3cb 1819
b0d17f7c 1820 if (offset == 0)
7baac3cb
VZ
1821 offset += m_art->GetIndentSize();
1822
1823
41b76acd 1824 // prepare the tab-close-button array
049333c2
BW
1825 // make sure tab button entries which aren't used are marked as hidden
1826 for (i = page_count; i < m_tab_close_buttons.GetCount(); ++i)
1827 m_tab_close_buttons.Item(i).cur_state = wxAUI_BUTTON_STATE_HIDDEN;
7baac3cb 1828
049333c2 1829 // make sure there are enough tab button entries to accommodate all tabs
41b76acd
BW
1830 while (m_tab_close_buttons.GetCount() < page_count)
1831 {
1832 wxAuiTabContainerButton tempbtn;
1833 tempbtn.id = wxAUI_BUTTON_CLOSE;
1834 tempbtn.location = wxCENTER;
1835 tempbtn.cur_state = wxAUI_BUTTON_STATE_HIDDEN;
1836 m_tab_close_buttons.Add(tempbtn);
1837 }
7baac3cb
VZ
1838
1839
4abf84fb 1840 // buttons before the tab offset must be set to hidden
41b76acd
BW
1841 for (i = 0; i < m_tab_offset; ++i)
1842 {
41b76acd
BW
1843 m_tab_close_buttons.Item(i).cur_state = wxAUI_BUTTON_STATE_HIDDEN;
1844 }
7baac3cb
VZ
1845
1846
b6418695 1847 // draw the tabs
cd05bf23
BW
1848
1849 size_t active = 999;
1850 int active_offset = 0;
b0d17f7c 1851 wxRect active_rect;
4444d148 1852
cd05bf23
BW
1853 int x_extent = 0;
1854 wxRect rect = m_rect;
1855 rect.y = 0;
cd05bf23 1856 rect.height = m_rect.height;
4444d148 1857
4953f8cf 1858 for (i = m_tab_offset; i < page_count; ++i)
cd05bf23
BW
1859 {
1860 wxAuiNotebookPage& page = m_pages.Item(i);
41b76acd 1861 wxAuiTabContainerButton& tab_button = m_tab_close_buttons.Item(i);
4444d148 1862
702b1c7e 1863 // determine if a close button is on this tab
702b1c7e
BW
1864 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
1865 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
1866 {
41b76acd
BW
1867 if (tab_button.cur_state == wxAUI_BUTTON_STATE_HIDDEN)
1868 {
1869 tab_button.id = wxAUI_BUTTON_CLOSE;
1870 tab_button.cur_state = wxAUI_BUTTON_STATE_NORMAL;
1871 tab_button.location = wxCENTER;
1872 }
1873 }
cedd7b22 1874 else
41b76acd
BW
1875 {
1876 tab_button.cur_state = wxAUI_BUTTON_STATE_HIDDEN;
702b1c7e
BW
1877 }
1878
cd05bf23 1879 rect.x = offset;
b0d17f7c
BW
1880 rect.width = m_rect.width - right_buttons_width - offset - 2;
1881
47b6bebb
BW
1882 if (rect.width <= 0)
1883 break;
1884
a6b0e5bd 1885 m_art->DrawTab(dc,
01372b8f 1886 wnd,
793d4365 1887 page,
01372b8f 1888 rect,
01372b8f
BW
1889 tab_button.cur_state,
1890 &page.rect,
1891 &tab_button.rect,
1892 &x_extent);
4444d148 1893
cd05bf23
BW
1894 if (page.active)
1895 {
1896 active = i;
1897 active_offset = offset;
b0d17f7c 1898 active_rect = rect;
cd05bf23 1899 }
7baac3cb 1900
cd05bf23
BW
1901 offset += x_extent;
1902 }
4444d148 1903
4abf84fb
BW
1904
1905 // make sure to deactivate buttons which are off the screen to the right
1906 for (++i; i < m_tab_close_buttons.GetCount(); ++i)
1907 {
1908 m_tab_close_buttons.Item(i).cur_state = wxAUI_BUTTON_STATE_HIDDEN;
1909 }
1910
1911
cd05bf23 1912 // draw the active tab again so it stands in the foreground
4953f8cf 1913 if (active >= m_tab_offset && active < m_pages.GetCount())
cd05bf23
BW
1914 {
1915 wxAuiNotebookPage& page = m_pages.Item(active);
1916
41b76acd
BW
1917 wxAuiTabContainerButton& tab_button = m_tab_close_buttons.Item(active);
1918
cd05bf23 1919 rect.x = active_offset;
a6b0e5bd 1920 m_art->DrawTab(dc,
01372b8f 1921 wnd,
793d4365 1922 page,
b0d17f7c 1923 active_rect,
01372b8f
BW
1924 tab_button.cur_state,
1925 &page.rect,
1926 &tab_button.rect,
1927 &x_extent);
cd05bf23 1928 }
4444d148 1929
7baac3cb 1930
4953f8cf
BW
1931 raw_dc->Blit(m_rect.x, m_rect.y,
1932 m_rect.GetWidth(), m_rect.GetHeight(),
1933 &dc, 0, 0);
cd05bf23
BW
1934}
1935
a0c2e4a0
JS
1936// Is the tab visible?
1937bool wxAuiTabContainer::IsTabVisible(int tabPage, int tabOffset, wxDC* dc, wxWindow* wnd)
1938{
1939 if (!dc || !dc->IsOk())
1940 return false;
1941
1942 size_t i;
1943 size_t page_count = m_pages.GetCount();
1944 size_t button_count = m_buttons.GetCount();
1945
1946 // Hasn't been rendered yet; assume it's visible
1947 if (m_tab_close_buttons.GetCount() < page_count)
1948 return true;
1949
1950 // First check if both buttons are disabled - if so, there's no need to
1951 // check further for visibility.
1952 int arrowButtonVisibleCount = 0;
1953 for (i = 0; i < button_count; ++i)
1954 {
1955 wxAuiTabContainerButton& button = m_buttons.Item(i);
1956 if (button.id == wxAUI_BUTTON_LEFT ||
1957 button.id == wxAUI_BUTTON_RIGHT)
1958 {
1959 if ((button.cur_state & wxAUI_BUTTON_STATE_HIDDEN) == 0)
1960 arrowButtonVisibleCount ++;
1961 }
1962 }
1963
1964 // Tab must be visible
1965 if (arrowButtonVisibleCount == 0)
1966 return true;
1967
1968 // If tab is less than the given offset, it must be invisible by definition
1969 if (tabPage < tabOffset)
1970 return false;
1971
1972 // draw buttons
1973 int left_buttons_width = 0;
1974 int right_buttons_width = 0;
1975
1976 int offset = 0;
1977
1978 // calculate size of the buttons on the right side
1979 offset = m_rect.x + m_rect.width;
1980 for (i = 0; i < button_count; ++i)
1981 {
1982 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
1983
1984 if (button.location != wxRIGHT)
1985 continue;
1986 if (button.cur_state & wxAUI_BUTTON_STATE_HIDDEN)
1987 continue;
1988
1989 offset -= button.rect.GetWidth();
1990 right_buttons_width += button.rect.GetWidth();
1991 }
1992
1993 offset = 0;
1994
1995 // calculate size of the buttons on the left side
1996 for (i = 0; i < button_count; ++i)
1997 {
1998 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
1999
2000 if (button.location != wxLEFT)
2001 continue;
2002 if (button.cur_state & wxAUI_BUTTON_STATE_HIDDEN)
2003 continue;
2004
2005 offset += button.rect.GetWidth();
2006 left_buttons_width += button.rect.GetWidth();
2007 }
2008
2009 offset = left_buttons_width;
2010
2011 if (offset == 0)
2012 offset += m_art->GetIndentSize();
2013
2014 wxRect active_rect;
2015
2016 wxRect rect = m_rect;
2017 rect.y = 0;
2018 rect.height = m_rect.height;
2019
2020 // See if the given page is visible at the given tab offset (effectively scroll position)
2021 for (i = tabOffset; i < page_count; ++i)
2022 {
2023 wxAuiNotebookPage& page = m_pages.Item(i);
2024 wxAuiTabContainerButton& tab_button = m_tab_close_buttons.Item(i);
2025
a0c2e4a0
JS
2026 rect.x = offset;
2027 rect.width = m_rect.width - right_buttons_width - offset - 2;
2028
2029 if (rect.width <= 0)
2030 return false; // haven't found the tab, and we've run out of space, so return false
2031
2032 int x_extent = 0;
2033 wxSize size = m_art->GetTabSize(*dc,
2034 wnd,
2035 page.caption,
2036 page.bitmap,
2037 page.active,
2038 tab_button.cur_state,
2039 &x_extent);
2040
2041 offset += x_extent;
2042
2043 if (i == (size_t) tabPage)
2044 {
2045 // If not all of the tab is visible, and supposing there's space to display it all,
2046 // we could do better so we return false.
2047 if (((m_rect.width - right_buttons_width - offset - 2) <= 0) && ((m_rect.width - right_buttons_width - left_buttons_width) > x_extent))
2048 return false;
2049 else
2050 return true;
2051 }
2052 }
2053
2054 // Shouldn't really get here, but if it does, assume the tab is visible to prevent
2055 // further looping in calling code.
2056 return true;
2057}
2058
2059// Make the tab visible if it wasn't already
2060void wxAuiTabContainer::MakeTabVisible(int tabPage, wxWindow* win)
2061{
2062 wxClientDC dc(win);
2063 if (!IsTabVisible(tabPage, GetTabOffset(), & dc, win))
2064 {
2065 int i;
2066 for (i = 0; i < (int) m_pages.GetCount(); i++)
2067 {
2068 if (IsTabVisible(tabPage, i, & dc, win))
2069 {
2070 SetTabOffset(i);
2071 win->Refresh();
2072 return;
2073 }
2074 }
2075 }
2076}
cd05bf23
BW
2077
2078// TabHitTest() tests if a tab was hit, passing the window pointer
2079// back if that condition was fulfilled. The function returns
2080// true if a tab was hit, otherwise false
2081bool wxAuiTabContainer::TabHitTest(int x, int y, wxWindow** hit) const
2082{
22a35096 2083 if (!m_rect.Contains(x,y))
cd05bf23 2084 return false;
7baac3cb 2085
41b76acd 2086 wxAuiTabContainerButton* btn = NULL;
65052c6f 2087 if (ButtonHitTest(x, y, &btn) && !(btn->cur_state & wxAUI_BUTTON_STATE_DISABLED))
41b76acd
BW
2088 {
2089 if (m_buttons.Index(*btn) != wxNOT_FOUND)
2090 return false;
2091 }
4444d148 2092
cd05bf23 2093 size_t i, page_count = m_pages.GetCount();
4444d148 2094
4953f8cf 2095 for (i = m_tab_offset; i < page_count; ++i)
cd05bf23
BW
2096 {
2097 wxAuiNotebookPage& page = m_pages.Item(i);
22a35096 2098 if (page.rect.Contains(x,y))
cd05bf23 2099 {
4953f8cf
BW
2100 if (hit)
2101 *hit = page.window;
cd05bf23
BW
2102 return true;
2103 }
2104 }
4444d148 2105
cd05bf23
BW
2106 return false;
2107}
2108
2109// ButtonHitTest() tests if a button was hit. The function returns
2110// true if a button was hit, otherwise false
2111bool wxAuiTabContainer::ButtonHitTest(int x, int y,
2112 wxAuiTabContainerButton** hit) const
2113{
22a35096 2114 if (!m_rect.Contains(x,y))
cd05bf23 2115 return false;
4444d148 2116
41b76acd 2117 size_t i, button_count;
7baac3cb
VZ
2118
2119
41b76acd 2120 button_count = m_buttons.GetCount();
cd05bf23
BW
2121 for (i = 0; i < button_count; ++i)
2122 {
2123 wxAuiTabContainerButton& button = m_buttons.Item(i);
9b405ab3 2124 if (button.rect.Contains(x,y) &&
65052c6f 2125 !(button.cur_state & wxAUI_BUTTON_STATE_HIDDEN ))
cd05bf23 2126 {
4953f8cf
BW
2127 if (hit)
2128 *hit = &button;
cd05bf23
BW
2129 return true;
2130 }
2131 }
7baac3cb 2132
41b76acd
BW
2133 button_count = m_tab_close_buttons.GetCount();
2134 for (i = 0; i < button_count; ++i)
2135 {
2136 wxAuiTabContainerButton& button = m_tab_close_buttons.Item(i);
9b405ab3
BW
2137 if (button.rect.Contains(x,y) &&
2138 !(button.cur_state & (wxAUI_BUTTON_STATE_HIDDEN |
2139 wxAUI_BUTTON_STATE_DISABLED)))
41b76acd
BW
2140 {
2141 if (hit)
2142 *hit = &button;
2143 return true;
2144 }
2145 }
7baac3cb 2146
cd05bf23
BW
2147 return false;
2148}
2149
2150
2151
2152// the utility function ShowWnd() is the same as show,
a3a5df9d 2153// except it handles wxAuiMDIChildFrame windows as well,
cd05bf23
BW
2154// as the Show() method on this class is "unplugged"
2155static void ShowWnd(wxWindow* wnd, bool show)
2156{
89272c55 2157#if wxUSE_MDI
a3a5df9d 2158 if (wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
cd05bf23 2159 {
a3a5df9d 2160 wxAuiMDIChildFrame* cf = (wxAuiMDIChildFrame*)wnd;
cd05bf23
BW
2161 cf->DoShow(show);
2162 }
cedd7b22 2163 else
89272c55 2164#endif
cd05bf23
BW
2165 {
2166 wnd->Show(show);
2167 }
2168}
2169
2170
2171// DoShowHide() this function shows the active window, then
2172// hides all of the other windows (in that order)
2173void wxAuiTabContainer::DoShowHide()
2174{
2175 wxAuiNotebookPageArray& pages = GetPages();
2176 size_t i, page_count = pages.GetCount();
2177
2178 // show new active page first
2179 for (i = 0; i < page_count; ++i)
2180 {
2181 wxAuiNotebookPage& page = pages.Item(i);
2182 if (page.active)
2183 {
2184 ShowWnd(page.window, true);
2185 break;
2186 }
2187 }
2188
2189 // hide all other pages
2190 for (i = 0; i < page_count; ++i)
2191 {
2192 wxAuiNotebookPage& page = pages.Item(i);
badcaaaf
BW
2193 if (!page.active)
2194 ShowWnd(page.window, false);
cd05bf23
BW
2195 }
2196}
2197
2198
2199
2200
2201
2202
2203// -- wxAuiTabCtrl class implementation --
2204
2205
cd05bf23
BW
2206
2207BEGIN_EVENT_TABLE(wxAuiTabCtrl, wxControl)
2208 EVT_PAINT(wxAuiTabCtrl::OnPaint)
2209 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground)
2210 EVT_SIZE(wxAuiTabCtrl::OnSize)
2211 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown)
198be845 2212 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDClick)
cd05bf23 2213 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp)
69f5e420
BW
2214 EVT_MIDDLE_DOWN(wxAuiTabCtrl::OnMiddleDown)
2215 EVT_MIDDLE_UP(wxAuiTabCtrl::OnMiddleUp)
2216 EVT_RIGHT_DOWN(wxAuiTabCtrl::OnRightDown)
2217 EVT_RIGHT_UP(wxAuiTabCtrl::OnRightUp)
cd05bf23
BW
2218 EVT_MOTION(wxAuiTabCtrl::OnMotion)
2219 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow)
c58ba15f 2220 EVT_AUINOTEBOOK_BUTTON(wxID_ANY, wxAuiTabCtrl::OnButton)
a0c2e4a0
JS
2221 EVT_SET_FOCUS(wxAuiTabCtrl::OnSetFocus)
2222 EVT_KILL_FOCUS(wxAuiTabCtrl::OnKillFocus)
2223 EVT_CHAR(wxAuiTabCtrl::OnChar)
45ca0e77 2224 EVT_MOUSE_CAPTURE_LOST(wxAuiTabCtrl::OnCaptureLost)
cd05bf23
BW
2225END_EVENT_TABLE()
2226
2227
2228wxAuiTabCtrl::wxAuiTabCtrl(wxWindow* parent,
2229 wxWindowID id,
2230 const wxPoint& pos,
2231 const wxSize& size,
4444d148 2232 long style) : wxControl(parent, id, pos, size, style)
cd05bf23 2233{
c7bfb76a 2234 SetName(wxT("wxAuiTabCtrl"));
cd05bf23
BW
2235 m_click_pt = wxDefaultPosition;
2236 m_is_dragging = false;
2237 m_hover_button = NULL;
9b3f654a 2238 m_pressed_button = NULL;
cd05bf23
BW
2239}
2240
26da5e4f
BW
2241wxAuiTabCtrl::~wxAuiTabCtrl()
2242{
2243}
cd05bf23
BW
2244
2245void wxAuiTabCtrl::OnPaint(wxPaintEvent&)
2246{
2247 wxPaintDC dc(this);
4444d148 2248
cd05bf23 2249 dc.SetFont(GetFont());
4444d148 2250
cd05bf23 2251 if (GetPageCount() > 0)
01372b8f 2252 Render(&dc, this);
cd05bf23
BW
2253}
2254
2255void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
2256{
2257}
2258
2259void wxAuiTabCtrl::OnSize(wxSizeEvent& evt)
2260{
2261 wxSize s = evt.GetSize();
2262 wxRect r(0, 0, s.GetWidth(), s.GetHeight());
2263 SetRect(r);
2264}
2265
2266void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt)
2267{
2268 CaptureMouse();
2269 m_click_pt = wxDefaultPosition;
2270 m_is_dragging = false;
08c068a4 2271 m_click_tab = NULL;
9b3f654a 2272 m_pressed_button = NULL;
4444d148 2273
760d3542 2274
cd05bf23
BW
2275 wxWindow* wnd;
2276 if (TabHitTest(evt.m_x, evt.m_y, &wnd))
9b405ab3 2277 {
049333c2 2278 int new_selection = GetIdxFromWindow(wnd);
7baac3cb 2279
68fd4f2c
BW
2280 // wxAuiNotebooks always want to receive this event
2281 // even if the tab is already active, because they may
2282 // have multiple tab controls
2283 if (new_selection != GetActivePage() ||
2284 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook)))
049333c2
BW
2285 {
2286 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
2287 e.SetSelection(new_selection);
2288 e.SetOldSelection(GetActivePage());
2289 e.SetEventObject(this);
2290 GetEventHandler()->ProcessEvent(e);
2291 }
4444d148 2292
cd05bf23
BW
2293 m_click_pt.x = evt.m_x;
2294 m_click_pt.y = evt.m_y;
08c068a4 2295 m_click_tab = wnd;
cd05bf23 2296 }
7baac3cb 2297
cd05bf23
BW
2298 if (m_hover_button)
2299 {
9b3f654a
BW
2300 m_pressed_button = m_hover_button;
2301 m_pressed_button->cur_state = wxAUI_BUTTON_STATE_PRESSED;
cd05bf23
BW
2302 Refresh();
2303 Update();
2304 }
2305}
2306
45ca0e77
BW
2307void wxAuiTabCtrl::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
2308{
2309}
2310
9b3f654a 2311void wxAuiTabCtrl::OnLeftUp(wxMouseEvent& evt)
cd05bf23
BW
2312{
2313 if (GetCapture() == this)
2314 ReleaseMouse();
4444d148 2315
cd05bf23
BW
2316 if (m_is_dragging)
2317 {
d16619f8 2318 m_is_dragging = false;
cedd7b22 2319
cd05bf23 2320 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, m_windowId);
08c068a4
BW
2321 evt.SetSelection(GetIdxFromWindow(m_click_tab));
2322 evt.SetOldSelection(evt.GetSelection());
cd05bf23
BW
2323 evt.SetEventObject(this);
2324 GetEventHandler()->ProcessEvent(evt);
cedd7b22 2325
cd05bf23
BW
2326 return;
2327 }
4444d148 2328
9b3f654a 2329 if (m_pressed_button)
cd05bf23 2330 {
9b3f654a
BW
2331 // make sure we're still clicking the button
2332 wxAuiTabContainerButton* button = NULL;
65052c6f
VZ
2333 if (!ButtonHitTest(evt.m_x, evt.m_y, &button) ||
2334 button->cur_state & wxAUI_BUTTON_STATE_DISABLED)
9b3f654a 2335 return;
7baac3cb 2336
9b3f654a
BW
2337 if (button != m_pressed_button)
2338 {
2339 m_pressed_button = NULL;
2340 return;
2341 }
2342
cd05bf23
BW
2343 Refresh();
2344 Update();
4444d148 2345
9b3f654a 2346 if (!(m_pressed_button->cur_state & wxAUI_BUTTON_STATE_DISABLED))
25d7497c
BW
2347 {
2348 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_windowId);
9b362935 2349 evt.SetSelection(GetIdxFromWindow(m_click_tab));
9b3f654a 2350 evt.SetInt(m_pressed_button->id);
25d7497c
BW
2351 evt.SetEventObject(this);
2352 GetEventHandler()->ProcessEvent(evt);
2353 }
7baac3cb 2354
9b3f654a 2355 m_pressed_button = NULL;
cd05bf23 2356 }
4444d148 2357
cd05bf23
BW
2358 m_click_pt = wxDefaultPosition;
2359 m_is_dragging = false;
08c068a4 2360 m_click_tab = NULL;
cd05bf23
BW
2361}
2362
69f5e420
BW
2363void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent& evt)
2364{
2365 wxWindow* wnd = NULL;
2366 if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
2367 return;
2368
2369 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, m_windowId);
2370 e.SetEventObject(this);
2371 e.SetSelection(GetIdxFromWindow(wnd));
2372 GetEventHandler()->ProcessEvent(e);
2373}
2374
2375void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent& evt)
2376{
2377 wxWindow* wnd = NULL;
2378 if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
2379 return;
2380
2381 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, m_windowId);
2382 e.SetEventObject(this);
2383 e.SetSelection(GetIdxFromWindow(wnd));
2384 GetEventHandler()->ProcessEvent(e);
2385}
2386
2387void wxAuiTabCtrl::OnRightUp(wxMouseEvent& evt)
2388{
2389 wxWindow* wnd = NULL;
2390 if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
2391 return;
2392
2393 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, m_windowId);
2394 e.SetEventObject(this);
2395 e.SetSelection(GetIdxFromWindow(wnd));
2396 GetEventHandler()->ProcessEvent(e);
2397}
2398
2399void wxAuiTabCtrl::OnRightDown(wxMouseEvent& evt)
2400{
2401 wxWindow* wnd = NULL;
2402 if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
2403 return;
2404
2405 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, m_windowId);
2406 e.SetEventObject(this);
2407 e.SetSelection(GetIdxFromWindow(wnd));
2408 GetEventHandler()->ProcessEvent(e);
2409}
2410
198be845
JS
2411void wxAuiTabCtrl::OnLeftDClick(wxMouseEvent& evt)
2412{
2413 wxWindow* wnd;
2414 wxAuiTabContainerButton* button;
2415 if (!TabHitTest(evt.m_x, evt.m_y, &wnd) && !ButtonHitTest(evt.m_x, evt.m_y, &button))
2416 {
2417 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, m_windowId);
2418 e.SetEventObject(this);
2419 GetEventHandler()->ProcessEvent(e);
2420 }
2421}
2422
cd05bf23
BW
2423void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt)
2424{
2425 wxPoint pos = evt.GetPosition();
2426
2427 // check if the mouse is hovering above a button
2428 wxAuiTabContainerButton* button;
65052c6f 2429 if (ButtonHitTest(pos.x, pos.y, &button) && !(button->cur_state & wxAUI_BUTTON_STATE_DISABLED))
cd05bf23 2430 {
b6418695
BW
2431 if (m_hover_button && button != m_hover_button)
2432 {
2433 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
2434 m_hover_button = NULL;
2435 Refresh();
2436 Update();
2437 }
7baac3cb 2438
cd05bf23
BW
2439 if (button->cur_state != wxAUI_BUTTON_STATE_HOVER)
2440 {
2441 button->cur_state = wxAUI_BUTTON_STATE_HOVER;
2442 Refresh();
2443 Update();
2444 m_hover_button = button;
2445 return;
2446 }
2447 }
cedd7b22 2448 else
cd05bf23
BW
2449 {
2450 if (m_hover_button)
2451 {
2452 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
2453 m_hover_button = NULL;
2454 Refresh();
2455 Update();
2456 }
2457 }
4444d148
WS
2458
2459
cd05bf23
BW
2460 if (!evt.LeftIsDown() || m_click_pt == wxDefaultPosition)
2461 return;
4444d148 2462
cd05bf23
BW
2463 if (m_is_dragging)
2464 {
2465 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, m_windowId);
08c068a4
BW
2466 evt.SetSelection(GetIdxFromWindow(m_click_tab));
2467 evt.SetOldSelection(evt.GetSelection());
cd05bf23
BW
2468 evt.SetEventObject(this);
2469 GetEventHandler()->ProcessEvent(evt);
2470 return;
4444d148
WS
2471 }
2472
2473
cd05bf23
BW
2474 int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
2475 int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
2476
2477 if (abs(pos.x - m_click_pt.x) > drag_x_threshold ||
2478 abs(pos.y - m_click_pt.y) > drag_y_threshold)
2479 {
2480 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, m_windowId);
08c068a4
BW
2481 evt.SetSelection(GetIdxFromWindow(m_click_tab));
2482 evt.SetOldSelection(evt.GetSelection());
cd05bf23
BW
2483 evt.SetEventObject(this);
2484 GetEventHandler()->ProcessEvent(evt);
4444d148 2485
cd05bf23
BW
2486 m_is_dragging = true;
2487 }
2488}
2489
2490void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event))
2491{
2492 if (m_hover_button)
2493 {
2494 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
2495 m_hover_button = NULL;
2496 Refresh();
2497 Update();
2498 }
2499}
2500
4953f8cf
BW
2501void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent& event)
2502{
2503 int button = event.GetInt();
7baac3cb 2504
4953f8cf
BW
2505 if (button == wxAUI_BUTTON_LEFT || button == wxAUI_BUTTON_RIGHT)
2506 {
2507 if (button == wxAUI_BUTTON_LEFT)
2508 {
2509 if (GetTabOffset() > 0)
2510 {
2511 SetTabOffset(GetTabOffset()-1);
2512 Refresh();
2513 Update();
2514 }
2515 }
cedd7b22 2516 else
4953f8cf
BW
2517 {
2518 SetTabOffset(GetTabOffset()+1);
2519 Refresh();
2520 Update();
2521 }
01372b8f 2522 }
cedd7b22 2523 else if (button == wxAUI_BUTTON_WINDOWLIST)
01372b8f 2524 {
793d4365 2525 int idx = GetArtProvider()->ShowDropDown(this, m_pages, GetActivePage());
7baac3cb 2526
01372b8f
BW
2527 if (idx != -1)
2528 {
2529 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
2530 e.SetSelection(idx);
2531 e.SetOldSelection(GetActivePage());
2532 e.SetEventObject(this);
2533 GetEventHandler()->ProcessEvent(e);
2534 }
4953f8cf 2535 }
cedd7b22 2536 else
4953f8cf
BW
2537 {
2538 event.Skip();
2539 }
2540}
cd05bf23 2541
a0c2e4a0
JS
2542void wxAuiTabCtrl::OnSetFocus(wxFocusEvent& WXUNUSED(event))
2543{
2544 Refresh();
2545}
2546
2547void wxAuiTabCtrl::OnKillFocus(wxFocusEvent& WXUNUSED(event))
2548{
2549 Refresh();
2550}
2551
2552void wxAuiTabCtrl::OnChar(wxKeyEvent& event)
2553{
2554 if (GetActivePage() == -1)
2555 {
2556 event.Skip();
2557 return;
2558 }
2559
2560 // We can't leave tab processing to the system; on Windows, tabs and keys
2561 // get eaten by the system and not processed properly if we specify both
2562 // wxTAB_TRAVERSAL and wxWANTS_CHARS. And if we specify just wxTAB_TRAVERSAL,
2563 // we don't key arrow key events.
2564
2565 int key = event.GetKeyCode();
2566
2567 if (key == WXK_NUMPAD_PAGEUP)
2568 key = WXK_PAGEUP;
2569 if (key == WXK_NUMPAD_PAGEDOWN)
2570 key = WXK_PAGEDOWN;
2571 if (key == WXK_NUMPAD_HOME)
2572 key = WXK_HOME;
2573 if (key == WXK_NUMPAD_END)
2574 key = WXK_END;
2575 if (key == WXK_NUMPAD_LEFT)
2576 key = WXK_LEFT;
2577 if (key == WXK_NUMPAD_RIGHT)
2578 key = WXK_RIGHT;
2579
2580 if (key == WXK_TAB || key == WXK_PAGEUP || key == WXK_PAGEDOWN)
2581 {
2582 bool bCtrlDown = event.ControlDown();
2583 bool bShiftDown = event.ShiftDown();
2584
2585 bool bForward = (key == WXK_TAB && !bShiftDown) || (key == WXK_PAGEDOWN);
2586 bool bWindowChange = (key == WXK_PAGEUP) || (key == WXK_PAGEDOWN) || bCtrlDown;
2587 bool bFromTab = (key == WXK_TAB);
2588
2589 wxAuiNotebook* nb = wxDynamicCast(GetParent(), wxAuiNotebook);
2590 if (!nb)
2591 {
2592 event.Skip();
2593 return;
2594 }
2595
2596 wxNavigationKeyEvent keyEvent;
2597 keyEvent.SetDirection(bForward);
2598 keyEvent.SetWindowChange(bWindowChange);
2599 keyEvent.SetFromTab(bFromTab);
2600 keyEvent.SetEventObject(nb);
2601
2602 if (!nb->GetEventHandler()->ProcessEvent(keyEvent))
2603 {
2604 // Not processed? Do an explicit tab into the page.
2605 wxWindow* win = GetWindowFromIdx(GetActivePage());
2606 if (win)
2607 win->SetFocus();
2608 }
2609 return;
2610 }
2611
2612 if (m_pages.GetCount() < 2)
2613 {
2614 event.Skip();
2615 return;
2616 }
2617
2618 int newPage = -1;
2619
5c58a3a9
VZ
2620 int forwardKey, backwardKey;
2621 if (GetLayoutDirection() == wxLayout_RightToLeft)
2622 {
2623 forwardKey = WXK_LEFT;
2624 backwardKey = WXK_RIGHT;
2625 }
2626 else
2627 {
2628 forwardKey = WXK_RIGHT;
2629 backwardKey = WXK_LEFT;
2630 }
2631
2632 if (key == forwardKey)
a0c2e4a0
JS
2633 {
2634 if (m_pages.GetCount() > 1)
2635 {
2636 if (GetActivePage() == -1)
2637 newPage = 0;
2638 else if (GetActivePage() < (int) (m_pages.GetCount() - 1))
2639 newPage = GetActivePage() + 1;
2640 }
2641 }
5c58a3a9 2642 else if (key == backwardKey)
a0c2e4a0
JS
2643 {
2644 if (m_pages.GetCount() > 1)
2645 {
2646 if (GetActivePage() == -1)
2647 newPage = (int) (m_pages.GetCount() - 1);
2648 else if (GetActivePage() > 0)
2649 newPage = GetActivePage() - 1;
2650 }
2651 }
2652 else if (key == WXK_HOME)
2653 {
2654 newPage = 0;
2655 }
2656 else if (key == WXK_END)
2657 {
2658 newPage = (int) (m_pages.GetCount() - 1);
2659 }
2660 else
2661 event.Skip();
2662
2663 if (newPage != -1)
2664 {
2665 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
2666 e.SetSelection(newPage);
2667 e.SetOldSelection(newPage);
2668 e.SetEventObject(this);
2669 this->GetEventHandler()->ProcessEvent(e);
2670 }
2671 else
2672 event.Skip();
2673}
2674
cd05bf23
BW
2675// wxTabFrame is an interesting case. It's important that all child pages
2676// of the multi-notebook control are all actually children of that control
2677// (and not grandchildren). wxTabFrame facilitates this. There is one
2678// instance of wxTabFrame for each tab control inside the multi-notebook.
2679// It's important to know that wxTabFrame is not a real window, but it merely
2680// used to capture the dimensions/positioning of the internal tab control and
2681// it's managed page windows
2682
2683class wxTabFrame : public wxWindow
2684{
2685public:
2686
2687 wxTabFrame()
2688 {
2689 m_tabs = NULL;
2690 m_rect = wxRect(0,0,200,200);
da5e85d9
BW
2691 m_tab_ctrl_height = 20;
2692 }
4444d148 2693
cedd7b22
PC
2694 ~wxTabFrame()
2695 {
2696 wxDELETE(m_tabs);
2697 }
bd4e0834 2698
da5e85d9
BW
2699 void SetTabCtrlHeight(int h)
2700 {
2701 m_tab_ctrl_height = h;
cd05bf23 2702 }
4444d148 2703
cedd7b22 2704protected:
cd05bf23
BW
2705 void DoSetSize(int x, int y,
2706 int width, int height,
2707 int WXUNUSED(sizeFlags = wxSIZE_AUTO))
2708 {
2709 m_rect = wxRect(x, y, width, height);
2710 DoSizing();
2711 }
4444d148 2712
cd05bf23
BW
2713 void DoGetClientSize(int* x, int* y) const
2714 {
2715 *x = m_rect.width;
2716 *y = m_rect.height;
2717 }
4f450f41 2718
cedd7b22 2719public:
4f450f41 2720 bool Show( bool WXUNUSED(show = true) ) { return false; }
4444d148 2721
cd05bf23
BW
2722 void DoSizing()
2723 {
2724 if (!m_tabs)
2725 return;
4444d148 2726
64178c36
JS
2727 if (m_tabs->IsFrozen() || m_tabs->GetParent()->IsFrozen())
2728 return;
2729
b0d17f7c 2730 m_tab_rect = wxRect(m_rect.x, m_rect.y, m_rect.width, m_tab_ctrl_height);
134198f1
JS
2731 if (m_tabs->GetFlags() & wxAUI_NB_BOTTOM)
2732 {
2733 m_tab_rect = wxRect (m_rect.x, m_rect.y + m_rect.height - m_tab_ctrl_height, m_rect.width, m_tab_ctrl_height);
2734 m_tabs->SetSize (m_rect.x, m_rect.y + m_rect.height - m_tab_ctrl_height, m_rect.width, m_tab_ctrl_height);
2735 m_tabs->SetRect (wxRect(0, 0, m_rect.width, m_tab_ctrl_height));
2736 }
2737 else //TODO: if (GetFlags() & wxAUI_NB_TOP)
2738 {
2739 m_tab_rect = wxRect (m_rect.x, m_rect.y, m_rect.width, m_tab_ctrl_height);
2740 m_tabs->SetSize (m_rect.x, m_rect.y, m_rect.width, m_tab_ctrl_height);
2741 m_tabs->SetRect (wxRect(0, 0, m_rect.width, m_tab_ctrl_height));
2742 }
2743 // TODO: else if (GetFlags() & wxAUI_NB_LEFT){}
2744 // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){}
2745
cd05bf23 2746 m_tabs->Refresh();
9d59bf68 2747 m_tabs->Update();
4444d148 2748
cd05bf23
BW
2749 wxAuiNotebookPageArray& pages = m_tabs->GetPages();
2750 size_t i, page_count = pages.GetCount();
4444d148 2751
cd05bf23
BW
2752 for (i = 0; i < page_count; ++i)
2753 {
f96f6a88
VZ
2754 int height = m_rect.height - m_tab_ctrl_height;
2755 if ( height < 0 )
2756 {
2757 // avoid passing negative height to wxWindow::SetSize(), this
2758 // results in assert failures/GTK+ warnings
2759 height = 0;
2760 }
2761
cd05bf23 2762 wxAuiNotebookPage& page = pages.Item(i);
134198f1
JS
2763 if (m_tabs->GetFlags() & wxAUI_NB_BOTTOM)
2764 {
f96f6a88 2765 page.window->SetSize(m_rect.x, m_rect.y, m_rect.width, height);
134198f1
JS
2766 }
2767 else //TODO: if (GetFlags() & wxAUI_NB_TOP)
2768 {
2769 page.window->SetSize(m_rect.x, m_rect.y + m_tab_ctrl_height,
f96f6a88 2770 m_rect.width, height);
134198f1
JS
2771 }
2772 // TODO: else if (GetFlags() & wxAUI_NB_LEFT){}
2773 // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){}
4444d148 2774
89272c55 2775#if wxUSE_MDI
a3a5df9d 2776 if (page.window->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
cd05bf23 2777 {
a3a5df9d 2778 wxAuiMDIChildFrame* wnd = (wxAuiMDIChildFrame*)page.window;
cd05bf23
BW
2779 wnd->ApplyMDIChildFrameRect();
2780 }
89272c55 2781#endif
cd05bf23
BW
2782 }
2783 }
2784
cedd7b22 2785protected:
134e83cb
BW
2786 void DoGetSize(int* x, int* y) const
2787 {
2788 if (x)
2789 *x = m_rect.GetWidth();
2790 if (y)
2791 *y = m_rect.GetHeight();
2792 }
4444d148 2793
cedd7b22 2794public:
134e83cb
BW
2795 void Update()
2796 {
2797 // does nothing
2798 }
4444d148 2799
cd05bf23
BW
2800 wxRect m_rect;
2801 wxRect m_tab_rect;
2802 wxAuiTabCtrl* m_tabs;
da5e85d9 2803 int m_tab_ctrl_height;
cd05bf23
BW
2804};
2805
2806
7ebc40e8 2807const int wxAuiBaseTabCtrlId = 5380;
cd05bf23
BW
2808
2809
a3a5df9d 2810// -- wxAuiNotebook class implementation --
cd05bf23 2811
3c778901
VZ
2812#define EVT_AUI_RANGE(id1, id2, event, func) \
2813 wx__DECLARE_EVT2(event, id1, id2, wxAuiNotebookEventHandler(func))
2814
a3a5df9d 2815BEGIN_EVENT_TABLE(wxAuiNotebook, wxControl)
9fbb7d80 2816 EVT_SIZE(wxAuiNotebook::OnSize)
5bf3f27f 2817 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocusNotebook)
3c778901 2818 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
cd05bf23 2819 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING,
a3a5df9d 2820 wxAuiNotebook::OnTabClicked)
3c778901 2821 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
cd05bf23 2822 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG,
a3a5df9d 2823 wxAuiNotebook::OnTabBeginDrag)
3c778901 2824 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
cd05bf23 2825 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG,
a3a5df9d 2826 wxAuiNotebook::OnTabEndDrag)
3c778901 2827 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
cd05bf23 2828 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION,
a3a5df9d 2829 wxAuiNotebook::OnTabDragMotion)
3c778901 2830 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
cd05bf23 2831 wxEVT_COMMAND_AUINOTEBOOK_BUTTON,
a3a5df9d 2832 wxAuiNotebook::OnTabButton)
3c778901 2833 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
69f5e420
BW
2834 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN,
2835 wxAuiNotebook::OnTabMiddleDown)
3c778901 2836 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
69f5e420
BW
2837 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP,
2838 wxAuiNotebook::OnTabMiddleUp)
3c778901 2839 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
69f5e420
BW
2840 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN,
2841 wxAuiNotebook::OnTabRightDown)
3c778901 2842 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
69f5e420
BW
2843 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP,
2844 wxAuiNotebook::OnTabRightUp)
3c778901 2845 EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
198be845
JS
2846 wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK,
2847 wxAuiNotebook::OnTabBgDClick)
5bf3f27f 2848 EVT_NAVIGATION_KEY(wxAuiNotebook::OnNavigationKeyNotebook)
c7bfb76a 2849
5bf3f27f 2850#ifdef wxHAS_NATIVE_TAB_TRAVERSAL
c7bfb76a 2851 WX_EVENT_TABLE_CONTROL_CONTAINER(wxAuiNotebook)
5bf3f27f
JS
2852#else
2853 // Avoid clash with container event handler functions
2854 EVT_SET_FOCUS(wxAuiNotebook::OnFocus)
2855#endif
cd05bf23
BW
2856END_EVENT_TABLE()
2857
c7bfb76a
JS
2858WX_DELEGATE_TO_CONTROL_CONTAINER(wxAuiNotebook, wxControl)
2859
a3a5df9d 2860wxAuiNotebook::wxAuiNotebook()
cd05bf23
BW
2861{
2862 m_curpage = -1;
7ebc40e8 2863 m_tab_id_counter = wxAuiBaseTabCtrlId;
cd05bf23 2864 m_dummy_wnd = NULL;
da5e85d9 2865 m_tab_ctrl_height = 20;
9fbb7d80 2866 m_requested_bmp_size = wxDefaultSize;
ca0d4407 2867 m_requested_tabctrl_height = -1;
cd05bf23
BW
2868}
2869
a3a5df9d 2870wxAuiNotebook::wxAuiNotebook(wxWindow *parent,
cd05bf23
BW
2871 wxWindowID id,
2872 const wxPoint& pos,
2873 const wxSize& size,
2874 long style) : wxControl(parent, id, pos, size, style)
2875{
9fbb7d80
BW
2876 m_dummy_wnd = NULL;
2877 m_requested_bmp_size = wxDefaultSize;
ca0d4407 2878 m_requested_tabctrl_height = -1;
702b1c7e 2879 InitNotebook(style);
cd05bf23
BW
2880}
2881
a3a5df9d 2882bool wxAuiNotebook::Create(wxWindow* parent,
cd05bf23
BW
2883 wxWindowID id,
2884 const wxPoint& pos,
2885 const wxSize& size,
2886 long style)
2887{
2888 if (!wxControl::Create(parent, id, pos, size, style))
2889 return false;
4444d148 2890
702b1c7e 2891 InitNotebook(style);
4444d148 2892
cd05bf23
BW
2893 return true;
2894}
2895
2896// InitNotebook() contains common initialization
2897// code called by all constructors
a3a5df9d 2898void wxAuiNotebook::InitNotebook(long style)
cd05bf23 2899{
c7bfb76a
JS
2900 WX_INIT_CONTROL_CONTAINER();
2901 // SetCanFocus(false);
2902
2903 SetName(wxT("wxAuiNotebook"));
da5e85d9 2904 m_curpage = -1;
7ebc40e8 2905 m_tab_id_counter = wxAuiBaseTabCtrlId;
da5e85d9 2906 m_dummy_wnd = NULL;
702b1c7e 2907 m_flags = (unsigned int)style;
ca0d4407 2908 m_tab_ctrl_height = 20;
c58ba15f 2909
cd05bf23
BW
2910 m_normal_font = *wxNORMAL_FONT;
2911 m_selected_font = *wxNORMAL_FONT;
2912 m_selected_font.SetWeight(wxBOLD);
4444d148 2913
b0d17f7c 2914 SetArtProvider(new wxAuiDefaultTabArt);
4444d148
WS
2915
2916 m_dummy_wnd = new wxWindow(this, wxID_ANY, wxPoint(0,0), wxSize(0,0));
cd05bf23
BW
2917 m_dummy_wnd->SetSize(200, 200);
2918 m_dummy_wnd->Show(false);
4444d148 2919
cd05bf23 2920 m_mgr.SetManagedWindow(this);
a6b7a521
VZ
2921 m_mgr.SetFlags(wxAUI_MGR_DEFAULT);
2922 m_mgr.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
4444d148 2923
cd05bf23 2924 m_mgr.AddPane(m_dummy_wnd,
9fbb7d80 2925 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
4444d148 2926
cd05bf23
BW
2927 m_mgr.Update();
2928}
2929
a3a5df9d 2930wxAuiNotebook::~wxAuiNotebook()
cd05bf23 2931{
18b40f30 2932 // Indicate we're deleting pages
c6212a0c 2933 SendDestroyEvent();
18b40f30 2934
1c0955dd
JS
2935 while ( GetPageCount() > 0 )
2936 DeletePage(0);
2937
cd05bf23
BW
2938 m_mgr.UnInit();
2939}
2940
a3a5df9d 2941void wxAuiNotebook::SetArtProvider(wxAuiTabArt* art)
3f69756e
BW
2942{
2943 m_tabs.SetArtProvider(art);
7baac3cb 2944
4026f044
VZ
2945 // Update the height and do nothing else if it did something but otherwise
2946 // (i.e. if the new art provider uses the same height as the old one) we
2947 // need to manually set the art provider for all tabs ourselves.
2948 if ( !UpdateTabCtrlHeight() )
2949 {
2950 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
2951 const size_t pane_count = all_panes.GetCount();
2952 for (size_t i = 0; i < pane_count; ++i)
2953 {
2954 wxAuiPaneInfo& pane = all_panes.Item(i);
2955 if (pane.name == wxT("dummy"))
2956 continue;
2957 wxTabFrame* tab_frame = (wxTabFrame*)pane.window;
2958 wxAuiTabCtrl* tabctrl = tab_frame->m_tabs;
2959 tabctrl->SetArtProvider(art->Clone());
2960 }
2961 }
2b9aac33
BW
2962}
2963
ca0d4407
BW
2964// SetTabCtrlHeight() is the highest-level override of the
2965// tab height. A call to this function effectively enforces a
2966// specified tab ctrl height, overriding all other considerations,
2967// such as text or bitmap height. It overrides any call to
2968// SetUniformBitmapSize(). Specifying a height of -1 reverts
4c51a665 2969// any previous call and returns to the default behaviour
ca0d4407
BW
2970
2971void wxAuiNotebook::SetTabCtrlHeight(int height)
2972{
2973 m_requested_tabctrl_height = height;
c58ba15f 2974
ca0d4407
BW
2975 // if window is already initialized, recalculate the tab height
2976 if (m_dummy_wnd)
2977 {
2978 UpdateTabCtrlHeight();
2979 }
2980}
2981
2982
2983// SetUniformBitmapSize() ensures that all tabs will have
2984// the same height, even if some tabs don't have bitmaps
2985// Passing wxDefaultSize to this function will instruct
2986// the control to use dynamic tab height-- so when a tab
2987// with a large bitmap is added, the tab ctrl's height will
2988// automatically increase to accommodate the bitmap
2989
9fbb7d80
BW
2990void wxAuiNotebook::SetUniformBitmapSize(const wxSize& size)
2991{
2992 m_requested_bmp_size = size;
c58ba15f 2993
9fbb7d80 2994 // if window is already initialized, recalculate the tab height
dbbe02ea
BW
2995 if (m_dummy_wnd)
2996 {
ca0d4407 2997 UpdateTabCtrlHeight();
dbbe02ea 2998 }
9fbb7d80
BW
2999}
3000
ca0d4407 3001// UpdateTabCtrlHeight() does the actual tab resizing. It's meant
4026f044
VZ
3002// to be used internally
3003bool wxAuiNotebook::UpdateTabCtrlHeight()
2b9aac33 3004{
ca0d4407
BW
3005 // get the tab ctrl height we will use
3006 int height = CalculateTabCtrlHeight();
c58ba15f 3007
2b9aac33
BW
3008 // if the tab control height needs to change, update
3009 // all of our tab controls with the new height
4026f044
VZ
3010 if (m_tab_ctrl_height == height)
3011 return false;
7baac3cb 3012
4026f044 3013 wxAuiTabArt* art = m_tabs.GetArtProvider();
7baac3cb 3014
4026f044
VZ
3015 m_tab_ctrl_height = height;
3016
3017 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
3018 size_t i, pane_count = all_panes.GetCount();
3019 for (i = 0; i < pane_count; ++i)
3020 {
3021 wxAuiPaneInfo& pane = all_panes.Item(i);
3022 if (pane.name == wxT("dummy"))
3023 continue;
3024 wxTabFrame* tab_frame = (wxTabFrame*)pane.window;
3025 wxAuiTabCtrl* tabctrl = tab_frame->m_tabs;
3026 tab_frame->SetTabCtrlHeight(m_tab_ctrl_height);
3027 tabctrl->SetArtProvider(art->Clone());
3028 tab_frame->DoSizing();
b0d17f7c 3029 }
4026f044
VZ
3030
3031 return true;
3f69756e
BW
3032}
3033
9fbb7d80
BW
3034void wxAuiNotebook::UpdateHintWindowSize()
3035{
3036 wxSize size = CalculateNewSplitSize();
c58ba15f 3037
9fbb7d80
BW
3038 // the placeholder hint window should be set to this size
3039 wxAuiPaneInfo& info = m_mgr.GetPane(wxT("dummy"));
3040 if (info.IsOk())
3041 {
3042 info.MinSize(size);
3043 info.BestSize(size);
3044 m_dummy_wnd->SetSize(size);
3045 }
3046}
3047
3048
3049// calculates the size of the new split
3050wxSize wxAuiNotebook::CalculateNewSplitSize()
3051{
3052 // count number of tab controls
3053 int tab_ctrl_count = 0;
3054 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
3055 size_t i, pane_count = all_panes.GetCount();
3056 for (i = 0; i < pane_count; ++i)
3057 {
3058 wxAuiPaneInfo& pane = all_panes.Item(i);
3059 if (pane.name == wxT("dummy"))
3060 continue;
3061 tab_ctrl_count++;
3062 }
3063
3064 wxSize new_split_size;
c58ba15f 3065
9fbb7d80
BW
3066 // if there is only one tab control, the first split
3067 // should happen around the middle
3068 if (tab_ctrl_count < 2)
3069 {
3070 new_split_size = GetClientSize();
3071 new_split_size.x /= 2;
3072 new_split_size.y /= 2;
3073 }
cedd7b22 3074 else
9fbb7d80
BW
3075 {
3076 // this is in place of a more complicated calculation
3077 // that needs to be implemented
3078 new_split_size = wxSize(180,180);
3079 }
c58ba15f 3080
9fbb7d80
BW
3081 return new_split_size;
3082}
3083
2b9aac33
BW
3084int wxAuiNotebook::CalculateTabCtrlHeight()
3085{
ca0d4407
BW
3086 // if a fixed tab ctrl height is specified,
3087 // just return that instead of calculating a
3088 // tab height
3089 if (m_requested_tabctrl_height != -1)
3090 return m_requested_tabctrl_height;
c58ba15f 3091
2b9aac33
BW
3092 // find out new best tab height
3093 wxAuiTabArt* art = m_tabs.GetArtProvider();
7baac3cb 3094
9fbb7d80
BW
3095 return art->GetBestTabCtrlSize(this,
3096 m_tabs.GetPages(),
3097 m_requested_bmp_size);
2b9aac33
BW
3098}
3099
3100
e0dc13d4 3101wxAuiTabArt* wxAuiNotebook::GetArtProvider() const
3f69756e
BW
3102{
3103 return m_tabs.GetArtProvider();
3104}
3105
0ce53f32
BW
3106void wxAuiNotebook::SetWindowStyleFlag(long style)
3107{
3108 wxControl::SetWindowStyleFlag(style);
7baac3cb 3109
0ce53f32 3110 m_flags = (unsigned int)style;
7baac3cb 3111
0ce53f32
BW
3112 // if the control is already initialized
3113 if (m_mgr.GetManagedWindow() == (wxWindow*)this)
3114 {
3115 // let all of the tab children know about the new style
7baac3cb 3116
0ce53f32
BW
3117 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
3118 size_t i, pane_count = all_panes.GetCount();
3119 for (i = 0; i < pane_count; ++i)
3120 {
3121 wxAuiPaneInfo& pane = all_panes.Item(i);
3122 if (pane.name == wxT("dummy"))
3123 continue;
97ac2d5e
BW
3124 wxTabFrame* tabframe = (wxTabFrame*)pane.window;
3125 wxAuiTabCtrl* tabctrl = tabframe->m_tabs;
0ce53f32 3126 tabctrl->SetFlags(m_flags);
97ac2d5e 3127 tabframe->DoSizing();
0ce53f32
BW
3128 tabctrl->Refresh();
3129 tabctrl->Update();
3130 }
3131 }
3132}
3133
3134
a3a5df9d 3135bool wxAuiNotebook::AddPage(wxWindow* page,
cd05bf23
BW
3136 const wxString& caption,
3137 bool select,
3138 const wxBitmap& bitmap)
3139{
3140 return InsertPage(GetPageCount(), page, caption, select, bitmap);
3141}
4444d148 3142
a3a5df9d 3143bool wxAuiNotebook::InsertPage(size_t page_idx,
cd05bf23
BW
3144 wxWindow* page,
3145 const wxString& caption,
3146 bool select,
3147 const wxBitmap& bitmap)
3148{
c36cdfc0
BW
3149 wxASSERT_MSG(page, wxT("page pointer must be non-NULL"));
3150 if (!page)
3151 return false;
5c58a3a9 3152
3d9b52a8
JS
3153 page->Reparent(this);
3154
cd05bf23
BW
3155 wxAuiNotebookPage info;
3156 info.window = page;
3157 info.caption = caption;
3158 info.bitmap = bitmap;
3159 info.active = false;
3160
3161 // if there are currently no tabs, the first added
3162 // tab must be active
3163 if (m_tabs.GetPageCount() == 0)
3164 info.active = true;
3165
3166 m_tabs.InsertPage(page, info, page_idx);
3167
298773ec
BW
3168 // if that was the first page added, even if
3169 // select is false, it must become the "current page"
3170 // (though no select events will be fired)
3171 if (!select && m_tabs.GetPageCount() == 1)
092d7f88
BW
3172 select = true;
3173 //m_curpage = GetPageIndex(page);
298773ec 3174
cd05bf23
BW
3175 wxAuiTabCtrl* active_tabctrl = GetActiveTabCtrl();
3176 if (page_idx >= active_tabctrl->GetPageCount())
3177 active_tabctrl->AddPage(page, info);
cedd7b22 3178 else
cd05bf23 3179 active_tabctrl->InsertPage(page, info, page_idx);
4444d148 3180
ca0d4407 3181 UpdateTabCtrlHeight();
cd05bf23
BW
3182 DoSizing();
3183 active_tabctrl->DoShowHide();
4444d148 3184
3d9b52a8
JS
3185 // adjust selected index
3186 if(m_curpage >= (int) page_idx)
3187 m_curpage++;
3188
cd05bf23
BW
3189 if (select)
3190 {
849c353a 3191 SetSelectionToWindow(page);
cd05bf23 3192 }
4444d148 3193
cd05bf23
BW
3194 return true;
3195}
3196
3197
3198// DeletePage() removes a tab from the multi-notebook,
3199// and destroys the window as well
a3a5df9d 3200bool wxAuiNotebook::DeletePage(size_t page_idx)
7baac3cb 3201{
fd749f4a
BW
3202 if (page_idx >= m_tabs.GetPageCount())
3203 return false;
cedd7b22 3204
4444d148 3205 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
cedd7b22 3206
fd749f4a
BW
3207 // hide the window in advance, as this will
3208 // prevent flicker
3209 ShowWnd(wnd, false);
5d3aeb0f
BW
3210
3211 if (!RemovePage(page_idx))
3212 return false;
3213
89272c55 3214#if wxUSE_MDI
5d3aeb0f
BW
3215 // actually destroy the window now
3216 if (wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
3217 {
3218 // delete the child frame with pending delete, as is
3219 // customary with frame windows
3220 if (!wxPendingDelete.Member(wnd))
3221 wxPendingDelete.Append(wnd);
3222 }
cedd7b22 3223 else
89272c55 3224#endif
5d3aeb0f
BW
3225 {
3226 wnd->Destroy();
3227 }
7baac3cb 3228
5d3aeb0f 3229 return true;
cd05bf23
BW
3230}
3231
3232
3233
3234// RemovePage() removes a tab from the multi-notebook,
3235// but does not destroy the window
a3a5df9d 3236bool wxAuiNotebook::RemovePage(size_t page_idx)
cd05bf23 3237{
9b362935
BW
3238 // save active window pointer
3239 wxWindow* active_wnd = NULL;
3240 if (m_curpage >= 0)
3241 active_wnd = m_tabs.GetWindowFromIdx(m_curpage);
cedd7b22 3242
9b362935 3243 // save pointer of window being deleted
cd05bf23 3244 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
5d3aeb0f 3245 wxWindow* new_active = NULL;
4444d148 3246
13aaa50f
BW
3247 // make sure we found the page
3248 if (!wnd)
3249 return false;
cedd7b22 3250
5d3aeb0f 3251 // find out which onscreen tab ctrl owns this tab
cd05bf23
BW
3252 wxAuiTabCtrl* ctrl;
3253 int ctrl_idx;
5d3aeb0f
BW
3254 if (!FindTab(wnd, &ctrl, &ctrl_idx))
3255 return false;
3256
13aaa50f
BW
3257 bool is_curpage = (m_curpage == (int)page_idx);
3258 bool is_active_in_split = ctrl->GetPage(ctrl_idx).active;
5d3aeb0f 3259
4444d148 3260
5d3aeb0f
BW
3261 // remove the tab from main catalog
3262 if (!m_tabs.RemovePage(wnd))
3263 return false;
3264
3265 // remove the tab from the onscreen tab ctrl
3266 ctrl->RemovePage(wnd);
3267
13aaa50f
BW
3268 if (is_active_in_split)
3269 {
3270 int ctrl_new_page_count = (int)ctrl->GetPageCount();
cedd7b22 3271
13aaa50f
BW
3272 if (ctrl_idx >= ctrl_new_page_count)
3273 ctrl_idx = ctrl_new_page_count-1;
cedd7b22 3274
13aaa50f
BW
3275 if (ctrl_idx >= 0 && ctrl_idx < (int)ctrl->GetPageCount())
3276 {
3277 // set new page as active in the tab split
3278 ctrl->SetActivePage(ctrl_idx);
cedd7b22 3279
13aaa50f
BW
3280 // if the page deleted was the current page for the
3281 // entire tab control, then record the window
3282 // pointer of the new active page for activation
3283 if (is_curpage)
3284 {
3285 new_active = ctrl->GetWindowFromIdx(ctrl_idx);
3286 }
3287 }
3288 }
cedd7b22 3289 else
9b362935
BW
3290 {
3291 // we are not deleting the active page, so keep it the same
3292 new_active = active_wnd;
3293 }
13aaa50f 3294
cedd7b22 3295
13aaa50f
BW
3296 if (!new_active)
3297 {
3298 // we haven't yet found a new page to active,
3299 // so select the next page from the main tab
3300 // catalogue
cedd7b22 3301
13aaa50f
BW
3302 if (page_idx < m_tabs.GetPageCount())
3303 {
3304 new_active = m_tabs.GetPage(page_idx).window;
3305 }
cedd7b22 3306
13aaa50f
BW
3307 if (!new_active && m_tabs.GetPageCount() > 0)
3308 {
3309 new_active = m_tabs.GetPage(0).window;
3310 }
3311 }
5d3aeb0f 3312
cedd7b22 3313
5d3aeb0f
BW
3314 RemoveEmptyTabFrames();
3315
917f228a
VZ
3316 m_curpage = wxNOT_FOUND;
3317
3318 // set new active pane unless we're being destroyed anyhow
18b40f30 3319 if (new_active && !m_isBeingDeleted)
849c353a 3320 SetSelectionToWindow(new_active);
cedd7b22 3321
5d3aeb0f 3322 return true;
cd05bf23
BW
3323}
3324
e0dc13d4
BW
3325// GetPageIndex() returns the index of the page, or -1 if the
3326// page could not be located in the notebook
3327int wxAuiNotebook::GetPageIndex(wxWindow* page_wnd) const
3328{
3329 return m_tabs.GetIdxFromWindow(page_wnd);
3330}
3331
3332
3333
cd05bf23 3334// SetPageText() changes the tab caption of the specified page
a3a5df9d 3335bool wxAuiNotebook::SetPageText(size_t page_idx, const wxString& text)
4444d148 3336{
cd05bf23
BW
3337 if (page_idx >= m_tabs.GetPageCount())
3338 return false;
4444d148 3339
cd05bf23
BW
3340 // update our own tab catalog
3341 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
3342 page_info.caption = text;
4444d148 3343
cd05bf23
BW
3344 // update what's on screen
3345 wxAuiTabCtrl* ctrl;
3346 int ctrl_idx;
3347 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
3348 {
3349 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
3350 info.caption = text;
3351 ctrl->Refresh();
639a4f7b 3352 ctrl->Update();
cd05bf23 3353 }
4444d148 3354
cd05bf23
BW
3355 return true;
3356}
3357
c3e016e4
JS
3358// returns the page caption
3359wxString wxAuiNotebook::GetPageText(size_t page_idx) const
3360{
3361 if (page_idx >= m_tabs.GetPageCount())
3362 return wxEmptyString;
3363
3364 // update our own tab catalog
3365 const wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
3366 return page_info.caption;
3367}
e0dc13d4
BW
3368
3369bool wxAuiNotebook::SetPageBitmap(size_t page_idx, const wxBitmap& bitmap)
3370{
3371 if (page_idx >= m_tabs.GetPageCount())
3372 return false;
7baac3cb 3373
e0dc13d4
BW
3374 // update our own tab catalog
3375 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
3376 page_info.bitmap = bitmap;
7baac3cb 3377
e0dc13d4 3378 // tab height might have changed
ca0d4407 3379 UpdateTabCtrlHeight();
7baac3cb 3380
e0dc13d4
BW
3381 // update what's on screen
3382 wxAuiTabCtrl* ctrl;
3383 int ctrl_idx;
3384 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
3385 {
3386 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
3387 info.bitmap = bitmap;
3388 ctrl->Refresh();
3389 ctrl->Update();
3390 }
7baac3cb 3391
e0dc13d4
BW
3392 return true;
3393}
3394
c3e016e4
JS
3395// returns the page bitmap
3396wxBitmap wxAuiNotebook::GetPageBitmap(size_t page_idx) const
3397{
3398 if (page_idx >= m_tabs.GetPageCount())
3399 return wxBitmap();
3400
3401 // update our own tab catalog
3402 const wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
3403 return page_info.bitmap;
3404}
e0dc13d4 3405
cd05bf23 3406// GetSelection() returns the index of the currently active page
a3a5df9d 3407int wxAuiNotebook::GetSelection() const
cd05bf23
BW
3408{
3409 return m_curpage;
3410}
3411
3412// SetSelection() sets the currently active page
a3a5df9d 3413size_t wxAuiNotebook::SetSelection(size_t new_page)
cd05bf23
BW
3414{
3415 wxWindow* wnd = m_tabs.GetWindowFromIdx(new_page);
3416 if (!wnd)
3417 return m_curpage;
4444d148 3418
754dc409
JS
3419 // don't change the page unless necessary;
3420 // however, clicking again on a tab should give it the focus.
3421 if ((int)new_page == m_curpage)
3422 {
3423 wxAuiTabCtrl* ctrl;
3424 int ctrl_idx;
3425 if (FindTab(wnd, &ctrl, &ctrl_idx))
3426 {
3427 if (FindFocus() != ctrl)
3428 ctrl->SetFocus();
3429 }
3430 return m_curpage;
3431 }
3432
cd05bf23
BW
3433 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
3434 evt.SetSelection(new_page);
3435 evt.SetOldSelection(m_curpage);
3436 evt.SetEventObject(this);
7ebc40e8 3437 if (!GetEventHandler()->ProcessEvent(evt) || evt.IsAllowed())
cd05bf23 3438 {
049333c2
BW
3439 int old_curpage = m_curpage;
3440 m_curpage = new_page;
7baac3cb 3441
cd05bf23
BW
3442 // program allows the page change
3443 evt.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED);
7ebc40e8 3444 (void)GetEventHandler()->ProcessEvent(evt);
cd05bf23
BW
3445
3446
cd05bf23
BW
3447 wxAuiTabCtrl* ctrl;
3448 int ctrl_idx;
3449 if (FindTab(wnd, &ctrl, &ctrl_idx))
4444d148 3450 {
cd05bf23 3451 m_tabs.SetActivePage(wnd);
4444d148 3452
cd05bf23
BW
3453 ctrl->SetActivePage(ctrl_idx);
3454 DoSizing();
3455 ctrl->DoShowHide();
4444d148 3456
a0c2e4a0 3457 ctrl->MakeTabVisible(ctrl_idx, ctrl);
cd05bf23
BW
3458
3459 // set fonts
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 {
a3a5df9d 3464 wxAuiPaneInfo& pane = all_panes.Item(i);
cd05bf23
BW
3465 if (pane.name == wxT("dummy"))
3466 continue;
3467 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
3468 if (tabctrl != ctrl)
3469 tabctrl->SetSelectedFont(m_normal_font);
cedd7b22 3470 else
cd05bf23
BW
3471 tabctrl->SetSelectedFont(m_selected_font);
3472 tabctrl->Refresh();
3473 }
3474
754dc409
JS
3475 // Set the focus to the page if we're not currently focused on the tab.
3476 // This is Firefox-like behaviour.
3477 if (wnd->IsShownOnScreen() && FindFocus() != ctrl)
3478 wnd->SetFocus();
4444d148 3479
cd05bf23
BW
3480 return old_curpage;
3481 }
3482 }
3483
3484 return m_curpage;
3485}
3486
849c353a
VZ
3487void wxAuiNotebook::SetSelectionToWindow(wxWindow *win)
3488{
3489 const int idx = m_tabs.GetIdxFromWindow(win);
9a83f860 3490 wxCHECK_RET( idx != wxNOT_FOUND, wxT("invalid notebook page") );
849c353a 3491
ea34484c
BW
3492
3493 // since a tab was clicked, let the parent know that we received
3494 // the focus, even if we will assign that focus immediately
3495 // to the child tab in the SetSelection call below
3496 // (the child focus event will also let wxAuiManager, if any,
3497 // know that the notebook control has been activated)
03647350 3498
ea34484c
BW
3499 wxWindow* parent = GetParent();
3500 if (parent)
3501 {
3502 wxChildFocusEvent eventFocus(this);
3503 parent->GetEventHandler()->ProcessEvent(eventFocus);
3504 }
3505
3506
849c353a
VZ
3507 SetSelection(idx);
3508}
3509
cd05bf23
BW
3510// GetPageCount() returns the total number of
3511// pages managed by the multi-notebook
a3a5df9d 3512size_t wxAuiNotebook::GetPageCount() const
cd05bf23
BW
3513{
3514 return m_tabs.GetPageCount();
3515}
3516
3517// GetPage() returns the wxWindow pointer of the
3518// specified page
a3a5df9d 3519wxWindow* wxAuiNotebook::GetPage(size_t page_idx) const
cd05bf23
BW
3520{
3521 wxASSERT(page_idx < m_tabs.GetPageCount());
4444d148 3522
cd05bf23
BW
3523 return m_tabs.GetWindowFromIdx(page_idx);
3524}
3525
3526// DoSizing() performs all sizing operations in each tab control
a3a5df9d 3527void wxAuiNotebook::DoSizing()
cd05bf23 3528{
a3a5df9d 3529 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
3530 size_t i, pane_count = all_panes.GetCount();
3531 for (i = 0; i < pane_count; ++i)
3532 {
3533 if (all_panes.Item(i).name == wxT("dummy"))
3534 continue;
3535
3536 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
3537 tabframe->DoSizing();
3538 }
3539}
3540
3541// GetActiveTabCtrl() returns the active tab control. It is
3542// called to determine which control gets new windows being added
a3a5df9d 3543wxAuiTabCtrl* wxAuiNotebook::GetActiveTabCtrl()
cd05bf23
BW
3544{
3545 if (m_curpage >= 0 && m_curpage < (int)m_tabs.GetPageCount())
3546 {
3547 wxAuiTabCtrl* ctrl;
3548 int idx;
4444d148 3549
cd05bf23
BW
3550 // find the tab ctrl with the current page
3551 if (FindTab(m_tabs.GetPage(m_curpage).window,
3552 &ctrl, &idx))
4444d148 3553 {
cd05bf23
BW
3554 return ctrl;
3555 }
3556 }
4444d148 3557
cd05bf23 3558 // no current page, just find the first tab ctrl
a3a5df9d 3559 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
3560 size_t i, pane_count = all_panes.GetCount();
3561 for (i = 0; i < pane_count; ++i)
3562 {
3563 if (all_panes.Item(i).name == wxT("dummy"))
3564 continue;
4444d148 3565
cd05bf23
BW
3566 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
3567 return tabframe->m_tabs;
3568 }
4444d148 3569
cd05bf23
BW
3570 // If there is no tabframe at all, create one
3571 wxTabFrame* tabframe = new wxTabFrame;
da5e85d9 3572 tabframe->SetTabCtrlHeight(m_tab_ctrl_height);
cd05bf23
BW
3573 tabframe->m_tabs = new wxAuiTabCtrl(this,
3574 m_tab_id_counter++,
3575 wxDefaultPosition,
3576 wxDefaultSize,
a0c2e4a0 3577 wxNO_BORDER|wxWANTS_CHARS);
702b1c7e 3578 tabframe->m_tabs->SetFlags(m_flags);
b0d17f7c 3579 tabframe->m_tabs->SetArtProvider(m_tabs.GetArtProvider()->Clone());
cd05bf23 3580 m_mgr.AddPane(tabframe,
a3a5df9d 3581 wxAuiPaneInfo().Center().CaptionVisible(false));
4444d148 3582
cd05bf23 3583 m_mgr.Update();
4444d148 3584
cd05bf23
BW
3585 return tabframe->m_tabs;
3586}
3587
3588// FindTab() finds the tab control that currently contains the window as well
3589// as the index of the window in the tab control. It returns true if the
3590// window was found, otherwise false.
a3a5df9d 3591bool wxAuiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx)
cd05bf23 3592{
a3a5df9d 3593 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
3594 size_t i, pane_count = all_panes.GetCount();
3595 for (i = 0; i < pane_count; ++i)
3596 {
3597 if (all_panes.Item(i).name == wxT("dummy"))
3598 continue;
4444d148 3599
cd05bf23 3600 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
4444d148 3601
cd05bf23
BW
3602 int page_idx = tabframe->m_tabs->GetIdxFromWindow(page);
3603 if (page_idx != -1)
3604 {
3605 *ctrl = tabframe->m_tabs;
3606 *idx = page_idx;
3607 return true;
3608 }
3609 }
4444d148 3610
cd05bf23
BW
3611 return false;
3612}
3613
d606b6e9
BW
3614void wxAuiNotebook::Split(size_t page, int direction)
3615{
3616 wxSize cli_size = GetClientSize();
54a8a78e 3617
d606b6e9
BW
3618 // get the page's window pointer
3619 wxWindow* wnd = GetPage(page);
3620 if (!wnd)
3621 return;
54a8a78e 3622
d606b6e9
BW
3623 // notebooks with 1 or less pages can't be split
3624 if (GetPageCount() < 2)
3625 return;
54a8a78e 3626
d606b6e9
BW
3627 // find out which tab control the page currently belongs to
3628 wxAuiTabCtrl *src_tabs, *dest_tabs;
3629 int src_idx = -1;
3630 src_tabs = NULL;
3631 if (!FindTab(wnd, &src_tabs, &src_idx))
3632 return;
3633 if (!src_tabs || src_idx == -1)
3634 return;
54a8a78e 3635
d606b6e9
BW
3636 // choose a split size
3637 wxSize split_size;
3638 if (GetPageCount() > 2)
3639 {
3640 split_size = CalculateNewSplitSize();
3641 }
cedd7b22 3642 else
d606b6e9
BW
3643 {
3644 // because there are two panes, always split them
3645 // equally
3646 split_size = GetClientSize();
3647 split_size.x /= 2;
3648 split_size.y /= 2;
3649 }
54a8a78e
VZ
3650
3651
d606b6e9
BW
3652 // create a new tab frame
3653 wxTabFrame* new_tabs = new wxTabFrame;
3654 new_tabs->m_rect = wxRect(wxPoint(0,0), split_size);
3655 new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
3656 new_tabs->m_tabs = new wxAuiTabCtrl(this,
3657 m_tab_id_counter++,
3658 wxDefaultPosition,
3659 wxDefaultSize,
a0c2e4a0 3660 wxNO_BORDER|wxWANTS_CHARS);
d606b6e9
BW
3661 new_tabs->m_tabs->SetArtProvider(m_tabs.GetArtProvider()->Clone());
3662 new_tabs->m_tabs->SetFlags(m_flags);
3663 dest_tabs = new_tabs->m_tabs;
3664
3665 // create a pane info structure with the information
3666 // about where the pane should be added
3667 wxAuiPaneInfo pane_info = wxAuiPaneInfo().Bottom().CaptionVisible(false);
3668 wxPoint mouse_pt;
54a8a78e 3669
d606b6e9
BW
3670 if (direction == wxLEFT)
3671 {
3672 pane_info.Left();
3673 mouse_pt = wxPoint(0, cli_size.y/2);
3674 }
cedd7b22 3675 else if (direction == wxRIGHT)
d606b6e9
BW
3676 {
3677 pane_info.Right();
3678 mouse_pt = wxPoint(cli_size.x, cli_size.y/2);
3679 }
cedd7b22 3680 else if (direction == wxTOP)
d606b6e9
BW
3681 {
3682 pane_info.Top();
3683 mouse_pt = wxPoint(cli_size.x/2, 0);
3684 }
cedd7b22 3685 else if (direction == wxBOTTOM)
d606b6e9
BW
3686 {
3687 pane_info.Bottom();
3688 mouse_pt = wxPoint(cli_size.x/2, cli_size.y);
3689 }
54a8a78e 3690
d606b6e9
BW
3691 m_mgr.AddPane(new_tabs, pane_info, mouse_pt);
3692 m_mgr.Update();
54a8a78e 3693
d606b6e9
BW
3694 // remove the page from the source tabs
3695 wxAuiNotebookPage page_info = src_tabs->GetPage(src_idx);
3696 page_info.active = false;
3697 src_tabs->RemovePage(page_info.window);
3698 if (src_tabs->GetPageCount() > 0)
3699 {
3700 src_tabs->SetActivePage((size_t)0);
3701 src_tabs->DoShowHide();
3702 src_tabs->Refresh();
3703 }
3704
3705
3706 // add the page to the destination tabs
3707 dest_tabs->InsertPage(page_info.window, page_info, 0);
3708
3709 if (src_tabs->GetPageCount() == 0)
3710 {
3711 RemoveEmptyTabFrames();
3712 }
3713
3714 DoSizing();
3715 dest_tabs->DoShowHide();
3716 dest_tabs->Refresh();
3717
3718 // force the set selection function reset the selection
3719 m_curpage = -1;
54a8a78e 3720
d606b6e9 3721 // set the active page to the one we just split off
849c353a 3722 SetSelectionToPage(page_info);
54a8a78e 3723
d606b6e9
BW
3724 UpdateHintWindowSize();
3725}
3726
3727
9fbb7d80 3728void wxAuiNotebook::OnSize(wxSizeEvent& evt)
cd05bf23 3729{
9fbb7d80 3730 UpdateHintWindowSize();
c58ba15f 3731
9fbb7d80 3732 evt.Skip();
cd05bf23
BW
3733}
3734
3c778901 3735void wxAuiNotebook::OnTabClicked(wxAuiNotebookEvent& evt)
cd05bf23 3736{
cd05bf23
BW
3737 wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject();
3738 wxASSERT(ctrl != NULL);
4444d148 3739
cd05bf23
BW
3740 wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection());
3741 wxASSERT(wnd != NULL);
4444d148 3742
849c353a 3743 SetSelectionToWindow(wnd);
cd05bf23
BW
3744}
3745
3c778901 3746void wxAuiNotebook::OnTabBgDClick(wxAuiNotebookEvent& WXUNUSED(evt))
198be845
JS
3747{
3748 // notify owner that the tabbar background has been double-clicked
3749 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, m_windowId);
3750 e.SetEventObject(this);
3751 GetEventHandler()->ProcessEvent(e);
3752}
3753
3c778901 3754void wxAuiNotebook::OnTabBeginDrag(wxAuiNotebookEvent&)
cd05bf23 3755{
08c068a4 3756 m_last_drag_x = 0;
cd05bf23
BW
3757}
3758
3c778901 3759void wxAuiNotebook::OnTabDragMotion(wxAuiNotebookEvent& evt)
cd05bf23
BW
3760{
3761 wxPoint screen_pt = ::wxGetMousePosition();
3762 wxPoint client_pt = ScreenToClient(screen_pt);
3763 wxPoint zero(0,0);
4444d148 3764
cd05bf23 3765 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
08c068a4 3766 wxAuiTabCtrl* dest_tabs = GetTabCtrlFromPoint(client_pt);
7baac3cb 3767
08c068a4 3768 if (dest_tabs == src_tabs)
cd05bf23 3769 {
3941df70
BW
3770 if (src_tabs)
3771 {
3772 src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
3773 }
7baac3cb 3774
08c068a4 3775 // always hide the hint for inner-tabctrl drag
cd05bf23 3776 m_mgr.HideHint();
7baac3cb 3777
695c0088
BW
3778 // if tab moving is not allowed, leave
3779 if (!(m_flags & wxAUI_NB_TAB_MOVE))
3780 {
3781 return;
3782 }
7baac3cb 3783
08c068a4
BW
3784 wxPoint pt = dest_tabs->ScreenToClient(screen_pt);
3785 wxWindow* dest_location_tab;
7baac3cb 3786
08c068a4
BW
3787 // this is an inner-tab drag/reposition
3788 if (dest_tabs->TabHitTest(pt.x, pt.y, &dest_location_tab))
3789 {
3790 int src_idx = evt.GetSelection();
3791 int dest_idx = dest_tabs->GetIdxFromWindow(dest_location_tab);
7baac3cb 3792
08c068a4
BW
3793 // prevent jumpy drag
3794 if ((src_idx == dest_idx) || dest_idx == -1 ||
3795 (src_idx > dest_idx && m_last_drag_x <= pt.x) ||
3796 (src_idx < dest_idx && m_last_drag_x >= pt.x))
3797 {
3798 m_last_drag_x = pt.x;
3799 return;
3800 }
3801
3802
3803 wxWindow* src_tab = dest_tabs->GetWindowFromIdx(src_idx);
3804 dest_tabs->MovePage(src_tab, dest_idx);
3805 dest_tabs->SetActivePage((size_t)dest_idx);
3806 dest_tabs->DoShowHide();
3807 dest_tabs->Refresh();
3808 m_last_drag_x = pt.x;
3809
3810 }
7baac3cb 3811
cd05bf23
BW
3812 return;
3813 }
4444d148 3814
695c0088 3815
5d3aeb0f
BW
3816 // if external drag is allowed, check if the tab is being dragged
3817 // over a different wxAuiNotebook control
3818 if (m_flags & wxAUI_NB_TAB_EXTERNAL_MOVE)
3819 {
3820 wxWindow* tab_ctrl = ::wxFindWindowAtPoint(screen_pt);
7baac3cb 3821
87e5fe69
BW
3822 // if we aren't over any window, stop here
3823 if (!tab_ctrl)
3824 return;
7baac3cb 3825
13d0b605 3826 // make sure we are not over the hint window
87e5fe69 3827 if (!tab_ctrl->IsKindOf(CLASSINFO(wxFrame)))
5d3aeb0f 3828 {
13d0b605 3829 while (tab_ctrl)
5d3aeb0f 3830 {
13d0b605
BW
3831 if (tab_ctrl->IsKindOf(CLASSINFO(wxAuiTabCtrl)))
3832 break;
3833 tab_ctrl = tab_ctrl->GetParent();
5d3aeb0f 3834 }
7baac3cb 3835
13d0b605
BW
3836 if (tab_ctrl)
3837 {
3838 wxAuiNotebook* nb = (wxAuiNotebook*)tab_ctrl->GetParent();
7baac3cb 3839
13d0b605
BW
3840 if (nb != this)
3841 {
87e5fe69 3842 wxRect hint_rect = tab_ctrl->GetClientRect();
13d0b605
BW
3843 tab_ctrl->ClientToScreen(&hint_rect.x, &hint_rect.y);
3844 m_mgr.ShowHint(hint_rect);
3845 return;
3846 }
87e5fe69
BW
3847 }
3848 }
cedd7b22 3849 else
87e5fe69
BW
3850 {
3851 if (!dest_tabs)
3852 {
3853 // we are either over a hint window, or not over a tab
3854 // window, and there is no where to drag to, so exit
3855 return;
13d0b605 3856 }
5d3aeb0f
BW
3857 }
3858 }
3859
3860
69685ee0
BW
3861 // if there are less than two panes, split can't happen, so leave
3862 if (m_tabs.GetPageCount() < 2)
3863 return;
7baac3cb 3864
695c0088
BW
3865 // if tab moving is not allowed, leave
3866 if (!(m_flags & wxAUI_NB_TAB_SPLIT))
695c0088 3867 return;
695c0088 3868
3941df70
BW
3869
3870 if (src_tabs)
3871 {
3872 src_tabs->SetCursor(wxCursor(wxCURSOR_SIZING));
3873 }
7baac3cb
VZ
3874
3875
08c068a4 3876 if (dest_tabs)
cd05bf23 3877 {
08c068a4 3878 wxRect hint_rect = dest_tabs->GetRect();
cd05bf23
BW
3879 ClientToScreen(&hint_rect.x, &hint_rect.y);
3880 m_mgr.ShowHint(hint_rect);
3881 }
cedd7b22 3882 else
cd05bf23
BW
3883 {
3884 m_mgr.DrawHintRect(m_dummy_wnd, client_pt, zero);
3885 }
3886}
3887
3888
3889
3c778901 3890void wxAuiNotebook::OnTabEndDrag(wxAuiNotebookEvent& evt)
cd05bf23 3891{
cd05bf23 3892 m_mgr.HideHint();
4444d148 3893
7baac3cb 3894
3941df70 3895 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
9a83f860 3896 wxCHECK_RET( src_tabs, wxT("no source object?") );
54a8a78e
VZ
3897
3898 src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
7baac3cb 3899
cd05bf23
BW
3900 // get the mouse position, which will be used to determine the drop point
3901 wxPoint mouse_screen_pt = ::wxGetMousePosition();
3902 wxPoint mouse_client_pt = ScreenToClient(mouse_screen_pt);
3903
3904
4444d148 3905
5d3aeb0f
BW
3906 // check for an external move
3907 if (m_flags & wxAUI_NB_TAB_EXTERNAL_MOVE)
cd05bf23 3908 {
5d3aeb0f 3909 wxWindow* tab_ctrl = ::wxFindWindowAtPoint(mouse_screen_pt);
7baac3cb 3910
5d3aeb0f 3911 while (tab_ctrl)
c69532f7 3912 {
5d3aeb0f
BW
3913 if (tab_ctrl->IsKindOf(CLASSINFO(wxAuiTabCtrl)))
3914 break;
3915 tab_ctrl = tab_ctrl->GetParent();
c69532f7 3916 }
7baac3cb 3917
5d3aeb0f
BW
3918 if (tab_ctrl)
3919 {
3920 wxAuiNotebook* nb = (wxAuiNotebook*)tab_ctrl->GetParent();
7baac3cb 3921
5d3aeb0f
BW
3922 if (nb != this)
3923 {
3924 // find out from the destination control
3925 // if it's ok to drop this tab here
3926 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, m_windowId);
3927 e.SetSelection(evt.GetSelection());
3928 e.SetOldSelection(evt.GetSelection());
3929 e.SetEventObject(this);
3930 e.SetDragSource(this);
3931 e.Veto(); // dropping must be explicitly approved by control owner
7baac3cb 3932
5d3aeb0f 3933 nb->GetEventHandler()->ProcessEvent(e);
7baac3cb 3934
5d3aeb0f
BW
3935 if (!e.IsAllowed())
3936 {
3937 // no answer or negative answer
3938 m_mgr.HideHint();
3939 return;
3940 }
7baac3cb 3941
5d3aeb0f
BW
3942 // drop was allowed
3943 int src_idx = evt.GetSelection();
3944 wxWindow* src_page = src_tabs->GetWindowFromIdx(src_idx);
7baac3cb 3945
884a369a
JS
3946 // Check that it's not an impossible parent relationship
3947 wxWindow* p = nb;
3948 while (p && !p->IsTopLevel())
3949 {
3950 if (p == src_page)
3951 {
3952 return;
3953 }
3954 p = p->GetParent();
3955 }
3956
5d3aeb0f
BW
3957 // get main index of the page
3958 int main_idx = m_tabs.GetIdxFromWindow(src_page);
9a83f860 3959 wxCHECK_RET( main_idx != wxNOT_FOUND, wxT("no source page?") );
849c353a 3960
7baac3cb 3961
5d3aeb0f 3962 // make a copy of the page info
849c353a 3963 wxAuiNotebookPage page_info = m_tabs.GetPage(main_idx);
7baac3cb 3964
5d3aeb0f
BW
3965 // remove the page from the source notebook
3966 RemovePage(main_idx);
7baac3cb 3967
5d3aeb0f
BW
3968 // reparent the page
3969 src_page->Reparent(nb);
7baac3cb
VZ
3970
3971
5d3aeb0f
BW
3972 // found out the insert idx
3973 wxAuiTabCtrl* dest_tabs = (wxAuiTabCtrl*)tab_ctrl;
3974 wxPoint pt = dest_tabs->ScreenToClient(mouse_screen_pt);
3975
3976 wxWindow* target = NULL;
3977 int insert_idx = -1;
3978 dest_tabs->TabHitTest(pt.x, pt.y, &target);
3979 if (target)
3980 {
3981 insert_idx = dest_tabs->GetIdxFromWindow(target);
3982 }
702b1c7e 3983
7baac3cb 3984
5d3aeb0f
BW
3985 // add the page to the new notebook
3986 if (insert_idx == -1)
3987 insert_idx = dest_tabs->GetPageCount();
3988 dest_tabs->InsertPage(page_info.window, page_info, insert_idx);
3989 nb->m_tabs.AddPage(page_info.window, page_info);
3990
3991 nb->DoSizing();
3992 dest_tabs->DoShowHide();
3993 dest_tabs->Refresh();
7baac3cb 3994
5d3aeb0f 3995 // set the selection in the destination tab control
849c353a 3996 nb->SetSelectionToPage(page_info);
5d3aeb0f 3997
d92f353c
JS
3998 // notify owner that the tab has been dragged
3999 wxAuiNotebookEvent e2(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, m_windowId);
4000 e2.SetSelection(evt.GetSelection());
4001 e2.SetOldSelection(evt.GetSelection());
4002 e2.SetEventObject(this);
4003 GetEventHandler()->ProcessEvent(e2);
4004
5d3aeb0f
BW
4005 return;
4006 }
4007 }
cd05bf23 4008 }
4444d148
WS
4009
4010
4011
5d3aeb0f
BW
4012
4013 // only perform a tab split if it's allowed
54a8a78e
VZ
4014 wxAuiTabCtrl* dest_tabs = NULL;
4015
69685ee0 4016 if ((m_flags & wxAUI_NB_TAB_SPLIT) && m_tabs.GetPageCount() >= 2)
cd05bf23 4017 {
5d3aeb0f
BW
4018 // If the pointer is in an existing tab frame, do a tab insert
4019 wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt);
4020 wxTabFrame* tab_frame = (wxTabFrame*)GetTabFrameFromTabCtrl(hit_wnd);
4021 int insert_idx = -1;
4022 if (tab_frame)
4023 {
4024 dest_tabs = tab_frame->m_tabs;
cd05bf23 4025
5d3aeb0f
BW
4026 if (dest_tabs == src_tabs)
4027 return;
7baac3cb
VZ
4028
4029
5d3aeb0f
BW
4030 wxPoint pt = dest_tabs->ScreenToClient(mouse_screen_pt);
4031 wxWindow* target = NULL;
4032 dest_tabs->TabHitTest(pt.x, pt.y, &target);
4033 if (target)
4034 {
4035 insert_idx = dest_tabs->GetIdxFromWindow(target);
4036 }
4037 }
54a8a78e 4038 else
5d3aeb0f 4039 {
ce15b45f
BW
4040 wxPoint zero(0,0);
4041 wxRect rect = m_mgr.CalculateHintRect(m_dummy_wnd,
4042 mouse_client_pt,
4043 zero);
4044 if (rect.IsEmpty())
4045 {
4046 // there is no suitable drop location here, exit out
4047 return;
4048 }
7baac3cb 4049
5d3aeb0f
BW
4050 // If there is no tabframe at all, create one
4051 wxTabFrame* new_tabs = new wxTabFrame;
9fbb7d80 4052 new_tabs->m_rect = wxRect(wxPoint(0,0), CalculateNewSplitSize());
5d3aeb0f
BW
4053 new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
4054 new_tabs->m_tabs = new wxAuiTabCtrl(this,
4055 m_tab_id_counter++,
4056 wxDefaultPosition,
4057 wxDefaultSize,
a0c2e4a0 4058 wxNO_BORDER|wxWANTS_CHARS);
b0d17f7c 4059 new_tabs->m_tabs->SetArtProvider(m_tabs.GetArtProvider()->Clone());
5d3aeb0f
BW
4060 new_tabs->m_tabs->SetFlags(m_flags);
4061
4062 m_mgr.AddPane(new_tabs,
4063 wxAuiPaneInfo().Bottom().CaptionVisible(false),
4064 mouse_client_pt);
4065 m_mgr.Update();
4066 dest_tabs = new_tabs->m_tabs;
4067 }
4444d148
WS
4068
4069
4444d148 4070
5d3aeb0f
BW
4071 // remove the page from the source tabs
4072 wxAuiNotebookPage page_info = src_tabs->GetPage(evt.GetSelection());
4073 page_info.active = false;
4074 src_tabs->RemovePage(page_info.window);
4075 if (src_tabs->GetPageCount() > 0)
4076 {
4077 src_tabs->SetActivePage((size_t)0);
4078 src_tabs->DoShowHide();
4079 src_tabs->Refresh();
4080 }
4444d148 4081
cd05bf23 4082
5d3aeb0f
BW
4083
4084 // add the page to the destination tabs
4085 if (insert_idx == -1)
4086 insert_idx = dest_tabs->GetPageCount();
4087 dest_tabs->InsertPage(page_info.window, page_info, insert_idx);
4088
4089 if (src_tabs->GetPageCount() == 0)
4090 {
4091 RemoveEmptyTabFrames();
4092 }
4093
4094 DoSizing();
4095 dest_tabs->DoShowHide();
4096 dest_tabs->Refresh();
4097
68fd4f2c
BW
4098 // force the set selection function reset the selection
4099 m_curpage = -1;
c58ba15f 4100
68fd4f2c 4101 // set the active page to the one we just split off
849c353a 4102 SetSelectionToPage(page_info);
c58ba15f 4103
9fbb7d80 4104 UpdateHintWindowSize();
5d3aeb0f 4105 }
d92f353c
JS
4106
4107 // notify owner that the tab has been dragged
4108 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, m_windowId);
4109 e.SetSelection(evt.GetSelection());
4110 e.SetOldSelection(evt.GetSelection());
4111 e.SetEventObject(this);
4112 GetEventHandler()->ProcessEvent(e);
cd05bf23
BW
4113}
4114
3941df70
BW
4115
4116
a3a5df9d 4117wxAuiTabCtrl* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint& pt)
cd05bf23
BW
4118{
4119 // if we've just removed the last tab from the source
4120 // tab set, the remove the tab control completely
a3a5df9d 4121 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
4122 size_t i, pane_count = all_panes.GetCount();
4123 for (i = 0; i < pane_count; ++i)
4124 {
4125 if (all_panes.Item(i).name == wxT("dummy"))
4126 continue;
4444d148 4127
cd05bf23 4128 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
22a35096 4129 if (tabframe->m_tab_rect.Contains(pt))
cd05bf23
BW
4130 return tabframe->m_tabs;
4131 }
4444d148 4132
cd05bf23
BW
4133 return NULL;
4134}
4135
a3a5df9d 4136wxWindow* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow* tab_ctrl)
cd05bf23
BW
4137{
4138 // if we've just removed the last tab from the source
4139 // tab set, the remove the tab control completely
a3a5df9d 4140 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
4141 size_t i, pane_count = all_panes.GetCount();
4142 for (i = 0; i < pane_count; ++i)
4143 {
4144 if (all_panes.Item(i).name == wxT("dummy"))
4145 continue;
4444d148 4146
cd05bf23
BW
4147 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
4148 if (tabframe->m_tabs == tab_ctrl)
4149 {
4150 return tabframe;
4151 }
4152 }
4444d148 4153
cd05bf23
BW
4154 return NULL;
4155}
4156
a3a5df9d 4157void wxAuiNotebook::RemoveEmptyTabFrames()
cd05bf23 4158{
cd05bf23
BW
4159 // if we've just removed the last tab from the source
4160 // tab set, the remove the tab control completely
a3a5df9d 4161 wxAuiPaneInfoArray all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
4162 size_t i, pane_count = all_panes.GetCount();
4163 for (i = 0; i < pane_count; ++i)
4164 {
4165 if (all_panes.Item(i).name == wxT("dummy"))
4166 continue;
4167
4168 wxTabFrame* tab_frame = (wxTabFrame*)all_panes.Item(i).window;
4169 if (tab_frame->m_tabs->GetPageCount() == 0)
4170 {
4171 m_mgr.DetachPane(tab_frame);
4444d148 4172
cd05bf23
BW
4173 // use pending delete because sometimes during
4174 // window closing, refreshs are pending
4175 if (!wxPendingDelete.Member(tab_frame->m_tabs))
4444d148 4176 wxPendingDelete.Append(tab_frame->m_tabs);
cedd7b22 4177
13aaa50f 4178 tab_frame->m_tabs = NULL;
4444d148 4179
cd05bf23 4180 delete tab_frame;
cd05bf23
BW
4181 }
4182 }
4444d148
WS
4183
4184
cd05bf23
BW
4185 // check to see if there is still a center pane;
4186 // if there isn't, make a frame the center pane
a3a5df9d 4187 wxAuiPaneInfoArray panes = m_mgr.GetAllPanes();
cd05bf23
BW
4188 pane_count = panes.GetCount();
4189 wxWindow* first_good = NULL;
4190 bool center_found = false;
4191 for (i = 0; i < pane_count; ++i)
4192 {
4193 if (panes.Item(i).name == wxT("dummy"))
4194 continue;
4195 if (panes.Item(i).dock_direction == wxAUI_DOCK_CENTRE)
4196 center_found = true;
4197 if (!first_good)
4198 first_good = panes.Item(i).window;
4199 }
4200
4201 if (!center_found && first_good)
4202 {
4203 m_mgr.GetPane(first_good).Centre();
cd05bf23
BW
4204 }
4205
18b40f30
JS
4206 if (!m_isBeingDeleted)
4207 m_mgr.Update();
cd05bf23
BW
4208}
4209
5bf3f27f 4210void wxAuiNotebook::OnChildFocusNotebook(wxChildFocusEvent& evt)
cd05bf23 4211{
d4f4657a
VZ
4212 evt.Skip();
4213
d16619f8
BW
4214 // if we're dragging a tab, don't change the current selection.
4215 // This code prevents a bug that used to happen when the hint window
4216 // was hidden. In the bug, the focus would return to the notebook
4217 // child, which would then enter this handler and call
4218 // SetSelection, which is not desired turn tab dragging.
cedd7b22 4219
d16619f8
BW
4220 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
4221 size_t i, pane_count = all_panes.GetCount();
4222 for (i = 0; i < pane_count; ++i)
4223 {
4224 wxAuiPaneInfo& pane = all_panes.Item(i);
4225 if (pane.name == wxT("dummy"))
4226 continue;
4227 wxTabFrame* tabframe = (wxTabFrame*)pane.window;
4228 if (tabframe->m_tabs->IsDragging())
4229 return;
4230 }
4231
4232
4233 // change the tab selection to the child
4234 // which was focused
cd05bf23
BW
4235 int idx = m_tabs.GetIdxFromWindow(evt.GetWindow());
4236 if (idx != -1 && idx != m_curpage)
4237 {
4444d148 4238 SetSelection(idx);
cd05bf23
BW
4239 }
4240}
4241
5bf3f27f 4242void wxAuiNotebook::OnNavigationKeyNotebook(wxNavigationKeyEvent& event)
a0c2e4a0
JS
4243{
4244 if ( event.IsWindowChange() ) {
4245 // change pages
4246 // FIXME: the problem with this is that if we have a split notebook,
4247 // we selection may go all over the place.
4248 AdvanceSelection(event.GetDirection());
4249 }
4250 else {
4251 // we get this event in 3 cases
4252 //
4253 // a) one of our pages might have generated it because the user TABbed
4254 // out from it in which case we should propagate the event upwards and
4255 // our parent will take care of setting the focus to prev/next sibling
4256 //
4257 // or
4258 //
4259 // b) the parent panel wants to give the focus to us so that we
4260 // forward it to our selected page. We can't deal with this in
4261 // OnSetFocus() because we don't know which direction the focus came
4262 // from in this case and so can't choose between setting the focus to
4263 // first or last panel child
4264 //
4265 // or
4266 //
4267 // c) we ourselves (see MSWTranslateMessage) generated the event
4268 //
4269 wxWindow * const parent = GetParent();
4270
4271 // the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
4272 const bool isFromParent = event.GetEventObject() == (wxObject*) parent;
4273 const bool isFromSelf = event.GetEventObject() == (wxObject*) this;
4274
4275 if ( isFromParent || isFromSelf )
4276 {
4277 // no, it doesn't come from child, case (b) or (c): forward to a
4278 // page but only if direction is backwards (TAB) or from ourselves,
4279 if ( GetSelection() != wxNOT_FOUND &&
4280 (!event.GetDirection() || isFromSelf) )
4281 {
4282 // so that the page knows that the event comes from it's parent
4283 // and is being propagated downwards
4284 event.SetEventObject(this);
4285
4286 wxWindow *page = GetPage(GetSelection());
4287 if ( !page->GetEventHandler()->ProcessEvent(event) )
4288 {
4289 page->SetFocus();
4290 }
4291 //else: page manages focus inside it itself
4292 }
4293 else // otherwise set the focus to the notebook itself
4294 {
4295 SetFocus();
4296 }
4297 }
4298 else
4299 {
4300 // it comes from our child, case (a), pass to the parent, but only
4301 // if the direction is forwards. Otherwise set the focus to the
4302 // notebook itself. The notebook is always the 'first' control of a
4303 // page.
4304 if ( !event.GetDirection() )
4305 {
4306 SetFocus();
4307 }
4308 else if ( parent )
4309 {
4310 event.SetCurrentFocus(this);
4311 parent->GetEventHandler()->ProcessEvent(event);
4312 }
4313 }
4314 }
4315}
cd05bf23 4316
3c778901 4317void wxAuiNotebook::OnTabButton(wxAuiNotebookEvent& evt)
cd05bf23 4318{
cd05bf23 4319 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4444d148 4320
cd05bf23 4321 int button_id = evt.GetInt();
4444d148 4322
4953f8cf 4323 if (button_id == wxAUI_BUTTON_CLOSE)
cd05bf23 4324 {
9b362935 4325 int selection = evt.GetSelection();
4444d148 4326
94473fa8
BW
4327 if (selection == -1)
4328 {
4329 // if the close button is to the right, use the active
4330 // page selection to determine which page to close
b27fdc38 4331 selection = tabs->GetActivePage();
94473fa8 4332 }
884a369a 4333
cd05bf23
BW
4334 if (selection != -1)
4335 {
4336 wxWindow* close_wnd = tabs->GetWindowFromIdx(selection);
4444d148 4337
3fd8c988
BW
4338 // ask owner if it's ok to close the tab
4339 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, m_windowId);
4340 e.SetSelection(m_tabs.GetIdxFromWindow(close_wnd));
d92f353c
JS
4341 const int idx = m_tabs.GetIdxFromWindow(close_wnd);
4342 e.SetSelection(idx);
3fd8c988
BW
4343 e.SetOldSelection(evt.GetSelection());
4344 e.SetEventObject(this);
7ebc40e8 4345 GetEventHandler()->ProcessEvent(e);
3fd8c988
BW
4346 if (!e.IsAllowed())
4347 return;
4348
4349
89272c55 4350#if wxUSE_MDI
a3a5df9d 4351 if (close_wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
cd05bf23
BW
4352 {
4353 close_wnd->Close();
4354 }
760fdb67 4355 else
89272c55 4356#endif
cd05bf23
BW
4357 {
4358 int main_idx = m_tabs.GetIdxFromWindow(close_wnd);
9a83f860 4359 wxCHECK_RET( main_idx != wxNOT_FOUND, wxT("no page to delete?") );
760fdb67 4360
cd05bf23
BW
4361 DeletePage(main_idx);
4362 }
d92f353c
JS
4363
4364 // notify owner that the tab has been closed
4365 wxAuiNotebookEvent e2(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, m_windowId);
4366 e2.SetSelection(idx);
4367 e2.SetEventObject(this);
4368 GetEventHandler()->ProcessEvent(e2);
cd05bf23
BW
4369 }
4370 }
4371}
4372
69f5e420 4373
3c778901 4374void wxAuiNotebook::OnTabMiddleDown(wxAuiNotebookEvent& evt)
69f5e420
BW
4375{
4376 // patch event through to owner
4377 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4378 wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
4379
4380 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, m_windowId);
4381 e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
4382 e.SetEventObject(this);
4383 GetEventHandler()->ProcessEvent(e);
4384}
4385
3c778901 4386void wxAuiNotebook::OnTabMiddleUp(wxAuiNotebookEvent& evt)
69f5e420
BW
4387{
4388 // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
4389 // click should act like a tab close action. However, first
4390 // give the owner an opportunity to handle the middle up event
4391 // for custom action
cedd7b22 4392
69f5e420
BW
4393 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4394 wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
4395
4396 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, m_windowId);
4397 e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
4398 e.SetEventObject(this);
4399 if (GetEventHandler()->ProcessEvent(e))
4400 return;
4401 if (!e.IsAllowed())
4402 return;
cedd7b22 4403
69f5e420
BW
4404 // check if we are supposed to close on middle-up
4405 if ((m_flags & wxAUI_NB_MIDDLE_CLICK_CLOSE) == 0)
4406 return;
cedd7b22 4407
69f5e420
BW
4408 // simulate the user pressing the close button on the tab
4409 evt.SetInt(wxAUI_BUTTON_CLOSE);
4410 OnTabButton(evt);
4411}
4412
3c778901 4413void wxAuiNotebook::OnTabRightDown(wxAuiNotebookEvent& evt)
69f5e420
BW
4414{
4415 // patch event through to owner
4416 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4417 wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
4418
4419 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, m_windowId);
4420 e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
4421 e.SetEventObject(this);
4422 GetEventHandler()->ProcessEvent(e);
4423}
4424
3c778901 4425void wxAuiNotebook::OnTabRightUp(wxAuiNotebookEvent& evt)
69f5e420
BW
4426{
4427 // patch event through to owner
4428 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4429 wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
4430
4431 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, m_windowId);
4432 e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
4433 e.SetEventObject(this);
4434 GetEventHandler()->ProcessEvent(e);
4435}
4436
fc17828a
JS
4437// Sets the normal font
4438void wxAuiNotebook::SetNormalFont(const wxFont& font)
4439{
4440 m_normal_font = font;
4441 GetArtProvider()->SetNormalFont(font);
4442}
4443
4444// Sets the selected tab font
4445void wxAuiNotebook::SetSelectedFont(const wxFont& font)
4446{
4447 m_selected_font = font;
4448 GetArtProvider()->SetSelectedFont(font);
4449}
4450
4451// Sets the measuring font
4452void wxAuiNotebook::SetMeasuringFont(const wxFont& font)
4453{
4454 GetArtProvider()->SetMeasuringFont(font);
4455}
4456
4457// Sets the tab font
4458bool wxAuiNotebook::SetFont(const wxFont& font)
4459{
4460 wxControl::SetFont(font);
cd05bf23 4461
fc17828a
JS
4462 wxFont normalFont(font);
4463 wxFont selectedFont(normalFont);
4464 selectedFont.SetWeight(wxBOLD);
4465
4466 SetNormalFont(normalFont);
4467 SetSelectedFont(selectedFont);
4468 SetMeasuringFont(selectedFont);
4469
4470 return true;
4471}
4472
4473// Gets the tab control height
4474int wxAuiNotebook::GetTabCtrlHeight() const
4475{
4476 return m_tab_ctrl_height;
4477}
4478
4479// Gets the height of the notebook for a given page height
4480int wxAuiNotebook::GetHeightForPageHeight(int pageHeight)
4481{
4482 UpdateTabCtrlHeight();
4483
4484 int tabCtrlHeight = GetTabCtrlHeight();
4485 int decorHeight = 2;
4486 return tabCtrlHeight + pageHeight + decorHeight;
4487}
cd05bf23 4488
a0c2e4a0
JS
4489// Advances the selection, generation page selection events
4490void wxAuiNotebook::AdvanceSelection(bool forward)
4491{
4492 if (GetPageCount() <= 1)
4493 return;
4494
4495 int currentSelection = GetSelection();
4496
4497 if (forward)
4498 {
4499 if (currentSelection == (int) (GetPageCount() - 1))
4500 return;
4501 else if (currentSelection == -1)
4502 currentSelection = 0;
4503 else
4504 currentSelection ++;
4505 }
4506 else
4507 {
4508 if (currentSelection <= 0)
4509 return;
4510 else
4511 currentSelection --;
4512 }
4513
4514 SetSelection(currentSelection);
4515}
4516
4517// Shows the window menu
4518bool wxAuiNotebook::ShowWindowMenu()
4519{
4520 wxAuiTabCtrl* tabCtrl = GetActiveTabCtrl();
4521
4522 int idx = tabCtrl->GetArtProvider()->ShowDropDown(tabCtrl, tabCtrl->GetPages(), tabCtrl->GetActivePage());
4523
4524 if (idx != -1)
4525 {
4526 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, tabCtrl->GetId());
4527 e.SetSelection(idx);
4528 e.SetOldSelection(tabCtrl->GetActivePage());
4529 e.SetEventObject(tabCtrl);
4530 GetEventHandler()->ProcessEvent(e);
4531
4532 return true;
4533 }
4534 else
4535 return false;
4536}
cd05bf23 4537
64178c36
JS
4538void wxAuiNotebook::Thaw()
4539{
4540 DoSizing();
4541
4542 wxControl::Thaw();
4543}
4544
cd05bf23 4545#endif // wxUSE_AUI