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