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