]> git.saurik.com Git - wxWidgets.git/blame - src/aui/auibook.cpp
implemented wxAUI_NB_WINDOWLIST_BUTTON and wxAUI_NB_SCROLL_BUTTONS in wxAuiNotebook
[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"
32
cd05bf23
BW
33#include "wx/arrimpl.cpp"
34WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray)
35WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray)
36
37DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING)
38DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED)
39DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON)
40DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG)
41DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG)
42DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION)
43
44
0ce53f32 45IMPLEMENT_CLASS(wxAuiNotebook, wxControl)
cd05bf23
BW
46IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent, wxEvent)
47
cd05bf23
BW
48
49
cd05bf23
BW
50
51
52// This functions are here for this proof of concept
53// and will be factored out later. See dockart.cpp
54static wxColor StepColour(const wxColor& c, int percent)
55{
56 int r = c.Red(), g = c.Green(), b = c.Blue();
57 return wxColour((unsigned char)wxMin((r*percent)/100,255),
58 (unsigned char)wxMin((g*percent)/100,255),
59 (unsigned char)wxMin((b*percent)/100,255));
60}
61
62// This functions are here for this proof of concept
63// and will be factored out later. See dockart.cpp
64static wxBitmap BitmapFromBits(const unsigned char bits[], int w, int h,
65 const wxColour& color)
66{
67 wxImage img = wxBitmap((const char*)bits, w, h).ConvertToImage();
df00bdf7
RR
68 img.Replace(0,0,0,123,123,123);
69 img.Replace(255,255,255,color.Red(),color.Green(),color.Blue());
cd05bf23
BW
70 img.SetMaskColour(123,123,123);
71 return wxBitmap(img);
72}
73
4953f8cf 74static void DrawButtonS(wxDC& dc,
cd05bf23
BW
75 const wxRect& _rect,
76 const wxBitmap& bmp,
77 const wxColour& bkcolour,
78 int button_state)
79{
80 wxRect rect = _rect;
81
82 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
83 {
84 rect.x++;
85 rect.y++;
86 }
87
88 if (button_state == wxAUI_BUTTON_STATE_HOVER ||
89 button_state == wxAUI_BUTTON_STATE_PRESSED)
90 {
91 dc.SetBrush(wxBrush(StepColour(bkcolour, 120)));
92 dc.SetPen(wxPen(StepColour(bkcolour, 70)));
93
94 // draw the background behind the button
95 dc.DrawRectangle(rect.x, rect.y, 15, 15);
96 }
97
98 // draw the button itself
99 dc.DrawBitmap(bmp, rect.x, rect.y, true);
100}
101
102
103
104
3f69756e 105
a3a5df9d 106// -- wxAuiDefaultTabArt class implementation --
3f69756e 107
a3a5df9d 108wxAuiDefaultTabArt::wxAuiDefaultTabArt()
cd05bf23
BW
109{
110 m_normal_font = *wxNORMAL_FONT;
111 m_selected_font = *wxNORMAL_FONT;
112 m_selected_font.SetWeight(wxBOLD);
113 m_measuring_font = m_selected_font;
4444d148 114
cd05bf23 115 wxColour base_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
4444d148 116
cd05bf23
BW
117 wxColour background_colour = StepColour(base_colour, 95);
118 wxColour normaltab_colour = base_colour;
119 wxColour selectedtab_colour = *wxWHITE;
4444d148 120
cd05bf23
BW
121 m_bkbrush = wxBrush(background_colour);
122 m_normal_bkbrush = wxBrush(normaltab_colour);
123 m_normal_bkpen = wxPen(normaltab_colour);
124 m_selected_bkbrush = wxBrush(selectedtab_colour);
125 m_selected_bkpen = wxPen(selectedtab_colour);
4953f8cf
BW
126
127
128#if defined( __WXMAC__ )
129 static unsigned char close_bits[]={
130 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
131 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
132 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
133#elif defined( __WXGTK__)
134 static unsigned char close_bits[]={
135 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
136 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
137 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
138#else
139 static unsigned char close_bits[]={
140 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
141 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
142 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
143#endif
144
145 static unsigned char left_bits[] = {
146 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
147 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
148 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
149
150 static unsigned char right_bits[] = {
151 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
152 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
153 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
154
01372b8f
BW
155 static unsigned char list_bits[] = {
156 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
157 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
158 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
159
160
4953f8cf
BW
161 m_active_close_bmp = BitmapFromBits(close_bits, 16, 16, *wxBLACK);
162 m_disabled_close_bmp = BitmapFromBits(close_bits, 16, 16, wxColour(128,128,128));
163
164 m_active_left_bmp = BitmapFromBits(left_bits, 16, 16, *wxBLACK);
165 m_disabled_left_bmp = BitmapFromBits(left_bits, 16, 16, wxColour(128,128,128));
166
167 m_active_right_bmp = BitmapFromBits(right_bits, 16, 16, *wxBLACK);
168 m_disabled_right_bmp = BitmapFromBits(right_bits, 16, 16, wxColour(128,128,128));
01372b8f
BW
169
170 m_active_windowlist_bmp = BitmapFromBits(list_bits, 16, 16, *wxBLACK);
171 m_disabled_windowlist_bmp = BitmapFromBits(list_bits, 16, 16, wxColour(128,128,128));
172
cd05bf23
BW
173}
174
a3a5df9d 175wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
488e50ee
BW
176{
177}
178
a3a5df9d 179void wxAuiDefaultTabArt::DrawBackground(wxDC* dc,
01372b8f
BW
180 wxWindow* WXUNUSED(wnd),
181 const wxRect& rect)
3f69756e
BW
182{
183 // draw background
184 dc->SetBrush(m_bkbrush);
185 dc->SetPen(*wxTRANSPARENT_PEN);
186 dc->DrawRectangle(-1, -1, rect.GetWidth()+2, rect.GetHeight()+2);
187
188 // draw base line
189 dc->SetPen(*wxGREY_PEN);
190 dc->DrawLine(0, rect.GetHeight()-1, rect.GetWidth(), rect.GetHeight()-1);
191}
192
4953f8cf 193
3f69756e
BW
194// DrawTab() draws an individual tab.
195//
196// dc - output dc
197// in_rect - rectangle the tab should be confined to
198// caption - tab's caption
199// active - whether or not the tab is active
200// out_rect - actual output rectangle
201// x_extent - the advance x; where the next tab should start
202
a3a5df9d 203void wxAuiDefaultTabArt::DrawTab(wxDC* dc,
01372b8f
BW
204 wxWindow* wnd,
205 const wxRect& in_rect,
206 const wxString& caption_text,
207 bool active,
208 int close_button_state,
209 wxRect* out_tab_rect,
210 wxRect* out_button_rect,
211 int* x_extent)
3f69756e
BW
212{
213 wxCoord normal_textx, normal_texty;
214 wxCoord selected_textx, selected_texty;
3f69756e 215 wxCoord textx, texty;
a4c8fc23 216
3f69756e
BW
217 // if the caption is empty, measure some temporary text
218 wxString caption = caption_text;
219 if (caption_text.empty())
220 caption = wxT("Xj");
a4c8fc23 221
3f69756e
BW
222 dc->SetFont(m_selected_font);
223 dc->GetTextExtent(caption, &selected_textx, &selected_texty);
a4c8fc23 224
3f69756e
BW
225 dc->SetFont(m_normal_font);
226 dc->GetTextExtent(caption, &normal_textx, &normal_texty);
a4c8fc23
BW
227
228 // figure out the size of the tab
01372b8f 229 wxSize tab_size = GetTabSize(dc, wnd, caption, active, close_button_state, x_extent);
3f69756e 230
a4c8fc23
BW
231 wxCoord tab_height = tab_size.y;
232 wxCoord tab_width = tab_size.x;
3f69756e
BW
233 wxCoord tab_x = in_rect.x;
234 wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
235
3f69756e
BW
236 // select pen, brush and font for the tab to be drawn
237
238 if (active)
239 {
240 dc->SetPen(m_selected_bkpen);
241 dc->SetBrush(m_selected_bkbrush);
242 dc->SetFont(m_selected_font);
243 textx = selected_textx;
244 texty = selected_texty;
245 }
246 else
247 {
248 dc->SetPen(m_normal_bkpen);
249 dc->SetBrush(m_normal_bkbrush);
250 dc->SetFont(m_normal_font);
251 textx = normal_textx;
252 texty = normal_texty;
253 }
254
255
256 // -- draw line --
257
258 wxPoint points[7];
259 points[0].x = tab_x;
260 points[0].y = tab_y + tab_height - 1;
261 points[1].x = tab_x + tab_height - 3;
262 points[1].y = tab_y + 2;
263 points[2].x = tab_x + tab_height + 3;
264 points[2].y = tab_y;
265 points[3].x = tab_x + tab_width - 2;
266 points[3].y = tab_y;
267 points[4].x = tab_x + tab_width;
268 points[4].y = tab_y + 2;
269 points[5].x = tab_x + tab_width;
270 points[5].y = tab_y + tab_height - 1;
271 points[6] = points[0];
272
273
274 dc->DrawPolygon(6, points);
275
276 dc->SetPen(*wxGREY_PEN);
277
278 //dc->DrawLines(active ? 6 : 7, points);
279 dc->DrawLines(7, points);
280
3f69756e 281
702b1c7e
BW
282 int text_offset;
283
284 int close_button_width = 0;
41b76acd 285 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
702b1c7e
BW
286 {
287 close_button_width = m_active_close_bmp.GetWidth();
288 text_offset = tab_x + (tab_height/2) + ((tab_width-close_button_width)/2) - (textx/2);
289 }
290 else
291 {
292 text_offset = tab_x + (tab_height/3) + (tab_width/2) - (textx/2);
293 }
294
295
296 // draw tab text
3f69756e 297 dc->DrawText(caption,
702b1c7e 298 text_offset,
a4c8fc23 299 (tab_y + tab_height)/2 - (texty/2) + 1);
3f69756e 300
702b1c7e
BW
301
302 // draw close button if necessary
41b76acd 303 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
702b1c7e
BW
304 {
305 wxBitmap bmp;
306 if (active)
307 bmp = m_active_close_bmp;
308 else
309 bmp = m_disabled_close_bmp;
310
0b3d6ff9
BW
311 wxRect rect(tab_x + tab_width - close_button_width - 1,
312 tab_y + (tab_height/2) - (bmp.GetHeight()/2) + 1,
313 close_button_width,
314 tab_height - 1);
41b76acd
BW
315 DrawButtonS(*dc, rect, bmp, *wxWHITE, close_button_state);
316
317 *out_button_rect = rect;
702b1c7e
BW
318 }
319
320
41b76acd 321 *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
3f69756e
BW
322}
323
324
a3a5df9d 325wxSize wxAuiDefaultTabArt::GetTabSize(wxDC* dc,
01372b8f
BW
326 wxWindow* WXUNUSED(wnd),
327 const wxString& caption,
328 bool WXUNUSED(active),
329 int close_button_state,
330 int* x_extent)
4953f8cf
BW
331{
332 wxCoord measured_textx, measured_texty;
333
334 dc->SetFont(m_measuring_font);
335 dc->GetTextExtent(caption, &measured_textx, &measured_texty);
336
337 wxCoord tab_height = measured_texty + 4;
338 wxCoord tab_width = measured_textx + tab_height + 5;
339
41b76acd 340 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
702b1c7e
BW
341 tab_width += m_active_close_bmp.GetWidth();
342
4953f8cf
BW
343 *x_extent = tab_width - (tab_height/2) - 1;
344
345 return wxSize(tab_width, tab_height);
346}
347
348
a3a5df9d 349void wxAuiDefaultTabArt::DrawButton(
01372b8f
BW
350 wxDC* dc,
351 wxWindow* WXUNUSED(wnd),
352 const wxRect& in_rect,
353 int bitmap_id,
354 int button_state,
355 int orientation,
356 const wxBitmap& bitmap_override,
357 wxRect* out_rect)
4953f8cf
BW
358{
359 wxBitmap bmp;
360 wxRect rect;
361
362 if (bitmap_override.IsOk())
363 {
364 bmp = bitmap_override;
365 }
366 else
367 {
368 switch (bitmap_id)
369 {
370 case wxAUI_BUTTON_CLOSE:
371 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
372 bmp = m_disabled_close_bmp;
373 else
374 bmp = m_active_close_bmp;
375 break;
376 case wxAUI_BUTTON_LEFT:
377 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
378 bmp = m_disabled_left_bmp;
379 else
380 bmp = m_active_left_bmp;
381 break;
382 case wxAUI_BUTTON_RIGHT:
383 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
384 bmp = m_disabled_right_bmp;
385 else
386 bmp = m_active_right_bmp;
387 break;
01372b8f
BW
388 case wxAUI_BUTTON_WINDOWLIST:
389 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
390 bmp = m_disabled_windowlist_bmp;
391 else
392 bmp = m_active_windowlist_bmp;
393 break;
4953f8cf
BW
394 }
395 }
396
397 if (!bmp.IsOk())
398 return;
399
400 rect = in_rect;
401
402 if (orientation == wxLEFT)
403 {
25d7497c
BW
404 rect.SetX(in_rect.x);
405 rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2));
4953f8cf
BW
406 rect.SetWidth(bmp.GetWidth());
407 rect.SetHeight(bmp.GetHeight());
408 }
409 else
410 {
25d7497c
BW
411 rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
412 ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
4953f8cf
BW
413 bmp.GetWidth(), bmp.GetHeight());
414 }
415
416
417 DrawButtonS(*dc, rect, bmp, *wxWHITE, button_state);
418
419 *out_rect = rect;
420}
421
422
423
01372b8f
BW
424
425// -- GUI helper classes and functions --
426
427class wxAuiCommandCapture : public wxEvtHandler
428{
429public:
430
431 wxAuiCommandCapture() { m_last_id = 0; }
432 int GetCommandId() const { return m_last_id; }
433
434 bool ProcessEvent(wxEvent& evt)
435 {
436 if (evt.GetEventType() == wxEVT_COMMAND_MENU_SELECTED)
437 {
438 m_last_id = evt.GetId();
439 return true;
440 }
441
442 if (GetNextHandler())
443 return GetNextHandler()->ProcessEvent(evt);
444
445 return false;
446 }
447
448private:
449 int m_last_id;
450};
451
452
453
454int wxAuiDefaultTabArt::ShowWindowList(wxWindow* wnd,
455 const wxArrayString& items,
456 int active_idx)
457{
458 wxMenu menuPopup;
459
460 size_t i, count = items.GetCount();
461 for (i = 0; i < count; ++i)
462 {
463 menuPopup.AppendCheckItem(1000+i, items.Item(i));
464 }
465
466 if (active_idx != -1)
467 {
468 menuPopup.Check(1000+active_idx, true);
469 }
470
471 // find out where to put the popup menu of window
472 // items. Subtract 100 for now to center the menu
473 // a bit, until a better mechanism can be implemented
474 wxPoint pt = ::wxGetMousePosition();
475 pt = wnd->ScreenToClient(pt);
476 if (pt.x < 100)
477 pt.x = 0;
478 else
479 pt.x -= 100;
480
481 // find out the screen coordinate at the bottom of the tab ctrl
482 wxRect cli_rect = wnd->GetClientRect();
483 pt.y = cli_rect.y + cli_rect.height;
484
485 wxAuiCommandCapture* cc = new wxAuiCommandCapture;
486 wnd->PushEventHandler(cc);
487 wnd->PopupMenu(&menuPopup, pt);
488 int command = cc->GetCommandId();
489 wnd->PopEventHandler(true);
490
491 if (command >= 1000)
492 return command-1000;
493
494 return -1;
495}
496
a3a5df9d 497int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow* wnd)
a4c8fc23
BW
498{
499 wxClientDC dc(wnd);
500 dc.SetFont(m_measuring_font);
501 int x_ext = 0;
01372b8f
BW
502 wxSize s = GetTabSize(&dc,
503 wnd,
504 wxT("ABCDEFGHIj"),
505 true,
506 wxAUI_BUTTON_STATE_HIDDEN,
507 &x_ext);
a4c8fc23
BW
508 return s.y+3;
509}
4953f8cf 510
a3a5df9d 511void wxAuiDefaultTabArt::SetNormalFont(const wxFont& font)
3f69756e
BW
512{
513 m_normal_font = font;
514}
515
a3a5df9d 516void wxAuiDefaultTabArt::SetSelectedFont(const wxFont& font)
3f69756e
BW
517{
518 m_selected_font = font;
519}
520
a3a5df9d 521void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont& font)
3f69756e
BW
522{
523 m_measuring_font = font;
524}
525
526
527
528
529
530
531// -- wxAuiTabContainer class implementation --
532
533
534// wxAuiTabContainer is a class which contains information about each
535// tab. It also can render an entire tab control to a specified DC.
536// It's not a window class itself, because this code will be used by
537// the wxFrameMananger, where it is disadvantageous to have separate
538// windows for each tab control in the case of "docked tabs"
539
540// A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
541// which can be used as a tab control in the normal sense.
542
543
544wxAuiTabContainer::wxAuiTabContainer()
545{
4953f8cf 546 m_tab_offset = 0;
702b1c7e 547 m_flags = 0;
a3a5df9d 548 m_art = new wxAuiDefaultTabArt;
4953f8cf
BW
549
550 AddButton(wxAUI_BUTTON_LEFT, wxLEFT);
01372b8f
BW
551 AddButton(wxAUI_BUTTON_RIGHT, wxRIGHT);
552 AddButton(wxAUI_BUTTON_WINDOWLIST, wxRIGHT);
4953f8cf 553 AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT);
3f69756e
BW
554}
555
fe498448
BW
556wxAuiTabContainer::~wxAuiTabContainer()
557{
3f69756e
BW
558 delete m_art;
559}
560
a3a5df9d 561void wxAuiTabContainer::SetArtProvider(wxAuiTabArt* art)
3f69756e
BW
562{
563 delete m_art;
564 m_art = art;
565}
566
a3a5df9d 567wxAuiTabArt* wxAuiTabContainer::GetArtProvider()
3f69756e
BW
568{
569 return m_art;
fe498448
BW
570}
571
702b1c7e
BW
572void wxAuiTabContainer::SetFlags(unsigned int flags)
573{
574 m_flags = flags;
41b76acd
BW
575
576 // check for new close button settings
01372b8f
BW
577 RemoveButton(wxAUI_BUTTON_LEFT);
578 RemoveButton(wxAUI_BUTTON_RIGHT);
579 RemoveButton(wxAUI_BUTTON_WINDOWLIST);
41b76acd 580 RemoveButton(wxAUI_BUTTON_CLOSE);
01372b8f
BW
581
582
583 if (flags & wxAUI_NB_SCROLL_BUTTONS)
584 {
585 AddButton(wxAUI_BUTTON_LEFT, wxLEFT);
586 AddButton(wxAUI_BUTTON_RIGHT, wxRIGHT);
587 }
588
589 if (flags & wxAUI_NB_WINDOWLIST_BUTTON)
590 {
591 AddButton(wxAUI_BUTTON_WINDOWLIST, wxRIGHT);
592 }
593
41b76acd
BW
594 if (flags & wxAUI_NB_CLOSE_BUTTON)
595 {
596 AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT);
597 }
702b1c7e
BW
598}
599
600unsigned int wxAuiTabContainer::GetFlags() const
601{
602 return m_flags;
603}
604
605
cd05bf23
BW
606void wxAuiTabContainer::SetNormalFont(const wxFont& font)
607{
3f69756e 608 m_art->SetNormalFont(font);
cd05bf23
BW
609}
610
611void wxAuiTabContainer::SetSelectedFont(const wxFont& font)
612{
3f69756e 613 m_art->SetSelectedFont(font);
cd05bf23
BW
614}
615
616void wxAuiTabContainer::SetMeasuringFont(const wxFont& font)
617{
3f69756e 618 m_art->SetMeasuringFont(font);
cd05bf23
BW
619}
620
621void wxAuiTabContainer::SetRect(const wxRect& rect)
622{
623 m_rect = rect;
624}
625
626bool wxAuiTabContainer::AddPage(wxWindow* page,
627 const wxAuiNotebookPage& info)
628{
629 wxAuiNotebookPage page_info;
630 page_info = info;
631 page_info.window = page;
4444d148 632
cd05bf23
BW
633 m_pages.Add(page_info);
634
635 return true;
636}
637
638bool wxAuiTabContainer::InsertPage(wxWindow* page,
639 const wxAuiNotebookPage& info,
640 size_t idx)
641{
642 wxAuiNotebookPage page_info;
643 page_info = info;
644 page_info.window = page;
4444d148 645
cd05bf23
BW
646 if (idx >= m_pages.GetCount())
647 m_pages.Add(page_info);
648 else
649 m_pages.Insert(page_info, idx);
650
651 return true;
652}
653
2fadbbfd
BW
654bool wxAuiTabContainer::MovePage(wxWindow* page,
655 size_t new_idx)
656{
657 int idx = GetIdxFromWindow(page);
658 if (idx == -1)
659 return false;
660
661 // get page entry, make a copy of it
662 wxAuiNotebookPage p = GetPage(idx);
663
664 // remove old page entry
665 RemovePage(page);
666
667 // insert page where it should be
668 InsertPage(page, p, new_idx);
669
670 return true;
671}
672
cd05bf23
BW
673bool wxAuiTabContainer::RemovePage(wxWindow* wnd)
674{
675 size_t i, page_count = m_pages.GetCount();
676 for (i = 0; i < page_count; ++i)
677 {
678 wxAuiNotebookPage& page = m_pages.Item(i);
679 if (page.window == wnd)
680 {
681 m_pages.RemoveAt(i);
682 return true;
683 }
684 }
4444d148 685
cd05bf23
BW
686 return false;
687}
688
689bool wxAuiTabContainer::SetActivePage(wxWindow* wnd)
690{
691 bool found = false;
4444d148 692
cd05bf23
BW
693 size_t i, page_count = m_pages.GetCount();
694 for (i = 0; i < page_count; ++i)
695 {
696 wxAuiNotebookPage& page = m_pages.Item(i);
697 if (page.window == wnd)
698 {
699 page.active = true;
700 found = true;
701 }
702 else
703 {
704 page.active = false;
705 }
706 }
4444d148 707
cd05bf23
BW
708 return found;
709}
710
711void wxAuiTabContainer::SetNoneActive()
712{
713 size_t i, page_count = m_pages.GetCount();
714 for (i = 0; i < page_count; ++i)
715 {
716 wxAuiNotebookPage& page = m_pages.Item(i);
717 page.active = false;
718 }
719}
720
721bool wxAuiTabContainer::SetActivePage(size_t page)
722{
723 if (page >= m_pages.GetCount())
724 return false;
4444d148 725
cd05bf23
BW
726 return SetActivePage(m_pages.Item(page).window);
727}
4444d148 728
cd05bf23
BW
729int wxAuiTabContainer::GetActivePage() const
730{
731 size_t i, page_count = m_pages.GetCount();
732 for (i = 0; i < page_count; ++i)
733 {
734 wxAuiNotebookPage& page = m_pages.Item(i);
735 if (page.active)
736 return i;
737 }
4444d148 738
cd05bf23
BW
739 return -1;
740}
741
742wxWindow* wxAuiTabContainer::GetWindowFromIdx(size_t idx) const
743{
744 if (idx >= m_pages.GetCount())
745 return NULL;
4444d148 746
cd05bf23
BW
747 return m_pages[idx].window;
748}
749
750int wxAuiTabContainer::GetIdxFromWindow(wxWindow* wnd) const
751{
752 size_t i, page_count = m_pages.GetCount();
753 for (i = 0; i < page_count; ++i)
754 {
755 wxAuiNotebookPage& page = m_pages.Item(i);
756 if (page.window == wnd)
757 return i;
758 }
759 return -1;
760}
761
762wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx)
763{
764 wxASSERT_MSG(idx < m_pages.GetCount(), wxT("Invalid Page index"));
765
766 return m_pages[idx];
767}
768
769wxAuiNotebookPageArray& wxAuiTabContainer::GetPages()
770{
771 return m_pages;
772}
773
774size_t wxAuiTabContainer::GetPageCount() const
775{
776 return m_pages.GetCount();
777}
778
4953f8cf
BW
779void wxAuiTabContainer::AddButton(int id,
780 int location,
781 const wxBitmap& normal_bitmap,
782 const wxBitmap& disabled_bitmap)
cd05bf23
BW
783{
784 wxAuiTabContainerButton button;
785 button.id = id;
4953f8cf
BW
786 button.bitmap = normal_bitmap;
787 button.dis_bitmap = disabled_bitmap;
b6418695 788 button.location = location;
cd05bf23 789 button.cur_state = wxAUI_BUTTON_STATE_NORMAL;
4444d148 790
cd05bf23
BW
791 m_buttons.Add(button);
792}
793
41b76acd
BW
794void wxAuiTabContainer::RemoveButton(int id)
795{
796 size_t i, button_count = m_buttons.GetCount();
797
798 for (i = 0; i < button_count; ++i)
799 {
800 if (m_buttons.Item(i).id == id)
801 {
802 m_buttons.RemoveAt(i);
803 return;
804 }
805 }
806}
807
808
809
4953f8cf
BW
810size_t wxAuiTabContainer::GetTabOffset() const
811{
812 return m_tab_offset;
813}
cd05bf23 814
4953f8cf
BW
815void wxAuiTabContainer::SetTabOffset(size_t offset)
816{
817 m_tab_offset = offset;
818}
cd05bf23 819
cd05bf23
BW
820// Render() renders the tab catalog to the specified DC
821// It is a virtual function and can be overridden to
822// provide custom drawing capabilities
01372b8f 823void wxAuiTabContainer::Render(wxDC* raw_dc, wxWindow* wnd)
4444d148 824{
cd05bf23
BW
825 wxMemoryDC dc;
826 wxBitmap bmp;
4953f8cf
BW
827 size_t i;
828 size_t page_count = m_pages.GetCount();
829 size_t button_count = m_buttons.GetCount();
830
831 // create off-screen bitmap
cd05bf23
BW
832 bmp.Create(m_rect.GetWidth(), m_rect.GetHeight());
833 dc.SelectObject(bmp);
4444d148 834
4953f8cf
BW
835
836 // find out if size of tabs is larger than can be
837 // afforded on screen
838 int total_width = 0;
25d7497c 839 int visible_width = 0;
4953f8cf
BW
840 for (i = 0; i < page_count; ++i)
841 {
842 wxAuiNotebookPage& page = m_pages.Item(i);
702b1c7e
BW
843
844 // determine if a close button is on this tab
845 bool close_button = false;
846 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
847 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
848 {
849 close_button = true;
850 }
851
852
4953f8cf 853 int x_extent = 0;
41b76acd 854 wxSize size = m_art->GetTabSize(&dc,
01372b8f 855 wnd,
41b76acd
BW
856 page.caption,
857 page.active,
858 close_button ?
859 wxAUI_BUTTON_STATE_NORMAL :
860 wxAUI_BUTTON_STATE_HIDDEN,
861 &x_extent);
25d7497c 862
4953f8cf
BW
863 if (i+1 < page_count)
864 total_width += x_extent;
865 else
866 total_width += size.x;
25d7497c
BW
867
868 if (i >= m_tab_offset)
869 {
870 if (i+1 < page_count)
871 visible_width += x_extent;
872 else
873 visible_width += size.x;
874 }
4953f8cf
BW
875 }
876
877 if (total_width > m_rect.GetWidth() - 20 || m_tab_offset != 0)
878 {
879 // show left/right buttons
880 for (i = 0; i < button_count; ++i)
881 {
882 wxAuiTabContainerButton& button = m_buttons.Item(i);
883 if (button.id == wxAUI_BUTTON_LEFT ||
884 button.id == wxAUI_BUTTON_RIGHT)
885 {
886 button.cur_state &= ~wxAUI_BUTTON_STATE_HIDDEN;
887 }
888 }
889 }
890 else
891 {
892 // hide left/right buttons
893 for (i = 0; i < button_count; ++i)
894 {
895 wxAuiTabContainerButton& button = m_buttons.Item(i);
896 if (button.id == wxAUI_BUTTON_LEFT ||
897 button.id == wxAUI_BUTTON_RIGHT)
898 {
899 button.cur_state |= wxAUI_BUTTON_STATE_HIDDEN;
900 }
901 }
902 }
903
25d7497c
BW
904 // determine whether left button should be enabled
905 for (i = 0; i < button_count; ++i)
906 {
907 wxAuiTabContainerButton& button = m_buttons.Item(i);
908 if (button.id == wxAUI_BUTTON_LEFT)
909 {
910 if (m_tab_offset == 0)
911 button.cur_state |= wxAUI_BUTTON_STATE_DISABLED;
912 else
913 button.cur_state &= ~wxAUI_BUTTON_STATE_DISABLED;
914 }
915 if (button.id == wxAUI_BUTTON_RIGHT)
916 {
917 if (visible_width < m_rect.GetWidth() - ((int)button_count*16))
918 button.cur_state |= wxAUI_BUTTON_STATE_DISABLED;
919 else
920 button.cur_state &= ~wxAUI_BUTTON_STATE_DISABLED;
921 }
922 }
923
4953f8cf
BW
924
925
926 // draw background
01372b8f 927 m_art->DrawBackground(&dc, wnd, m_rect);
4444d148 928
4953f8cf
BW
929 // draw buttons
930 int left_buttons_width = 0;
931 int right_buttons_width = 0;
932
cd05bf23 933 int offset = 0;
b6418695
BW
934
935 // draw the buttons on the right side
936 offset = m_rect.x + m_rect.width;
b6418695
BW
937 for (i = 0; i < button_count; ++i)
938 {
939 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
940
941 if (button.location != wxRIGHT)
942 continue;
4953f8cf
BW
943 if (button.cur_state & wxAUI_BUTTON_STATE_HIDDEN)
944 continue;
945
946 wxRect button_rect = m_rect;
947 button_rect.SetY(1);
948 button_rect.SetWidth(offset);
949
950 m_art->DrawButton(&dc,
01372b8f 951 wnd,
4953f8cf
BW
952 button_rect,
953 button.id,
954 button.cur_state,
955 wxRIGHT,
956 wxNullBitmap,
957 &button.rect);
958
959 offset -= button.rect.GetWidth();
960 right_buttons_width += button.rect.GetWidth();
b6418695
BW
961 }
962
963
964
965 offset = 0;
966
967 // draw the buttons on the left side
968
969 for (i = 0; i < button_count; ++i)
970 {
971 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
972
973 if (button.location != wxLEFT)
974 continue;
4953f8cf
BW
975 if (button.cur_state & wxAUI_BUTTON_STATE_HIDDEN)
976 continue;
977
978 wxRect button_rect(offset, 1, 1000, m_rect.height);
979
980 m_art->DrawButton(&dc,
01372b8f 981 wnd,
4953f8cf
BW
982 button_rect,
983 button.id,
984 button.cur_state,
985 wxLEFT,
986 wxNullBitmap,
987 &button.rect);
988
989 offset += button.rect.GetWidth();
990 left_buttons_width += button.rect.GetWidth();
b6418695
BW
991 }
992
4953f8cf
BW
993 offset = left_buttons_width;
994
702b1c7e 995 // set a clipping region to the tabs don't draw over the buttons
4953f8cf
BW
996 dc.SetClippingRegion(left_buttons_width, 0,
997 m_rect.GetWidth() - right_buttons_width - left_buttons_width - 2,
998 m_rect.GetHeight());
702b1c7e
BW
999
1000
41b76acd
BW
1001
1002 // prepare the tab-close-button array
1003 while (m_tab_close_buttons.GetCount() < page_count)
1004 {
1005 wxAuiTabContainerButton tempbtn;
1006 tempbtn.id = wxAUI_BUTTON_CLOSE;
1007 tempbtn.location = wxCENTER;
1008 tempbtn.cur_state = wxAUI_BUTTON_STATE_HIDDEN;
1009 m_tab_close_buttons.Add(tempbtn);
1010 }
1011
1012 for (i = 0; i < m_tab_offset; ++i)
1013 {
1014 // buttons before the tab offset must be set to hidden
1015 m_tab_close_buttons.Item(i).cur_state = wxAUI_BUTTON_STATE_HIDDEN;
1016 }
1017
4953f8cf 1018
b6418695 1019 // draw the tabs
cd05bf23
BW
1020
1021 size_t active = 999;
1022 int active_offset = 0;
4444d148 1023
cd05bf23
BW
1024 int x_extent = 0;
1025 wxRect rect = m_rect;
1026 rect.y = 0;
1027 rect.width = 1000;
1028 rect.height = m_rect.height;
4444d148 1029
4953f8cf 1030 for (i = m_tab_offset; i < page_count; ++i)
cd05bf23
BW
1031 {
1032 wxAuiNotebookPage& page = m_pages.Item(i);
41b76acd 1033 wxAuiTabContainerButton& tab_button = m_tab_close_buttons.Item(i);
4444d148 1034
702b1c7e
BW
1035 // determine if a close button is on this tab
1036 bool close_button = false;
1037 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
1038 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
1039 {
1040 close_button = true;
41b76acd
BW
1041 if (tab_button.cur_state == wxAUI_BUTTON_STATE_HIDDEN)
1042 {
1043 tab_button.id = wxAUI_BUTTON_CLOSE;
1044 tab_button.cur_state = wxAUI_BUTTON_STATE_NORMAL;
1045 tab_button.location = wxCENTER;
1046 }
1047 }
1048 else
1049 {
1050 tab_button.cur_state = wxAUI_BUTTON_STATE_HIDDEN;
702b1c7e
BW
1051 }
1052
cd05bf23 1053 rect.x = offset;
4444d148 1054
01372b8f
BW
1055 m_art->DrawTab(&dc,
1056 wnd,
1057 rect,
1058 page.caption,
1059 page.active,
1060 tab_button.cur_state,
1061 &page.rect,
1062 &tab_button.rect,
1063 &x_extent);
4444d148 1064
cd05bf23
BW
1065 if (page.active)
1066 {
1067 active = i;
1068 active_offset = offset;
1069 }
41b76acd 1070
cd05bf23
BW
1071 offset += x_extent;
1072 }
4444d148 1073
cd05bf23 1074 // draw the active tab again so it stands in the foreground
4953f8cf 1075 if (active >= m_tab_offset && active < m_pages.GetCount())
cd05bf23
BW
1076 {
1077 wxAuiNotebookPage& page = m_pages.Item(active);
1078
41b76acd
BW
1079 wxAuiTabContainerButton& tab_button = m_tab_close_buttons.Item(active);
1080
702b1c7e
BW
1081 // determine if a close button is on this tab
1082 bool close_button = false;
1083 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
1084 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
1085 {
1086 close_button = true;
1087 }
1088
cd05bf23 1089 rect.x = active_offset;
3f69756e 1090 m_art->DrawTab(&dc,
01372b8f
BW
1091 wnd,
1092 rect,
1093 page.caption,
1094 page.active,
1095 tab_button.cur_state,
1096 &page.rect,
1097 &tab_button.rect,
1098 &x_extent);
cd05bf23 1099 }
4444d148 1100
4953f8cf
BW
1101 dc.DestroyClippingRegion();
1102
1103 raw_dc->Blit(m_rect.x, m_rect.y,
1104 m_rect.GetWidth(), m_rect.GetHeight(),
1105 &dc, 0, 0);
cd05bf23
BW
1106}
1107
1108
1109// TabHitTest() tests if a tab was hit, passing the window pointer
1110// back if that condition was fulfilled. The function returns
1111// true if a tab was hit, otherwise false
1112bool wxAuiTabContainer::TabHitTest(int x, int y, wxWindow** hit) const
1113{
22a35096 1114 if (!m_rect.Contains(x,y))
cd05bf23 1115 return false;
4953f8cf 1116
41b76acd
BW
1117 wxAuiTabContainerButton* btn = NULL;
1118 if (ButtonHitTest(x, y, &btn))
1119 {
1120 if (m_buttons.Index(*btn) != wxNOT_FOUND)
1121 return false;
1122 }
4444d148 1123
cd05bf23 1124 size_t i, page_count = m_pages.GetCount();
4444d148 1125
4953f8cf 1126 for (i = m_tab_offset; i < page_count; ++i)
cd05bf23
BW
1127 {
1128 wxAuiNotebookPage& page = m_pages.Item(i);
22a35096 1129 if (page.rect.Contains(x,y))
cd05bf23 1130 {
4953f8cf
BW
1131 if (hit)
1132 *hit = page.window;
cd05bf23
BW
1133 return true;
1134 }
1135 }
4444d148 1136
cd05bf23
BW
1137 return false;
1138}
1139
1140// ButtonHitTest() tests if a button was hit. The function returns
1141// true if a button was hit, otherwise false
1142bool wxAuiTabContainer::ButtonHitTest(int x, int y,
1143 wxAuiTabContainerButton** hit) const
1144{
22a35096 1145 if (!m_rect.Contains(x,y))
cd05bf23 1146 return false;
4444d148 1147
41b76acd
BW
1148 size_t i, button_count;
1149
1150
1151 button_count = m_buttons.GetCount();
cd05bf23
BW
1152 for (i = 0; i < button_count; ++i)
1153 {
1154 wxAuiTabContainerButton& button = m_buttons.Item(i);
22a35096 1155 if (button.rect.Contains(x,y))
cd05bf23 1156 {
4953f8cf
BW
1157 if (hit)
1158 *hit = &button;
cd05bf23
BW
1159 return true;
1160 }
1161 }
41b76acd
BW
1162
1163 button_count = m_tab_close_buttons.GetCount();
1164 for (i = 0; i < button_count; ++i)
1165 {
1166 wxAuiTabContainerButton& button = m_tab_close_buttons.Item(i);
1167 if (button.rect.Contains(x,y))
1168 {
1169 if (hit)
1170 *hit = &button;
1171 return true;
1172 }
1173 }
1174
cd05bf23
BW
1175 return false;
1176}
1177
1178
1179
1180// the utility function ShowWnd() is the same as show,
a3a5df9d 1181// except it handles wxAuiMDIChildFrame windows as well,
cd05bf23
BW
1182// as the Show() method on this class is "unplugged"
1183static void ShowWnd(wxWindow* wnd, bool show)
1184{
a3a5df9d 1185 if (wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
cd05bf23 1186 {
a3a5df9d 1187 wxAuiMDIChildFrame* cf = (wxAuiMDIChildFrame*)wnd;
cd05bf23
BW
1188 cf->DoShow(show);
1189 }
1190 else
1191 {
1192 wnd->Show(show);
1193 }
1194}
1195
1196
1197// DoShowHide() this function shows the active window, then
1198// hides all of the other windows (in that order)
1199void wxAuiTabContainer::DoShowHide()
1200{
1201 wxAuiNotebookPageArray& pages = GetPages();
1202 size_t i, page_count = pages.GetCount();
1203
1204 // show new active page first
1205 for (i = 0; i < page_count; ++i)
1206 {
1207 wxAuiNotebookPage& page = pages.Item(i);
1208 if (page.active)
1209 {
1210 ShowWnd(page.window, true);
1211 break;
1212 }
1213 }
1214
1215 // hide all other pages
1216 for (i = 0; i < page_count; ++i)
1217 {
1218 wxAuiNotebookPage& page = pages.Item(i);
1219 ShowWnd(page.window, page.active);
1220 }
1221}
1222
1223
1224
1225
1226
1227
1228// -- wxAuiTabCtrl class implementation --
1229
1230
cd05bf23
BW
1231
1232BEGIN_EVENT_TABLE(wxAuiTabCtrl, wxControl)
1233 EVT_PAINT(wxAuiTabCtrl::OnPaint)
1234 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground)
1235 EVT_SIZE(wxAuiTabCtrl::OnSize)
1236 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown)
1237 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp)
1238 EVT_MOTION(wxAuiTabCtrl::OnMotion)
1239 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow)
4953f8cf 1240 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton)
cd05bf23
BW
1241END_EVENT_TABLE()
1242
1243
1244wxAuiTabCtrl::wxAuiTabCtrl(wxWindow* parent,
1245 wxWindowID id,
1246 const wxPoint& pos,
1247 const wxSize& size,
4444d148 1248 long style) : wxControl(parent, id, pos, size, style)
cd05bf23
BW
1249{
1250 m_click_pt = wxDefaultPosition;
1251 m_is_dragging = false;
1252 m_hover_button = NULL;
cd05bf23
BW
1253}
1254
26da5e4f
BW
1255wxAuiTabCtrl::~wxAuiTabCtrl()
1256{
1257}
cd05bf23
BW
1258
1259void wxAuiTabCtrl::OnPaint(wxPaintEvent&)
1260{
1261 wxPaintDC dc(this);
4444d148 1262
cd05bf23 1263 dc.SetFont(GetFont());
4444d148 1264
cd05bf23 1265 if (GetPageCount() > 0)
01372b8f 1266 Render(&dc, this);
cd05bf23
BW
1267}
1268
1269void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
1270{
1271}
1272
1273void wxAuiTabCtrl::OnSize(wxSizeEvent& evt)
1274{
1275 wxSize s = evt.GetSize();
1276 wxRect r(0, 0, s.GetWidth(), s.GetHeight());
1277 SetRect(r);
1278}
1279
1280void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt)
1281{
1282 CaptureMouse();
1283 m_click_pt = wxDefaultPosition;
1284 m_is_dragging = false;
08c068a4 1285 m_click_tab = NULL;
4444d148 1286
cd05bf23
BW
1287 wxWindow* wnd;
1288 if (TabHitTest(evt.m_x, evt.m_y, &wnd))
1289 {
1290 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1291 e.SetSelection(GetIdxFromWindow(wnd));
1292 e.SetOldSelection(GetActivePage());
1293 e.SetEventObject(this);
1294 GetEventHandler()->ProcessEvent(e);
4444d148 1295
cd05bf23
BW
1296 m_click_pt.x = evt.m_x;
1297 m_click_pt.y = evt.m_y;
08c068a4 1298 m_click_tab = wnd;
cd05bf23 1299 }
4444d148 1300
cd05bf23
BW
1301 if (m_hover_button)
1302 {
1303 m_hover_button->cur_state = wxAUI_BUTTON_STATE_PRESSED;
1304 Refresh();
1305 Update();
1306 }
1307}
1308
1309void wxAuiTabCtrl::OnLeftUp(wxMouseEvent&)
1310{
1311 if (GetCapture() == this)
1312 ReleaseMouse();
4444d148 1313
cd05bf23
BW
1314 if (m_is_dragging)
1315 {
1316 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, m_windowId);
08c068a4
BW
1317 evt.SetSelection(GetIdxFromWindow(m_click_tab));
1318 evt.SetOldSelection(evt.GetSelection());
cd05bf23
BW
1319 evt.SetEventObject(this);
1320 GetEventHandler()->ProcessEvent(evt);
1321 return;
1322 }
4444d148 1323
cd05bf23
BW
1324 if (m_hover_button)
1325 {
1326 m_hover_button->cur_state = wxAUI_BUTTON_STATE_HOVER;
1327 Refresh();
1328 Update();
4444d148 1329
25d7497c
BW
1330 if (!(m_hover_button->cur_state & wxAUI_BUTTON_STATE_DISABLED))
1331 {
1332 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_windowId);
1333 evt.SetInt(m_hover_button->id);
1334 evt.SetEventObject(this);
1335 GetEventHandler()->ProcessEvent(evt);
1336 }
cd05bf23 1337 }
4444d148 1338
cd05bf23
BW
1339 m_click_pt = wxDefaultPosition;
1340 m_is_dragging = false;
08c068a4 1341 m_click_tab = NULL;
cd05bf23
BW
1342}
1343
1344void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt)
1345{
1346 wxPoint pos = evt.GetPosition();
1347
1348 // check if the mouse is hovering above a button
1349 wxAuiTabContainerButton* button;
1350 if (ButtonHitTest(pos.x, pos.y, &button))
1351 {
b6418695
BW
1352 if (m_hover_button && button != m_hover_button)
1353 {
1354 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
1355 m_hover_button = NULL;
1356 Refresh();
1357 Update();
1358 }
1359
cd05bf23
BW
1360 if (button->cur_state != wxAUI_BUTTON_STATE_HOVER)
1361 {
1362 button->cur_state = wxAUI_BUTTON_STATE_HOVER;
1363 Refresh();
1364 Update();
1365 m_hover_button = button;
1366 return;
1367 }
1368 }
1369 else
1370 {
1371 if (m_hover_button)
1372 {
1373 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
1374 m_hover_button = NULL;
1375 Refresh();
1376 Update();
1377 }
1378 }
4444d148
WS
1379
1380
cd05bf23
BW
1381 if (!evt.LeftIsDown() || m_click_pt == wxDefaultPosition)
1382 return;
4444d148 1383
cd05bf23
BW
1384 if (m_is_dragging)
1385 {
1386 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, m_windowId);
08c068a4
BW
1387 evt.SetSelection(GetIdxFromWindow(m_click_tab));
1388 evt.SetOldSelection(evt.GetSelection());
cd05bf23
BW
1389 evt.SetEventObject(this);
1390 GetEventHandler()->ProcessEvent(evt);
1391 return;
4444d148
WS
1392 }
1393
1394
cd05bf23
BW
1395 int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
1396 int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
1397
1398 if (abs(pos.x - m_click_pt.x) > drag_x_threshold ||
1399 abs(pos.y - m_click_pt.y) > drag_y_threshold)
1400 {
1401 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, m_windowId);
08c068a4
BW
1402 evt.SetSelection(GetIdxFromWindow(m_click_tab));
1403 evt.SetOldSelection(evt.GetSelection());
cd05bf23
BW
1404 evt.SetEventObject(this);
1405 GetEventHandler()->ProcessEvent(evt);
4444d148 1406
cd05bf23
BW
1407 m_is_dragging = true;
1408 }
1409}
1410
1411void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event))
1412{
1413 if (m_hover_button)
1414 {
1415 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
1416 m_hover_button = NULL;
1417 Refresh();
1418 Update();
1419 }
1420}
1421
4953f8cf
BW
1422void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent& event)
1423{
1424 int button = event.GetInt();
1425
1426 if (button == wxAUI_BUTTON_LEFT || button == wxAUI_BUTTON_RIGHT)
1427 {
1428 if (button == wxAUI_BUTTON_LEFT)
1429 {
1430 if (GetTabOffset() > 0)
1431 {
1432 SetTabOffset(GetTabOffset()-1);
1433 Refresh();
1434 Update();
1435 }
1436 }
1437 else
1438 {
1439 SetTabOffset(GetTabOffset()+1);
1440 Refresh();
1441 Update();
1442 }
01372b8f
BW
1443 }
1444 else if (button == wxAUI_BUTTON_WINDOWLIST)
1445 {
1446 wxArrayString as;
1447
1448 size_t i, page_count = m_pages.GetCount();
1449 for (i = 0; i < page_count; ++i)
1450 {
1451 wxAuiNotebookPage& page = m_pages.Item(i);
1452 as.Add(page.caption);
1453 }
1454
1455 int idx = GetArtProvider()->ShowWindowList(this, as, GetActivePage());
1456
1457 if (idx != -1)
1458 {
1459 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1460 e.SetSelection(idx);
1461 e.SetOldSelection(GetActivePage());
1462 e.SetEventObject(this);
1463 GetEventHandler()->ProcessEvent(e);
1464 }
4953f8cf
BW
1465 }
1466 else
1467 {
1468 event.Skip();
1469 }
1470}
cd05bf23
BW
1471
1472// wxTabFrame is an interesting case. It's important that all child pages
1473// of the multi-notebook control are all actually children of that control
1474// (and not grandchildren). wxTabFrame facilitates this. There is one
1475// instance of wxTabFrame for each tab control inside the multi-notebook.
1476// It's important to know that wxTabFrame is not a real window, but it merely
1477// used to capture the dimensions/positioning of the internal tab control and
1478// it's managed page windows
1479
1480class wxTabFrame : public wxWindow
1481{
1482public:
1483
1484 wxTabFrame()
1485 {
1486 m_tabs = NULL;
1487 m_rect = wxRect(0,0,200,200);
da5e85d9
BW
1488 m_tab_ctrl_height = 20;
1489 }
4444d148 1490
da5e85d9
BW
1491 void SetTabCtrlHeight(int h)
1492 {
1493 m_tab_ctrl_height = h;
cd05bf23 1494 }
4444d148 1495
cd05bf23
BW
1496 void DoSetSize(int x, int y,
1497 int width, int height,
1498 int WXUNUSED(sizeFlags = wxSIZE_AUTO))
1499 {
1500 m_rect = wxRect(x, y, width, height);
1501 DoSizing();
1502 }
4444d148 1503
cd05bf23
BW
1504 void DoGetClientSize(int* x, int* y) const
1505 {
1506 *x = m_rect.width;
1507 *y = m_rect.height;
1508 }
4f450f41
RD
1509
1510 bool Show( bool WXUNUSED(show = true) ) { return false; }
4444d148 1511
cd05bf23
BW
1512 void DoSizing()
1513 {
1514 if (!m_tabs)
1515 return;
4444d148 1516
da5e85d9 1517 int tab_height = wxMin(m_rect.height, m_tab_ctrl_height);
cd05bf23
BW
1518 m_tab_rect = wxRect(m_rect.x, m_rect.y, m_rect.width, tab_height);
1519 m_tabs->SetSize(m_rect.x, m_rect.y, m_rect.width, tab_height);
1520 m_tabs->SetRect(wxRect(0, 0, m_rect.width, tab_height));
1521 m_tabs->Refresh();
9d59bf68 1522 m_tabs->Update();
4444d148 1523
cd05bf23
BW
1524 wxAuiNotebookPageArray& pages = m_tabs->GetPages();
1525 size_t i, page_count = pages.GetCount();
4444d148 1526
cd05bf23
BW
1527 for (i = 0; i < page_count; ++i)
1528 {
1529 wxAuiNotebookPage& page = pages.Item(i);
01372b8f
BW
1530 page.window->SetSize(m_rect.x, m_rect.y+tab_height,
1531 m_rect.width, m_rect.height-tab_height);
4444d148 1532
a3a5df9d 1533 if (page.window->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
cd05bf23 1534 {
a3a5df9d 1535 wxAuiMDIChildFrame* wnd = (wxAuiMDIChildFrame*)page.window;
cd05bf23
BW
1536 wnd->ApplyMDIChildFrameRect();
1537 }
1538 }
1539 }
1540
134e83cb
BW
1541 void DoGetSize(int* x, int* y) const
1542 {
1543 if (x)
1544 *x = m_rect.GetWidth();
1545 if (y)
1546 *y = m_rect.GetHeight();
1547 }
4444d148 1548
134e83cb
BW
1549 void Update()
1550 {
1551 // does nothing
1552 }
4444d148 1553
cd05bf23
BW
1554public:
1555
1556 wxRect m_rect;
1557 wxRect m_tab_rect;
1558 wxAuiTabCtrl* m_tabs;
da5e85d9 1559 int m_tab_ctrl_height;
cd05bf23
BW
1560};
1561
1562
1563
1564
1565
a3a5df9d 1566// -- wxAuiNotebook class implementation --
cd05bf23 1567
a3a5df9d
BW
1568BEGIN_EVENT_TABLE(wxAuiNotebook, wxControl)
1569 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
1570 //EVT_SIZE(wxAuiNotebook::OnSize)
1571 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
1572 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus)
cd05bf23
BW
1573 EVT_COMMAND_RANGE(10000, 10100,
1574 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING,
a3a5df9d 1575 wxAuiNotebook::OnTabClicked)
cd05bf23
BW
1576 EVT_COMMAND_RANGE(10000, 10100,
1577 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG,
a3a5df9d 1578 wxAuiNotebook::OnTabBeginDrag)
cd05bf23
BW
1579 EVT_COMMAND_RANGE(10000, 10100,
1580 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG,
a3a5df9d 1581 wxAuiNotebook::OnTabEndDrag)
cd05bf23
BW
1582 EVT_COMMAND_RANGE(10000, 10100,
1583 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION,
a3a5df9d 1584 wxAuiNotebook::OnTabDragMotion)
cd05bf23
BW
1585 EVT_COMMAND_RANGE(10000, 10100,
1586 wxEVT_COMMAND_AUINOTEBOOK_BUTTON,
a3a5df9d 1587 wxAuiNotebook::OnTabButton)
cd05bf23
BW
1588END_EVENT_TABLE()
1589
a3a5df9d 1590wxAuiNotebook::wxAuiNotebook()
cd05bf23
BW
1591{
1592 m_curpage = -1;
1593 m_tab_id_counter = 10000;
1594 m_dummy_wnd = NULL;
da5e85d9 1595 m_tab_ctrl_height = 20;
cd05bf23
BW
1596}
1597
a3a5df9d 1598wxAuiNotebook::wxAuiNotebook(wxWindow *parent,
cd05bf23
BW
1599 wxWindowID id,
1600 const wxPoint& pos,
1601 const wxSize& size,
1602 long style) : wxControl(parent, id, pos, size, style)
1603{
702b1c7e 1604 InitNotebook(style);
cd05bf23
BW
1605}
1606
a3a5df9d 1607bool wxAuiNotebook::Create(wxWindow* parent,
cd05bf23
BW
1608 wxWindowID id,
1609 const wxPoint& pos,
1610 const wxSize& size,
1611 long style)
1612{
1613 if (!wxControl::Create(parent, id, pos, size, style))
1614 return false;
4444d148 1615
702b1c7e 1616 InitNotebook(style);
4444d148 1617
cd05bf23
BW
1618 return true;
1619}
1620
1621// InitNotebook() contains common initialization
1622// code called by all constructors
a3a5df9d 1623void wxAuiNotebook::InitNotebook(long style)
cd05bf23 1624{
da5e85d9
BW
1625 m_curpage = -1;
1626 m_tab_id_counter = 10000;
1627 m_dummy_wnd = NULL;
1628 m_tab_ctrl_height = 20;
702b1c7e
BW
1629 m_flags = (unsigned int)style;
1630
cd05bf23
BW
1631 m_normal_font = *wxNORMAL_FONT;
1632 m_selected_font = *wxNORMAL_FONT;
1633 m_selected_font.SetWeight(wxBOLD);
4444d148 1634
da5e85d9 1635 // choose a default for the tab height
a4c8fc23 1636 m_tab_ctrl_height = m_tabs.GetArtProvider()->GetBestTabCtrlSize(this);
4444d148
WS
1637
1638 m_dummy_wnd = new wxWindow(this, wxID_ANY, wxPoint(0,0), wxSize(0,0));
cd05bf23
BW
1639 m_dummy_wnd->SetSize(200, 200);
1640 m_dummy_wnd->Show(false);
4444d148 1641
cd05bf23 1642 m_mgr.SetManagedWindow(this);
4444d148 1643
cd05bf23 1644 m_mgr.AddPane(m_dummy_wnd,
a3a5df9d 1645 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
4444d148 1646
cd05bf23
BW
1647 m_mgr.Update();
1648}
1649
a3a5df9d 1650wxAuiNotebook::~wxAuiNotebook()
cd05bf23
BW
1651{
1652 m_mgr.UnInit();
1653}
1654
a3a5df9d 1655void wxAuiNotebook::SetArtProvider(wxAuiTabArt* art)
3f69756e
BW
1656{
1657 m_tabs.SetArtProvider(art);
1658}
1659
a3a5df9d 1660wxAuiTabArt* wxAuiNotebook::GetArtProvider()
3f69756e
BW
1661{
1662 return m_tabs.GetArtProvider();
1663}
1664
0ce53f32
BW
1665void wxAuiNotebook::SetWindowStyleFlag(long style)
1666{
1667 wxControl::SetWindowStyleFlag(style);
1668
1669 m_flags = (unsigned int)style;
1670
1671 // if the control is already initialized
1672 if (m_mgr.GetManagedWindow() == (wxWindow*)this)
1673 {
1674 // let all of the tab children know about the new style
1675
1676 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1677 size_t i, pane_count = all_panes.GetCount();
1678 for (i = 0; i < pane_count; ++i)
1679 {
1680 wxAuiPaneInfo& pane = all_panes.Item(i);
1681 if (pane.name == wxT("dummy"))
1682 continue;
1683 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
1684 tabctrl->SetFlags(m_flags);
1685 tabctrl->Refresh();
1686 tabctrl->Update();
1687 }
1688 }
1689}
1690
1691
a3a5df9d 1692bool wxAuiNotebook::AddPage(wxWindow* page,
cd05bf23
BW
1693 const wxString& caption,
1694 bool select,
1695 const wxBitmap& bitmap)
1696{
1697 return InsertPage(GetPageCount(), page, caption, select, bitmap);
1698}
4444d148 1699
a3a5df9d 1700bool wxAuiNotebook::InsertPage(size_t page_idx,
cd05bf23
BW
1701 wxWindow* page,
1702 const wxString& caption,
1703 bool select,
1704 const wxBitmap& bitmap)
1705{
1706 wxAuiNotebookPage info;
1707 info.window = page;
1708 info.caption = caption;
1709 info.bitmap = bitmap;
1710 info.active = false;
1711
1712 // if there are currently no tabs, the first added
1713 // tab must be active
1714 if (m_tabs.GetPageCount() == 0)
1715 info.active = true;
1716
1717 m_tabs.InsertPage(page, info, page_idx);
1718
1719 wxAuiTabCtrl* active_tabctrl = GetActiveTabCtrl();
1720 if (page_idx >= active_tabctrl->GetPageCount())
1721 active_tabctrl->AddPage(page, info);
1722 else
1723 active_tabctrl->InsertPage(page, info, page_idx);
4444d148 1724
cd05bf23
BW
1725 DoSizing();
1726 active_tabctrl->DoShowHide();
4444d148 1727
cd05bf23
BW
1728 if (select)
1729 {
1730 int idx = m_tabs.GetIdxFromWindow(page);
a3a5df9d 1731 wxASSERT_MSG(idx != -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
4444d148 1732
cd05bf23
BW
1733 SetSelection(idx);
1734 }
4444d148 1735
cd05bf23
BW
1736 return true;
1737}
1738
1739
1740// DeletePage() removes a tab from the multi-notebook,
1741// and destroys the window as well
a3a5df9d 1742bool wxAuiNotebook::DeletePage(size_t page_idx)
ae4558e0 1743{
4444d148 1744 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
ae4558e0 1745 wxWindow* new_active = NULL;
4444d148 1746
cd05bf23
BW
1747 // find out which onscreen tab ctrl owns this tab
1748 wxAuiTabCtrl* ctrl;
1749 int ctrl_idx;
1750 if (!FindTab(wnd, &ctrl, &ctrl_idx))
1751 return false;
4444d148 1752
cd05bf23
BW
1753 // find a new page and set it as active
1754 int new_idx = ctrl_idx+1;
1755 if (new_idx >= (int)ctrl->GetPageCount())
1756 new_idx = ctrl_idx-1;
4444d148 1757
cd05bf23
BW
1758 if (new_idx >= 0 && new_idx < (int)ctrl->GetPageCount())
1759 {
ae4558e0 1760 new_active = ctrl->GetWindowFromIdx(new_idx);
cd05bf23
BW
1761 }
1762 else
1763 {
1764 // set the active page to the first page that
1765 // isn't the one being deleted
cd05bf23
BW
1766 size_t i, page_count = m_tabs.GetPageCount();
1767 for (i = 0; i < page_count; ++i)
1768 {
1769 wxWindow* w = m_tabs.GetWindowFromIdx(i);
1770 if (wnd != w)
1771 {
ae4558e0 1772 new_active = m_tabs.GetWindowFromIdx(i);
cd05bf23
BW
1773 break;
1774 }
1775 }
cd05bf23 1776 }
4444d148 1777
cd05bf23
BW
1778 // remove the tab from main catalog
1779 if (!m_tabs.RemovePage(wnd))
1780 return false;
4444d148 1781
cd05bf23
BW
1782 // remove the tab from the onscreen tab ctrl
1783 ctrl->RemovePage(wnd);
4444d148 1784
cd05bf23 1785 // actually destroy the window now
a3a5df9d 1786 if (wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
cd05bf23
BW
1787 {
1788 // delete the child frame with pending delete, as is
1789 // customary with frame windows
1790 if (!wxPendingDelete.Member(wnd))
1791 wxPendingDelete.Append(wnd);
1792 }
1793 else
1794 {
1795 wnd->Destroy();
1796 }
4444d148 1797
cd05bf23 1798 RemoveEmptyTabFrames();
4444d148 1799
ae4558e0
BW
1800 // set new active pane
1801 if (new_active)
1802 {
1803 m_curpage = -1;
1804 SetSelection(m_tabs.GetIdxFromWindow(new_active));
1805 }
1806
cd05bf23
BW
1807 return true;
1808}
1809
1810
1811
1812// RemovePage() removes a tab from the multi-notebook,
1813// but does not destroy the window
a3a5df9d 1814bool wxAuiNotebook::RemovePage(size_t page_idx)
cd05bf23
BW
1815{
1816 // remove the tab from our own catalog
1817 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
1818 if (!m_tabs.RemovePage(wnd))
1819 return false;
4444d148 1820
cd05bf23
BW
1821 // remove the tab from the onscreen tab ctrl
1822 wxAuiTabCtrl* ctrl;
1823 int ctrl_idx;
1824 if (FindTab(wnd, &ctrl, &ctrl_idx))
1825 {
1826 ctrl->RemovePage(wnd);
1827 return true;
1828 }
4444d148 1829
cd05bf23
BW
1830 return false;
1831}
1832
1833// SetPageText() changes the tab caption of the specified page
a3a5df9d 1834bool wxAuiNotebook::SetPageText(size_t page_idx, const wxString& text)
4444d148 1835{
cd05bf23
BW
1836 if (page_idx >= m_tabs.GetPageCount())
1837 return false;
4444d148 1838
cd05bf23
BW
1839 // update our own tab catalog
1840 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
1841 page_info.caption = text;
4444d148 1842
cd05bf23
BW
1843 // update what's on screen
1844 wxAuiTabCtrl* ctrl;
1845 int ctrl_idx;
1846 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
1847 {
1848 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
1849 info.caption = text;
1850 ctrl->Refresh();
639a4f7b 1851 ctrl->Update();
cd05bf23 1852 }
4444d148 1853
cd05bf23
BW
1854 return true;
1855}
1856
1857// GetSelection() returns the index of the currently active page
a3a5df9d 1858int wxAuiNotebook::GetSelection() const
cd05bf23
BW
1859{
1860 return m_curpage;
1861}
1862
1863// SetSelection() sets the currently active page
a3a5df9d 1864size_t wxAuiNotebook::SetSelection(size_t new_page)
cd05bf23
BW
1865{
1866 wxWindow* wnd = m_tabs.GetWindowFromIdx(new_page);
1867 if (!wnd)
1868 return m_curpage;
4444d148 1869
cd05bf23
BW
1870 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1871 evt.SetSelection(new_page);
1872 evt.SetOldSelection(m_curpage);
1873 evt.SetEventObject(this);
1874 if (!GetEventHandler()->ProcessEvent(evt) || evt.IsAllowed())
1875 {
1876 // program allows the page change
1877 evt.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED);
1878 (void)GetEventHandler()->ProcessEvent(evt);
1879
1880
1881
1882 wxAuiTabCtrl* ctrl;
1883 int ctrl_idx;
1884 if (FindTab(wnd, &ctrl, &ctrl_idx))
4444d148 1885 {
cd05bf23 1886 m_tabs.SetActivePage(wnd);
4444d148 1887
cd05bf23
BW
1888 ctrl->SetActivePage(ctrl_idx);
1889 DoSizing();
1890 ctrl->DoShowHide();
4444d148 1891
cd05bf23
BW
1892 int old_curpage = m_curpage;
1893 m_curpage = new_page;
1894
1895
1896 // set fonts
a3a5df9d 1897 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
1898 size_t i, pane_count = all_panes.GetCount();
1899 for (i = 0; i < pane_count; ++i)
1900 {
a3a5df9d 1901 wxAuiPaneInfo& pane = all_panes.Item(i);
cd05bf23
BW
1902 if (pane.name == wxT("dummy"))
1903 continue;
1904 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
1905 if (tabctrl != ctrl)
1906 tabctrl->SetSelectedFont(m_normal_font);
1907 else
1908 tabctrl->SetSelectedFont(m_selected_font);
1909 tabctrl->Refresh();
1910 }
1911
1912 wnd->SetFocus();
4444d148 1913
cd05bf23
BW
1914 return old_curpage;
1915 }
1916 }
1917
1918 return m_curpage;
1919}
1920
1921// GetPageCount() returns the total number of
1922// pages managed by the multi-notebook
a3a5df9d 1923size_t wxAuiNotebook::GetPageCount() const
cd05bf23
BW
1924{
1925 return m_tabs.GetPageCount();
1926}
1927
1928// GetPage() returns the wxWindow pointer of the
1929// specified page
a3a5df9d 1930wxWindow* wxAuiNotebook::GetPage(size_t page_idx) const
cd05bf23
BW
1931{
1932 wxASSERT(page_idx < m_tabs.GetPageCount());
4444d148 1933
cd05bf23
BW
1934 return m_tabs.GetWindowFromIdx(page_idx);
1935}
1936
1937// DoSizing() performs all sizing operations in each tab control
a3a5df9d 1938void wxAuiNotebook::DoSizing()
cd05bf23 1939{
a3a5df9d 1940 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
1941 size_t i, pane_count = all_panes.GetCount();
1942 for (i = 0; i < pane_count; ++i)
1943 {
1944 if (all_panes.Item(i).name == wxT("dummy"))
1945 continue;
1946
1947 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1948 tabframe->DoSizing();
1949 }
1950}
1951
1952// GetActiveTabCtrl() returns the active tab control. It is
1953// called to determine which control gets new windows being added
a3a5df9d 1954wxAuiTabCtrl* wxAuiNotebook::GetActiveTabCtrl()
cd05bf23
BW
1955{
1956 if (m_curpage >= 0 && m_curpage < (int)m_tabs.GetPageCount())
1957 {
1958 wxAuiTabCtrl* ctrl;
1959 int idx;
4444d148 1960
cd05bf23
BW
1961 // find the tab ctrl with the current page
1962 if (FindTab(m_tabs.GetPage(m_curpage).window,
1963 &ctrl, &idx))
4444d148 1964 {
cd05bf23
BW
1965 return ctrl;
1966 }
1967 }
4444d148 1968
cd05bf23 1969 // no current page, just find the first tab ctrl
a3a5df9d 1970 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
1971 size_t i, pane_count = all_panes.GetCount();
1972 for (i = 0; i < pane_count; ++i)
1973 {
1974 if (all_panes.Item(i).name == wxT("dummy"))
1975 continue;
4444d148 1976
cd05bf23
BW
1977 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1978 return tabframe->m_tabs;
1979 }
4444d148 1980
cd05bf23
BW
1981 // If there is no tabframe at all, create one
1982 wxTabFrame* tabframe = new wxTabFrame;
da5e85d9 1983 tabframe->SetTabCtrlHeight(m_tab_ctrl_height);
cd05bf23
BW
1984 tabframe->m_tabs = new wxAuiTabCtrl(this,
1985 m_tab_id_counter++,
1986 wxDefaultPosition,
1987 wxDefaultSize,
1988 wxNO_BORDER);
702b1c7e 1989 tabframe->m_tabs->SetFlags(m_flags);
cd05bf23 1990 m_mgr.AddPane(tabframe,
a3a5df9d 1991 wxAuiPaneInfo().Center().CaptionVisible(false));
4444d148 1992
cd05bf23 1993 m_mgr.Update();
4444d148 1994
cd05bf23
BW
1995 return tabframe->m_tabs;
1996}
1997
1998// FindTab() finds the tab control that currently contains the window as well
1999// as the index of the window in the tab control. It returns true if the
2000// window was found, otherwise false.
a3a5df9d 2001bool wxAuiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx)
cd05bf23 2002{
a3a5df9d 2003 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
2004 size_t i, pane_count = all_panes.GetCount();
2005 for (i = 0; i < pane_count; ++i)
2006 {
2007 if (all_panes.Item(i).name == wxT("dummy"))
2008 continue;
4444d148 2009
cd05bf23 2010 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
4444d148 2011
cd05bf23
BW
2012 int page_idx = tabframe->m_tabs->GetIdxFromWindow(page);
2013 if (page_idx != -1)
2014 {
2015 *ctrl = tabframe->m_tabs;
2016 *idx = page_idx;
2017 return true;
2018 }
2019 }
4444d148 2020
cd05bf23
BW
2021 return false;
2022}
2023
2024
a3a5df9d 2025void wxAuiNotebook::OnEraseBackground(wxEraseEvent&)
cd05bf23
BW
2026{
2027}
2028
a3a5df9d 2029void wxAuiNotebook::OnSize(wxSizeEvent&)
cd05bf23
BW
2030{
2031}
2032
a3a5df9d 2033void wxAuiNotebook::OnTabClicked(wxCommandEvent& command_evt)
cd05bf23
BW
2034{
2035 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
4444d148 2036
cd05bf23
BW
2037 wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject();
2038 wxASSERT(ctrl != NULL);
4444d148 2039
cd05bf23
BW
2040 wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection());
2041 wxASSERT(wnd != NULL);
4444d148 2042
cd05bf23
BW
2043 int idx = m_tabs.GetIdxFromWindow(wnd);
2044 wxASSERT(idx != -1);
4444d148 2045
cd05bf23
BW
2046 SetSelection(idx);
2047}
2048
a3a5df9d 2049void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent&)
cd05bf23 2050{
08c068a4 2051 m_last_drag_x = 0;
cd05bf23
BW
2052}
2053
a3a5df9d 2054void wxAuiNotebook::OnTabDragMotion(wxCommandEvent& evt)
cd05bf23
BW
2055{
2056 wxPoint screen_pt = ::wxGetMousePosition();
2057 wxPoint client_pt = ScreenToClient(screen_pt);
2058 wxPoint zero(0,0);
4444d148 2059
cd05bf23 2060 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4444d148 2061
08c068a4
BW
2062 wxAuiTabCtrl* dest_tabs = GetTabCtrlFromPoint(client_pt);
2063 if (dest_tabs == src_tabs)
cd05bf23 2064 {
3941df70
BW
2065 if (src_tabs)
2066 {
2067 src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
2068 }
2069
08c068a4 2070 // always hide the hint for inner-tabctrl drag
cd05bf23 2071 m_mgr.HideHint();
695c0088
BW
2072
2073 // if tab moving is not allowed, leave
2074 if (!(m_flags & wxAUI_NB_TAB_MOVE))
2075 {
2076 return;
2077 }
08c068a4
BW
2078
2079 wxPoint pt = dest_tabs->ScreenToClient(screen_pt);
2080 wxWindow* dest_location_tab;
2081
2082 // this is an inner-tab drag/reposition
2083 if (dest_tabs->TabHitTest(pt.x, pt.y, &dest_location_tab))
2084 {
2085 int src_idx = evt.GetSelection();
2086 int dest_idx = dest_tabs->GetIdxFromWindow(dest_location_tab);
2087
2088 // prevent jumpy drag
2089 if ((src_idx == dest_idx) || dest_idx == -1 ||
2090 (src_idx > dest_idx && m_last_drag_x <= pt.x) ||
2091 (src_idx < dest_idx && m_last_drag_x >= pt.x))
2092 {
2093 m_last_drag_x = pt.x;
2094 return;
2095 }
2096
2097
2098 wxWindow* src_tab = dest_tabs->GetWindowFromIdx(src_idx);
2099 dest_tabs->MovePage(src_tab, dest_idx);
2100 dest_tabs->SetActivePage((size_t)dest_idx);
2101 dest_tabs->DoShowHide();
2102 dest_tabs->Refresh();
2103 m_last_drag_x = pt.x;
2104
2105 }
2106
cd05bf23
BW
2107 return;
2108 }
4444d148 2109
695c0088
BW
2110
2111 // if tab moving is not allowed, leave
2112 if (!(m_flags & wxAUI_NB_TAB_SPLIT))
2113 {
2114 return;
2115 }
2116
3941df70
BW
2117
2118 if (src_tabs)
2119 {
2120 src_tabs->SetCursor(wxCursor(wxCURSOR_SIZING));
2121 }
2122
2123
08c068a4 2124 if (dest_tabs)
cd05bf23 2125 {
08c068a4 2126 wxRect hint_rect = dest_tabs->GetRect();
cd05bf23
BW
2127 ClientToScreen(&hint_rect.x, &hint_rect.y);
2128 m_mgr.ShowHint(hint_rect);
2129 }
2130 else
2131 {
2132 m_mgr.DrawHintRect(m_dummy_wnd, client_pt, zero);
2133 }
2134}
2135
2136
2137
a3a5df9d 2138void wxAuiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
cd05bf23
BW
2139{
2140 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
2141
2142 m_mgr.HideHint();
4444d148 2143
695c0088
BW
2144 // if tab moving is not allowed, leave
2145 if (!(m_flags & wxAUI_NB_TAB_SPLIT))
2146 {
2147 return;
2148 }
2149
3941df70
BW
2150 // set cursor back to an arrow
2151 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
2152 if (src_tabs)
2153 {
2154 src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
2155 }
2156
cd05bf23
BW
2157 // get the mouse position, which will be used to determine the drop point
2158 wxPoint mouse_screen_pt = ::wxGetMousePosition();
2159 wxPoint mouse_client_pt = ScreenToClient(mouse_screen_pt);
2160
2161
2162 // the src tab control is the control that fired this event
cd05bf23 2163 wxAuiTabCtrl* dest_tabs = NULL;
4444d148 2164
cd05bf23
BW
2165
2166 // If the pointer is in an existing tab frame, do a tab insert
2167 wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt);
2168 wxTabFrame* tab_frame = (wxTabFrame*)GetTabFrameFromTabCtrl(hit_wnd);
c69532f7 2169 int insert_idx = -1;
cd05bf23
BW
2170 if (tab_frame)
2171 {
2172 dest_tabs = tab_frame->m_tabs;
4444d148 2173
cd05bf23
BW
2174 if (dest_tabs == src_tabs)
2175 return;
c69532f7
BW
2176
2177
2178 wxPoint pt = dest_tabs->ScreenToClient(mouse_screen_pt);
2179 wxWindow* target = NULL;
2180 dest_tabs->TabHitTest(pt.x, pt.y, &target);
2181 if (target)
2182 {
2183 insert_idx = dest_tabs->GetIdxFromWindow(target);
2184 }
cd05bf23
BW
2185 }
2186 else
2187 {
2188 // If there is no tabframe at all, create one
2189 wxTabFrame* new_tabs = new wxTabFrame;
da5e85d9 2190 new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
cd05bf23
BW
2191 new_tabs->m_tabs = new wxAuiTabCtrl(this,
2192 m_tab_id_counter++,
2193 wxDefaultPosition,
2194 wxDefaultSize,
2195 wxNO_BORDER);
702b1c7e
BW
2196 new_tabs->m_tabs->SetFlags(m_flags);
2197
cd05bf23 2198 m_mgr.AddPane(new_tabs,
a3a5df9d 2199 wxAuiPaneInfo().Bottom().CaptionVisible(false),
cd05bf23
BW
2200 mouse_client_pt);
2201 m_mgr.Update();
2202 dest_tabs = new_tabs->m_tabs;
2203 }
4444d148
WS
2204
2205
2206
cd05bf23
BW
2207 // remove the page from the source tabs
2208 wxAuiNotebookPage page_info = src_tabs->GetPage(evt.GetSelection());
2209 page_info.active = false;
2210 src_tabs->RemovePage(page_info.window);
2211 if (src_tabs->GetPageCount() > 0)
2212 {
2213 src_tabs->SetActivePage((size_t)0);
2214 src_tabs->DoShowHide();
2215 src_tabs->Refresh();
2216 }
2217
4444d148
WS
2218
2219
cd05bf23 2220 // add the page to the destination tabs
c69532f7
BW
2221 if (insert_idx == -1)
2222 insert_idx = dest_tabs->GetPageCount();
2223 dest_tabs->InsertPage(page_info.window, page_info, insert_idx);
4444d148 2224
cd05bf23 2225 if (src_tabs->GetPageCount() == 0)
4444d148 2226 {
cd05bf23
BW
2227 RemoveEmptyTabFrames();
2228 }
4444d148 2229
cd05bf23
BW
2230 DoSizing();
2231 dest_tabs->DoShowHide();
2232 dest_tabs->Refresh();
2233
2234 SetSelection(m_tabs.GetIdxFromWindow(page_info.window));
2235}
2236
3941df70
BW
2237
2238
a3a5df9d 2239wxAuiTabCtrl* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint& pt)
cd05bf23
BW
2240{
2241 // if we've just removed the last tab from the source
2242 // tab set, the remove the tab control completely
a3a5df9d 2243 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
2244 size_t i, pane_count = all_panes.GetCount();
2245 for (i = 0; i < pane_count; ++i)
2246 {
2247 if (all_panes.Item(i).name == wxT("dummy"))
2248 continue;
4444d148 2249
cd05bf23 2250 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
22a35096 2251 if (tabframe->m_tab_rect.Contains(pt))
cd05bf23
BW
2252 return tabframe->m_tabs;
2253 }
4444d148 2254
cd05bf23
BW
2255 return NULL;
2256}
2257
a3a5df9d 2258wxWindow* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow* tab_ctrl)
cd05bf23
BW
2259{
2260 // if we've just removed the last tab from the source
2261 // tab set, the remove the tab control completely
a3a5df9d 2262 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
2263 size_t i, pane_count = all_panes.GetCount();
2264 for (i = 0; i < pane_count; ++i)
2265 {
2266 if (all_panes.Item(i).name == wxT("dummy"))
2267 continue;
4444d148 2268
cd05bf23
BW
2269 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
2270 if (tabframe->m_tabs == tab_ctrl)
2271 {
2272 return tabframe;
2273 }
2274 }
4444d148 2275
cd05bf23
BW
2276 return NULL;
2277}
2278
a3a5df9d 2279void wxAuiNotebook::RemoveEmptyTabFrames()
cd05bf23 2280{
cd05bf23
BW
2281 // if we've just removed the last tab from the source
2282 // tab set, the remove the tab control completely
a3a5df9d 2283 wxAuiPaneInfoArray all_panes = m_mgr.GetAllPanes();
cd05bf23
BW
2284 size_t i, pane_count = all_panes.GetCount();
2285 for (i = 0; i < pane_count; ++i)
2286 {
2287 if (all_panes.Item(i).name == wxT("dummy"))
2288 continue;
2289
2290 wxTabFrame* tab_frame = (wxTabFrame*)all_panes.Item(i).window;
2291 if (tab_frame->m_tabs->GetPageCount() == 0)
2292 {
2293 m_mgr.DetachPane(tab_frame);
4444d148 2294
cd05bf23
BW
2295 // use pending delete because sometimes during
2296 // window closing, refreshs are pending
2297 if (!wxPendingDelete.Member(tab_frame->m_tabs))
4444d148 2298 wxPendingDelete.Append(tab_frame->m_tabs);
cd05bf23 2299 //tab_frame->m_tabs->Destroy();
4444d148 2300
cd05bf23 2301 delete tab_frame;
cd05bf23
BW
2302 }
2303 }
4444d148
WS
2304
2305
cd05bf23
BW
2306 // check to see if there is still a center pane;
2307 // if there isn't, make a frame the center pane
a3a5df9d 2308 wxAuiPaneInfoArray panes = m_mgr.GetAllPanes();
cd05bf23
BW
2309 pane_count = panes.GetCount();
2310 wxWindow* first_good = NULL;
2311 bool center_found = false;
2312 for (i = 0; i < pane_count; ++i)
2313 {
2314 if (panes.Item(i).name == wxT("dummy"))
2315 continue;
2316 if (panes.Item(i).dock_direction == wxAUI_DOCK_CENTRE)
2317 center_found = true;
2318 if (!first_good)
2319 first_good = panes.Item(i).window;
2320 }
2321
2322 if (!center_found && first_good)
2323 {
2324 m_mgr.GetPane(first_good).Centre();
cd05bf23
BW
2325 }
2326
4444d148 2327 m_mgr.Update();
cd05bf23
BW
2328}
2329
a3a5df9d 2330void wxAuiNotebook::OnChildFocus(wxChildFocusEvent& evt)
cd05bf23
BW
2331{
2332 int idx = m_tabs.GetIdxFromWindow(evt.GetWindow());
2333 if (idx != -1 && idx != m_curpage)
2334 {
4444d148 2335 SetSelection(idx);
cd05bf23
BW
2336 }
2337}
2338
2339
a3a5df9d 2340void wxAuiNotebook::OnTabButton(wxCommandEvent& command_evt)
cd05bf23
BW
2341{
2342 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
2343 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4444d148 2344
cd05bf23 2345 int button_id = evt.GetInt();
4444d148 2346
4953f8cf 2347 if (button_id == wxAUI_BUTTON_CLOSE)
cd05bf23
BW
2348 {
2349 int selection = tabs->GetActivePage();
4444d148 2350
cd05bf23
BW
2351 if (selection != -1)
2352 {
2353 wxWindow* close_wnd = tabs->GetWindowFromIdx(selection);
4444d148 2354
a3a5df9d 2355 if (close_wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
cd05bf23
BW
2356 {
2357 close_wnd->Close();
2358 }
2359 else
2360 {
2361 int main_idx = m_tabs.GetIdxFromWindow(close_wnd);
2362 DeletePage(main_idx);
2363 }
2364 }
2365 }
2366}
2367
2368
2369
2370
2371#endif // wxUSE_AUI