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