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