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