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