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