]> git.saurik.com Git - wxWidgets.git/blame - src/aui/auibook.cpp
Override GetPixelSize on OS X as the base impl creates a wxScreenDC each time, which...
[wxWidgets.git] / src / aui / auibook.cpp
CommitLineData
cd05bf23 1///////////////////////////////////////////////////////////////////////////////
4444d148 2// Name: src/aui/auibook.cpp
cd05bf23
BW
3// Purpose: wxaui: wx advanced user interface - notebook
4// Author: Benjamin I. Williams
5// Modified by:
6// Created: 2006-06-28
7// Copyright: (C) Copyright 2006, Kirix Corporation, All Rights Reserved
8// Licence: wxWindows Library Licence, Version 3.1
9///////////////////////////////////////////////////////////////////////////////
10
11// ----------------------------------------------------------------------------
12// headers
13// ----------------------------------------------------------------------------
14
15#include "wx/wxprec.h"
16
17#ifdef __BORLANDC__
18 #pragma hdrstop
19#endif
20
21#if wxUSE_AUI
22
189da67c 23#include "wx/aui/auibook.h"
cd05bf23
BW
24
25#ifndef WX_PRECOMP
4444d148 26 #include "wx/settings.h"
03265113 27 #include "wx/image.h"
cd05bf23
BW
28#endif
29
4444d148
WS
30#include "wx/aui/tabmdi.h"
31#include "wx/dcbuffer.h"
32
cd05bf23
BW
33#include "wx/arrimpl.cpp"
34WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray)
35WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray)
36
37DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING)
38DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED)
39DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON)
40DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG)
41DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG)
42DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION)
43
44
45
46IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent, wxEvent)
47
48// -- wxAuiTabContainer class implementation --
49
50
51// wxAuiTabContainer is a class which contains information about each
52// tab. It also can render an entire tab control to a specified DC.
53// It's not a window class itself, because this code will be used by
54// the wxFrameMananger, where it is disadvantageous to have separate
55// windows for each tab control in the case of "docked tabs"
56
57// A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
58// which can be used as a tab control in the normal sense.
59
60
61// This functions are here for this proof of concept
62// and will be factored out later. See dockart.cpp
63static wxColor StepColour(const wxColor& c, int percent)
64{
65 int r = c.Red(), g = c.Green(), b = c.Blue();
66 return wxColour((unsigned char)wxMin((r*percent)/100,255),
67 (unsigned char)wxMin((g*percent)/100,255),
68 (unsigned char)wxMin((b*percent)/100,255));
69}
70
71// This functions are here for this proof of concept
72// and will be factored out later. See dockart.cpp
73static wxBitmap BitmapFromBits(const unsigned char bits[], int w, int h,
74 const wxColour& color)
75{
76 wxImage img = wxBitmap((const char*)bits, w, h).ConvertToImage();
df00bdf7
RR
77 img.Replace(0,0,0,123,123,123);
78 img.Replace(255,255,255,color.Red(),color.Green(),color.Blue());
cd05bf23
BW
79 img.SetMaskColour(123,123,123);
80 return wxBitmap(img);
81}
82
83static void DrawButton(wxDC& dc,
84 const wxRect& _rect,
85 const wxBitmap& bmp,
86 const wxColour& bkcolour,
87 int button_state)
88{
89 wxRect rect = _rect;
90
91 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
92 {
93 rect.x++;
94 rect.y++;
95 }
96
97 if (button_state == wxAUI_BUTTON_STATE_HOVER ||
98 button_state == wxAUI_BUTTON_STATE_PRESSED)
99 {
100 dc.SetBrush(wxBrush(StepColour(bkcolour, 120)));
101 dc.SetPen(wxPen(StepColour(bkcolour, 70)));
102
103 // draw the background behind the button
104 dc.DrawRectangle(rect.x, rect.y, 15, 15);
105 }
106
107 // draw the button itself
108 dc.DrawBitmap(bmp, rect.x, rect.y, true);
109}
110
111
112
113
114wxAuiTabContainer::wxAuiTabContainer()
115{
116 m_normal_font = *wxNORMAL_FONT;
117 m_selected_font = *wxNORMAL_FONT;
118 m_selected_font.SetWeight(wxBOLD);
119 m_measuring_font = m_selected_font;
4444d148 120
cd05bf23 121 wxColour base_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
4444d148 122
cd05bf23
BW
123 wxColour background_colour = StepColour(base_colour, 95);
124 wxColour normaltab_colour = base_colour;
125 wxColour selectedtab_colour = *wxWHITE;
4444d148 126
cd05bf23
BW
127 m_bkbrush = wxBrush(background_colour);
128 m_normal_bkbrush = wxBrush(normaltab_colour);
129 m_normal_bkpen = wxPen(normaltab_colour);
130 m_selected_bkbrush = wxBrush(selectedtab_colour);
131 m_selected_bkpen = wxPen(selectedtab_colour);
132}
133
fe498448
BW
134wxAuiTabContainer::~wxAuiTabContainer()
135{
136}
137
cd05bf23
BW
138void wxAuiTabContainer::SetNormalFont(const wxFont& font)
139{
140 m_normal_font = font;
141}
142
143void wxAuiTabContainer::SetSelectedFont(const wxFont& font)
144{
145 m_selected_font = font;
146}
147
148void wxAuiTabContainer::SetMeasuringFont(const wxFont& font)
149{
150 m_measuring_font = font;
151}
152
153void wxAuiTabContainer::SetRect(const wxRect& rect)
154{
155 m_rect = rect;
156}
157
158bool wxAuiTabContainer::AddPage(wxWindow* page,
159 const wxAuiNotebookPage& info)
160{
161 wxAuiNotebookPage page_info;
162 page_info = info;
163 page_info.window = page;
4444d148 164
cd05bf23
BW
165 m_pages.Add(page_info);
166
167 return true;
168}
169
170bool wxAuiTabContainer::InsertPage(wxWindow* page,
171 const wxAuiNotebookPage& info,
172 size_t idx)
173{
174 wxAuiNotebookPage page_info;
175 page_info = info;
176 page_info.window = page;
4444d148 177
cd05bf23
BW
178 if (idx >= m_pages.GetCount())
179 m_pages.Add(page_info);
180 else
181 m_pages.Insert(page_info, idx);
182
183 return true;
184}
185
186bool wxAuiTabContainer::RemovePage(wxWindow* wnd)
187{
188 size_t i, page_count = m_pages.GetCount();
189 for (i = 0; i < page_count; ++i)
190 {
191 wxAuiNotebookPage& page = m_pages.Item(i);
192 if (page.window == wnd)
193 {
194 m_pages.RemoveAt(i);
195 return true;
196 }
197 }
4444d148 198
cd05bf23
BW
199 return false;
200}
201
202bool wxAuiTabContainer::SetActivePage(wxWindow* wnd)
203{
204 bool found = false;
4444d148 205
cd05bf23
BW
206 size_t i, page_count = m_pages.GetCount();
207 for (i = 0; i < page_count; ++i)
208 {
209 wxAuiNotebookPage& page = m_pages.Item(i);
210 if (page.window == wnd)
211 {
212 page.active = true;
213 found = true;
214 }
215 else
216 {
217 page.active = false;
218 }
219 }
4444d148 220
cd05bf23
BW
221 return found;
222}
223
224void wxAuiTabContainer::SetNoneActive()
225{
226 size_t i, page_count = m_pages.GetCount();
227 for (i = 0; i < page_count; ++i)
228 {
229 wxAuiNotebookPage& page = m_pages.Item(i);
230 page.active = false;
231 }
232}
233
234bool wxAuiTabContainer::SetActivePage(size_t page)
235{
236 if (page >= m_pages.GetCount())
237 return false;
4444d148 238
cd05bf23
BW
239 return SetActivePage(m_pages.Item(page).window);
240}
4444d148 241
cd05bf23
BW
242int wxAuiTabContainer::GetActivePage() const
243{
244 size_t i, page_count = m_pages.GetCount();
245 for (i = 0; i < page_count; ++i)
246 {
247 wxAuiNotebookPage& page = m_pages.Item(i);
248 if (page.active)
249 return i;
250 }
4444d148 251
cd05bf23
BW
252 return -1;
253}
254
255wxWindow* wxAuiTabContainer::GetWindowFromIdx(size_t idx) const
256{
257 if (idx >= m_pages.GetCount())
258 return NULL;
4444d148 259
cd05bf23
BW
260 return m_pages[idx].window;
261}
262
263int wxAuiTabContainer::GetIdxFromWindow(wxWindow* wnd) const
264{
265 size_t i, page_count = m_pages.GetCount();
266 for (i = 0; i < page_count; ++i)
267 {
268 wxAuiNotebookPage& page = m_pages.Item(i);
269 if (page.window == wnd)
270 return i;
271 }
272 return -1;
273}
274
275wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx)
276{
277 wxASSERT_MSG(idx < m_pages.GetCount(), wxT("Invalid Page index"));
278
279 return m_pages[idx];
280}
281
282wxAuiNotebookPageArray& wxAuiTabContainer::GetPages()
283{
284 return m_pages;
285}
286
287size_t wxAuiTabContainer::GetPageCount() const
288{
289 return m_pages.GetCount();
290}
291
292void wxAuiTabContainer::AddButton(int id, const wxBitmap& bmp)
293{
294 wxAuiTabContainerButton button;
295 button.id = id;
296 button.bitmap = bmp;
297 button.cur_state = wxAUI_BUTTON_STATE_NORMAL;
4444d148 298
cd05bf23
BW
299 m_buttons.Add(button);
300}
301
302
303
304// DrawTab() draws an individual tab.
305// As it is virtual it may be overridden.
306//
307// dc - output dc
308// in_rect - rectangle the tab should be confined to
309// caption - tab's caption
310// active - whether or not the tab is active
311// out_rect - actual output rectangle
312// x_extent - the advance x; where the next tab should start
313
314void wxAuiTabContainer::DrawTab(wxDC* dc,
315 const wxRect& in_rect,
f169e95d 316 const wxString& caption_text,
cd05bf23
BW
317 bool active,
318 wxRect* out_rect,
319 int* x_extent)
320{
321 wxCoord normal_textx, normal_texty;
322 wxCoord selected_textx, selected_texty;
323 wxCoord measured_textx, measured_texty;
324 wxCoord textx, texty;
4444d148
WS
325
326
9d59bf68 327 // if the caption is empty, measure some temporary text
f169e95d 328 wxString caption = caption_text;
17da5410 329 if (caption_text.empty())
9d59bf68
BW
330 caption = wxT("Xj");
331
cd05bf23
BW
332 // measure text
333 dc->SetFont(m_measuring_font);
334 dc->GetTextExtent(caption, &measured_textx, &measured_texty);
4444d148 335
cd05bf23
BW
336 dc->SetFont(m_selected_font);
337 dc->GetTextExtent(caption, &selected_textx, &selected_texty);
4444d148 338
cd05bf23
BW
339 dc->SetFont(m_normal_font);
340 dc->GetTextExtent(caption, &normal_textx, &normal_texty);
341
f169e95d 342 caption = caption_text;
4444d148 343
cd05bf23
BW
344 wxCoord tab_height = measured_texty + 4;
345 wxCoord tab_width = measured_textx + tab_height + 5;
346 wxCoord tab_x = in_rect.x;
347 wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
4444d148
WS
348
349
cd05bf23 350 // select pen, brush and font for the tab to be drawn
4444d148 351
cd05bf23
BW
352 if (active)
353 {
354 dc->SetPen(m_selected_bkpen);
355 dc->SetBrush(m_selected_bkbrush);
356 dc->SetFont(m_selected_font);
357 textx = selected_textx;
358 texty = selected_texty;
359 }
360 else
361 {
362 dc->SetPen(m_normal_bkpen);
363 dc->SetBrush(m_normal_bkbrush);
364 dc->SetFont(m_normal_font);
365 textx = normal_textx;
366 texty = normal_texty;
367 }
4444d148
WS
368
369
cd05bf23 370 // -- draw line --
4444d148 371
cd05bf23
BW
372 wxPoint points[7];
373 points[0].x = tab_x;
374 points[0].y = tab_y + tab_height - 1;
375 points[1].x = tab_x + tab_height - 3;
376 points[1].y = tab_y + 2;
377 points[2].x = tab_x + tab_height + 3;
378 points[2].y = tab_y;
379 points[3].x = tab_x + tab_width - 2;
380 points[3].y = tab_y;
381 points[4].x = tab_x + tab_width;
382 points[4].y = tab_y + 2;
383 points[5].x = tab_x + tab_width;
384 points[5].y = tab_y + tab_height - 1;
385 points[6] = points[0];
386
387
388 dc->DrawPolygon(6, points);
4444d148 389
cd05bf23 390 dc->SetPen(*wxGREY_PEN);
4444d148 391
cd05bf23
BW
392 //dc->DrawLines(active ? 6 : 7, points);
393 dc->DrawLines(7, points);
4444d148 394
cd05bf23 395 // -- draw text --
4444d148
WS
396
397 dc->DrawText(caption,
398 tab_x + (tab_height/3) + (tab_width/2) - (textx/2),
cd05bf23 399 tab_y + tab_height - texty - 2);
4444d148 400
cd05bf23
BW
401 *out_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
402 *x_extent = tab_width - (tab_height/2) - 1;
403}
404
405
406// Render() renders the tab catalog to the specified DC
407// It is a virtual function and can be overridden to
408// provide custom drawing capabilities
409void wxAuiTabContainer::Render(wxDC* raw_dc)
4444d148 410{
cd05bf23
BW
411 wxMemoryDC dc;
412 wxBitmap bmp;
413 bmp.Create(m_rect.GetWidth(), m_rect.GetHeight());
414 dc.SelectObject(bmp);
4444d148 415
cd05bf23
BW
416 // draw background
417 dc.SetBrush(m_bkbrush);
418 dc.SetPen(*wxTRANSPARENT_PEN);
419 dc.DrawRectangle(-1, -1, m_rect.GetWidth()+2, m_rect.GetHeight()+2);
4444d148 420
cd05bf23
BW
421 // draw base line
422 dc.SetPen(*wxGREY_PEN);
423 dc.DrawLine(0, m_rect.GetHeight()-1, m_rect.GetWidth(), m_rect.GetHeight()-1);
4444d148
WS
424
425
cd05bf23
BW
426 size_t i, page_count = m_pages.GetCount();
427 int offset = 0;
428
429 size_t active = 999;
430 int active_offset = 0;
4444d148 431
cd05bf23
BW
432 int x_extent = 0;
433 wxRect rect = m_rect;
434 rect.y = 0;
435 rect.width = 1000;
436 rect.height = m_rect.height;
4444d148 437
cd05bf23
BW
438 for (i = 0; i < page_count; ++i)
439 {
440 wxAuiNotebookPage& page = m_pages.Item(i);
4444d148 441
cd05bf23 442 rect.x = offset;
4444d148 443
cd05bf23
BW
444 DrawTab(&dc,
445 rect,
446 page.caption,
447 page.active,
448 &page.rect,
449 &x_extent);
4444d148 450
cd05bf23
BW
451 if (page.active)
452 {
453 active = i;
454 active_offset = offset;
455 }
4444d148 456
cd05bf23
BW
457 offset += x_extent;
458 }
4444d148 459
cd05bf23
BW
460 // draw the active tab again so it stands in the foreground
461 if (active < m_pages.GetCount())
462 {
463 wxAuiNotebookPage& page = m_pages.Item(active);
464
465 rect.x = active_offset;
466 DrawTab(&dc,
467 rect,
468 page.caption,
469 page.active,
470 &page.rect,
471 &x_extent);
472 }
4444d148 473
cd05bf23
BW
474 // draw the buttons
475 offset = m_rect.x + m_rect.width;
476 size_t button_count = m_buttons.GetCount();
477 for (i = 0; i < button_count; ++i)
478 {
479 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
4444d148 480
cd05bf23
BW
481 wxRect button_rect(offset - button.bitmap.GetWidth(), 1,
482 button.bitmap.GetWidth(), button.bitmap.GetHeight());
4444d148 483
cd05bf23 484 button.rect = button_rect;
4444d148 485
cd05bf23
BW
486 DrawButton(dc, button.rect, button.bitmap,
487 m_bkbrush.GetColour(),
488 button.cur_state);
4444d148 489
cd05bf23
BW
490 offset -= button.bitmap.GetWidth();
491 }
4444d148
WS
492
493
cd05bf23
BW
494 raw_dc->Blit(m_rect.x, m_rect.y, m_rect.GetWidth(), m_rect.GetHeight(), &dc, 0, 0);
495}
496
497
498// TabHitTest() tests if a tab was hit, passing the window pointer
499// back if that condition was fulfilled. The function returns
500// true if a tab was hit, otherwise false
501bool wxAuiTabContainer::TabHitTest(int x, int y, wxWindow** hit) const
502{
22a35096 503 if (!m_rect.Contains(x,y))
cd05bf23 504 return false;
4444d148 505
cd05bf23 506 size_t i, page_count = m_pages.GetCount();
4444d148 507
cd05bf23
BW
508 for (i = 0; i < page_count; ++i)
509 {
510 wxAuiNotebookPage& page = m_pages.Item(i);
22a35096 511 if (page.rect.Contains(x,y))
cd05bf23
BW
512 {
513 *hit = page.window;
514 return true;
515 }
516 }
4444d148 517
cd05bf23
BW
518 return false;
519}
520
521// ButtonHitTest() tests if a button was hit. The function returns
522// true if a button was hit, otherwise false
523bool wxAuiTabContainer::ButtonHitTest(int x, int y,
524 wxAuiTabContainerButton** hit) const
525{
22a35096 526 if (!m_rect.Contains(x,y))
cd05bf23 527 return false;
4444d148 528
cd05bf23 529 size_t i, button_count = m_buttons.GetCount();
4444d148 530
cd05bf23
BW
531 for (i = 0; i < button_count; ++i)
532 {
533 wxAuiTabContainerButton& button = m_buttons.Item(i);
22a35096 534 if (button.rect.Contains(x,y))
cd05bf23
BW
535 {
536 *hit = &button;
537 return true;
538 }
539 }
4444d148 540
cd05bf23
BW
541 return false;
542}
543
544
545
546// the utility function ShowWnd() is the same as show,
547// except it handles wxTabMDIChildFrame windows as well,
548// as the Show() method on this class is "unplugged"
549static void ShowWnd(wxWindow* wnd, bool show)
550{
551 if (wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
552 {
553 wxTabMDIChildFrame* cf = (wxTabMDIChildFrame*)wnd;
554 cf->DoShow(show);
555 }
556 else
557 {
558 wnd->Show(show);
559 }
560}
561
562
563// DoShowHide() this function shows the active window, then
564// hides all of the other windows (in that order)
565void wxAuiTabContainer::DoShowHide()
566{
567 wxAuiNotebookPageArray& pages = GetPages();
568 size_t i, page_count = pages.GetCount();
569
570 // show new active page first
571 for (i = 0; i < page_count; ++i)
572 {
573 wxAuiNotebookPage& page = pages.Item(i);
574 if (page.active)
575 {
576 ShowWnd(page.window, true);
577 break;
578 }
579 }
580
581 // hide all other pages
582 for (i = 0; i < page_count; ++i)
583 {
584 wxAuiNotebookPage& page = pages.Item(i);
585 ShowWnd(page.window, page.active);
586 }
587}
588
589
590
591
592
593
594// -- wxAuiTabCtrl class implementation --
595
596
597const int wxAuiButtonClose = 101;
598
599BEGIN_EVENT_TABLE(wxAuiTabCtrl, wxControl)
600 EVT_PAINT(wxAuiTabCtrl::OnPaint)
601 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground)
602 EVT_SIZE(wxAuiTabCtrl::OnSize)
603 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown)
604 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp)
605 EVT_MOTION(wxAuiTabCtrl::OnMotion)
606 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow)
607END_EVENT_TABLE()
608
609
610wxAuiTabCtrl::wxAuiTabCtrl(wxWindow* parent,
611 wxWindowID id,
612 const wxPoint& pos,
613 const wxSize& size,
4444d148 614 long style) : wxControl(parent, id, pos, size, style)
cd05bf23
BW
615{
616 m_click_pt = wxDefaultPosition;
617 m_is_dragging = false;
618 m_hover_button = NULL;
4444d148
WS
619
620 // FIXME: copied from dockart-- needs to put in a common place
df00bdf7
RR
621#if defined( __WXMAC__ )
622 static unsigned char close_bits[]={
623 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
624 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
625 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
626#elif defined( __WXGTK__)
627 static unsigned char close_bits[]={
628 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
629 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
630 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
631#else
cd05bf23
BW
632 static unsigned char close_bits[]={
633 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
634 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
635 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
df00bdf7 636#endif
4444d148 637
cd05bf23
BW
638 AddButton(101, BitmapFromBits(close_bits, 16, 16, *wxBLACK));
639}
640
641
642void wxAuiTabCtrl::OnPaint(wxPaintEvent&)
643{
644 wxPaintDC dc(this);
4444d148 645
cd05bf23 646 dc.SetFont(GetFont());
4444d148 647
cd05bf23
BW
648 if (GetPageCount() > 0)
649 Render(&dc);
650}
651
652void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
653{
654}
655
656void wxAuiTabCtrl::OnSize(wxSizeEvent& evt)
657{
658 wxSize s = evt.GetSize();
659 wxRect r(0, 0, s.GetWidth(), s.GetHeight());
660 SetRect(r);
661}
662
663void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt)
664{
665 CaptureMouse();
666 m_click_pt = wxDefaultPosition;
667 m_is_dragging = false;
668 m_click_tab = -1;
4444d148 669
cd05bf23
BW
670 wxWindow* wnd;
671 if (TabHitTest(evt.m_x, evt.m_y, &wnd))
672 {
673 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
674 e.SetSelection(GetIdxFromWindow(wnd));
675 e.SetOldSelection(GetActivePage());
676 e.SetEventObject(this);
677 GetEventHandler()->ProcessEvent(e);
4444d148 678
cd05bf23
BW
679 m_click_pt.x = evt.m_x;
680 m_click_pt.y = evt.m_y;
681 m_click_tab = e.GetSelection();
682 }
4444d148 683
cd05bf23
BW
684 if (m_hover_button)
685 {
686 m_hover_button->cur_state = wxAUI_BUTTON_STATE_PRESSED;
687 Refresh();
688 Update();
689 }
690}
691
692void wxAuiTabCtrl::OnLeftUp(wxMouseEvent&)
693{
694 if (GetCapture() == this)
695 ReleaseMouse();
4444d148 696
cd05bf23
BW
697 if (m_is_dragging)
698 {
699 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, m_windowId);
700 evt.SetSelection(m_click_tab);
701 evt.SetOldSelection(m_click_tab);
702 evt.SetEventObject(this);
703 GetEventHandler()->ProcessEvent(evt);
704 return;
705 }
4444d148 706
cd05bf23
BW
707 if (m_hover_button)
708 {
709 m_hover_button->cur_state = wxAUI_BUTTON_STATE_HOVER;
710 Refresh();
711 Update();
4444d148 712
cd05bf23
BW
713 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_windowId);
714 evt.SetInt(m_hover_button->id);
715 evt.SetEventObject(this);
716 GetEventHandler()->ProcessEvent(evt);
717 }
4444d148 718
cd05bf23
BW
719 m_click_pt = wxDefaultPosition;
720 m_is_dragging = false;
721 m_click_tab = -1;
722}
723
724void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt)
725{
726 wxPoint pos = evt.GetPosition();
727
728 // check if the mouse is hovering above a button
729 wxAuiTabContainerButton* button;
730 if (ButtonHitTest(pos.x, pos.y, &button))
731 {
732 if (button->cur_state != wxAUI_BUTTON_STATE_HOVER)
733 {
734 button->cur_state = wxAUI_BUTTON_STATE_HOVER;
735 Refresh();
736 Update();
737 m_hover_button = button;
738 return;
739 }
740 }
741 else
742 {
743 if (m_hover_button)
744 {
745 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
746 m_hover_button = NULL;
747 Refresh();
748 Update();
749 }
750 }
4444d148
WS
751
752
cd05bf23
BW
753 if (!evt.LeftIsDown() || m_click_pt == wxDefaultPosition)
754 return;
4444d148 755
cd05bf23
BW
756 if (m_is_dragging)
757 {
758 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, m_windowId);
759 evt.SetSelection(m_click_tab);
760 evt.SetOldSelection(m_click_tab);
761 evt.SetEventObject(this);
762 GetEventHandler()->ProcessEvent(evt);
763 return;
4444d148
WS
764 }
765
766
cd05bf23
BW
767 int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
768 int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
769
770 if (abs(pos.x - m_click_pt.x) > drag_x_threshold ||
771 abs(pos.y - m_click_pt.y) > drag_y_threshold)
772 {
773 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, m_windowId);
774 evt.SetSelection(m_click_tab);
775 evt.SetOldSelection(m_click_tab);
776 evt.SetEventObject(this);
777 GetEventHandler()->ProcessEvent(evt);
4444d148 778
cd05bf23
BW
779 m_is_dragging = true;
780 }
781}
782
783void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event))
784{
785 if (m_hover_button)
786 {
787 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
788 m_hover_button = NULL;
789 Refresh();
790 Update();
791 }
792}
793
794
795// wxTabFrame is an interesting case. It's important that all child pages
796// of the multi-notebook control are all actually children of that control
797// (and not grandchildren). wxTabFrame facilitates this. There is one
798// instance of wxTabFrame for each tab control inside the multi-notebook.
799// It's important to know that wxTabFrame is not a real window, but it merely
800// used to capture the dimensions/positioning of the internal tab control and
801// it's managed page windows
802
803class wxTabFrame : public wxWindow
804{
805public:
806
807 wxTabFrame()
808 {
809 m_tabs = NULL;
810 m_rect = wxRect(0,0,200,200);
da5e85d9
BW
811 m_tab_ctrl_height = 20;
812 }
4444d148 813
da5e85d9
BW
814 void SetTabCtrlHeight(int h)
815 {
816 m_tab_ctrl_height = h;
cd05bf23 817 }
4444d148 818
cd05bf23
BW
819 void DoSetSize(int x, int y,
820 int width, int height,
821 int WXUNUSED(sizeFlags = wxSIZE_AUTO))
822 {
823 m_rect = wxRect(x, y, width, height);
824 DoSizing();
825 }
4444d148 826
cd05bf23
BW
827 void DoGetClientSize(int* x, int* y) const
828 {
829 *x = m_rect.width;
830 *y = m_rect.height;
831 }
4f450f41
RD
832
833 bool Show( bool WXUNUSED(show = true) ) { return false; }
4444d148 834
cd05bf23
BW
835 void DoSizing()
836 {
837 if (!m_tabs)
838 return;
4444d148 839
da5e85d9 840 int tab_height = wxMin(m_rect.height, m_tab_ctrl_height);
cd05bf23
BW
841 m_tab_rect = wxRect(m_rect.x, m_rect.y, m_rect.width, tab_height);
842 m_tabs->SetSize(m_rect.x, m_rect.y, m_rect.width, tab_height);
843 m_tabs->SetRect(wxRect(0, 0, m_rect.width, tab_height));
844 m_tabs->Refresh();
9d59bf68 845 m_tabs->Update();
4444d148 846
cd05bf23
BW
847 wxAuiNotebookPageArray& pages = m_tabs->GetPages();
848 size_t i, page_count = pages.GetCount();
4444d148 849
cd05bf23
BW
850 for (i = 0; i < page_count; ++i)
851 {
852 wxAuiNotebookPage& page = pages.Item(i);
853 page.window->SetSize(m_rect.x, m_rect.y+tab_height, m_rect.width, m_rect.height-tab_height);
4444d148 854
cd05bf23
BW
855 if (page.window->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
856 {
857 wxTabMDIChildFrame* wnd = (wxTabMDIChildFrame*)page.window;
858 wnd->ApplyMDIChildFrameRect();
859 }
860 }
861 }
862
134e83cb
BW
863 void DoGetSize(int* x, int* y) const
864 {
865 if (x)
866 *x = m_rect.GetWidth();
867 if (y)
868 *y = m_rect.GetHeight();
869 }
4444d148 870
134e83cb
BW
871 void Update()
872 {
873 // does nothing
874 }
4444d148 875
cd05bf23
BW
876public:
877
878 wxRect m_rect;
879 wxRect m_tab_rect;
880 wxAuiTabCtrl* m_tabs;
da5e85d9 881 int m_tab_ctrl_height;
cd05bf23
BW
882};
883
884
885
886
887
888// -- wxAuiMultiNotebook class implementation --
889
890BEGIN_EVENT_TABLE(wxAuiMultiNotebook, wxControl)
891 //EVT_ERASE_BACKGROUND(wxAuiMultiNotebook::OnEraseBackground)
892 //EVT_SIZE(wxAuiMultiNotebook::OnSize)
893 //EVT_LEFT_DOWN(wxAuiMultiNotebook::OnLeftDown)
894 EVT_CHILD_FOCUS(wxAuiMultiNotebook::OnChildFocus)
895 EVT_COMMAND_RANGE(10000, 10100,
896 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING,
897 wxAuiMultiNotebook::OnTabClicked)
898 EVT_COMMAND_RANGE(10000, 10100,
899 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG,
4444d148 900 wxAuiMultiNotebook::OnTabBeginDrag)
cd05bf23
BW
901 EVT_COMMAND_RANGE(10000, 10100,
902 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG,
4444d148 903 wxAuiMultiNotebook::OnTabEndDrag)
cd05bf23
BW
904 EVT_COMMAND_RANGE(10000, 10100,
905 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION,
906 wxAuiMultiNotebook::OnTabDragMotion)
907 EVT_COMMAND_RANGE(10000, 10100,
908 wxEVT_COMMAND_AUINOTEBOOK_BUTTON,
909 wxAuiMultiNotebook::OnTabButton)
910END_EVENT_TABLE()
911
912wxAuiMultiNotebook::wxAuiMultiNotebook()
913{
914 m_curpage = -1;
915 m_tab_id_counter = 10000;
916 m_dummy_wnd = NULL;
da5e85d9 917 m_tab_ctrl_height = 20;
cd05bf23
BW
918}
919
920wxAuiMultiNotebook::wxAuiMultiNotebook(wxWindow *parent,
921 wxWindowID id,
922 const wxPoint& pos,
923 const wxSize& size,
924 long style) : wxControl(parent, id, pos, size, style)
925{
926 InitNotebook();
927}
928
929bool wxAuiMultiNotebook::Create(wxWindow* parent,
930 wxWindowID id,
931 const wxPoint& pos,
932 const wxSize& size,
933 long style)
934{
935 if (!wxControl::Create(parent, id, pos, size, style))
936 return false;
4444d148 937
cd05bf23 938 InitNotebook();
4444d148 939
cd05bf23
BW
940 return true;
941}
942
943// InitNotebook() contains common initialization
944// code called by all constructors
945void wxAuiMultiNotebook::InitNotebook()
946{
da5e85d9
BW
947 m_curpage = -1;
948 m_tab_id_counter = 10000;
949 m_dummy_wnd = NULL;
950 m_tab_ctrl_height = 20;
4444d148 951
cd05bf23
BW
952 m_normal_font = *wxNORMAL_FONT;
953 m_selected_font = *wxNORMAL_FONT;
954 m_selected_font.SetWeight(wxBOLD);
4444d148 955
da5e85d9
BW
956 // choose a default for the tab height
957 wxClientDC dc(this);
958 int tx, ty;
959 dc.SetFont(m_selected_font);
960 dc.GetTextExtent(wxT("ABCDEFGHhijklm"), &tx, &ty);
961 m_tab_ctrl_height = (ty*150)/100;
4444d148
WS
962
963 m_dummy_wnd = new wxWindow(this, wxID_ANY, wxPoint(0,0), wxSize(0,0));
cd05bf23
BW
964 m_dummy_wnd->SetSize(200, 200);
965 m_dummy_wnd->Show(false);
4444d148 966
cd05bf23 967 m_mgr.SetManagedWindow(this);
4444d148 968
cd05bf23
BW
969 m_mgr.AddPane(m_dummy_wnd,
970 wxPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
4444d148 971
cd05bf23
BW
972 m_mgr.Update();
973}
974
975wxAuiMultiNotebook::~wxAuiMultiNotebook()
976{
977 m_mgr.UnInit();
978}
979
980bool wxAuiMultiNotebook::AddPage(wxWindow* page,
981 const wxString& caption,
982 bool select,
983 const wxBitmap& bitmap)
984{
985 return InsertPage(GetPageCount(), page, caption, select, bitmap);
986}
4444d148 987
cd05bf23
BW
988bool wxAuiMultiNotebook::InsertPage(size_t page_idx,
989 wxWindow* page,
990 const wxString& caption,
991 bool select,
992 const wxBitmap& bitmap)
993{
994 wxAuiNotebookPage info;
995 info.window = page;
996 info.caption = caption;
997 info.bitmap = bitmap;
998 info.active = false;
999
1000 // if there are currently no tabs, the first added
1001 // tab must be active
1002 if (m_tabs.GetPageCount() == 0)
1003 info.active = true;
1004
1005 m_tabs.InsertPage(page, info, page_idx);
1006
1007 wxAuiTabCtrl* active_tabctrl = GetActiveTabCtrl();
1008 if (page_idx >= active_tabctrl->GetPageCount())
1009 active_tabctrl->AddPage(page, info);
1010 else
1011 active_tabctrl->InsertPage(page, info, page_idx);
4444d148 1012
cd05bf23
BW
1013 DoSizing();
1014 active_tabctrl->DoShowHide();
4444d148 1015
cd05bf23
BW
1016 if (select)
1017 {
1018 int idx = m_tabs.GetIdxFromWindow(page);
1019 wxASSERT_MSG(idx != -1, wxT("Invalid Page index returned on wxAuiMultiNotebook::InsertPage()"));
4444d148 1020
cd05bf23
BW
1021 SetSelection(idx);
1022 }
4444d148 1023
cd05bf23
BW
1024 return true;
1025}
1026
1027
1028// DeletePage() removes a tab from the multi-notebook,
1029// and destroys the window as well
1030bool wxAuiMultiNotebook::DeletePage(size_t page_idx)
1031{
4444d148
WS
1032 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
1033
1034
cd05bf23
BW
1035 // find out which onscreen tab ctrl owns this tab
1036 wxAuiTabCtrl* ctrl;
1037 int ctrl_idx;
1038 if (!FindTab(wnd, &ctrl, &ctrl_idx))
1039 return false;
4444d148 1040
cd05bf23
BW
1041 // find a new page and set it as active
1042 int new_idx = ctrl_idx+1;
1043 if (new_idx >= (int)ctrl->GetPageCount())
1044 new_idx = ctrl_idx-1;
4444d148 1045
cd05bf23
BW
1046 if (new_idx >= 0 && new_idx < (int)ctrl->GetPageCount())
1047 {
1048 wxWindow* new_wnd = ctrl->GetWindowFromIdx(new_idx);
1049 int main_idx = m_tabs.GetIdxFromWindow(new_wnd);
1050 wxASSERT(main_idx != -1);
1051 SetSelection(main_idx);
1052 }
1053 else
1054 {
1055 // set the active page to the first page that
1056 // isn't the one being deleted
1057 bool found = false;
1058 size_t i, page_count = m_tabs.GetPageCount();
1059 for (i = 0; i < page_count; ++i)
1060 {
1061 wxWindow* w = m_tabs.GetWindowFromIdx(i);
1062 if (wnd != w)
1063 {
1064 found = true;
1065 SetSelection(i);
1066 break;
1067 }
1068 }
4444d148 1069
cd05bf23
BW
1070 if (!found)
1071 m_curpage = -1;
1072 }
4444d148
WS
1073
1074
cd05bf23
BW
1075 // remove the tab from main catalog
1076 if (!m_tabs.RemovePage(wnd))
1077 return false;
4444d148 1078
cd05bf23
BW
1079 // remove the tab from the onscreen tab ctrl
1080 ctrl->RemovePage(wnd);
4444d148 1081
cd05bf23
BW
1082 // actually destroy the window now
1083 if (wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
1084 {
1085 // delete the child frame with pending delete, as is
1086 // customary with frame windows
1087 if (!wxPendingDelete.Member(wnd))
1088 wxPendingDelete.Append(wnd);
1089 }
1090 else
1091 {
1092 wnd->Destroy();
1093 }
4444d148 1094
cd05bf23 1095 RemoveEmptyTabFrames();
4444d148 1096
cd05bf23
BW
1097 return true;
1098}
1099
1100
1101
1102// RemovePage() removes a tab from the multi-notebook,
1103// but does not destroy the window
1104bool wxAuiMultiNotebook::RemovePage(size_t page_idx)
1105{
1106 // remove the tab from our own catalog
1107 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
1108 if (!m_tabs.RemovePage(wnd))
1109 return false;
4444d148 1110
cd05bf23
BW
1111 // remove the tab from the onscreen tab ctrl
1112 wxAuiTabCtrl* ctrl;
1113 int ctrl_idx;
1114 if (FindTab(wnd, &ctrl, &ctrl_idx))
1115 {
1116 ctrl->RemovePage(wnd);
1117 return true;
1118 }
4444d148 1119
cd05bf23
BW
1120 return false;
1121}
1122
1123// SetPageText() changes the tab caption of the specified page
1124bool wxAuiMultiNotebook::SetPageText(size_t page_idx, const wxString& text)
4444d148 1125{
cd05bf23
BW
1126 if (page_idx >= m_tabs.GetPageCount())
1127 return false;
4444d148 1128
cd05bf23
BW
1129 // update our own tab catalog
1130 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
1131 page_info.caption = text;
4444d148 1132
cd05bf23
BW
1133 // update what's on screen
1134 wxAuiTabCtrl* ctrl;
1135 int ctrl_idx;
1136 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
1137 {
1138 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
1139 info.caption = text;
1140 ctrl->Refresh();
639a4f7b 1141 ctrl->Update();
cd05bf23 1142 }
4444d148 1143
cd05bf23
BW
1144 return true;
1145}
1146
1147// GetSelection() returns the index of the currently active page
1148int wxAuiMultiNotebook::GetSelection() const
1149{
1150 return m_curpage;
1151}
1152
1153// SetSelection() sets the currently active page
1154size_t wxAuiMultiNotebook::SetSelection(size_t new_page)
1155{
1156 wxWindow* wnd = m_tabs.GetWindowFromIdx(new_page);
1157 if (!wnd)
1158 return m_curpage;
4444d148 1159
cd05bf23
BW
1160 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1161 evt.SetSelection(new_page);
1162 evt.SetOldSelection(m_curpage);
1163 evt.SetEventObject(this);
1164 if (!GetEventHandler()->ProcessEvent(evt) || evt.IsAllowed())
1165 {
1166 // program allows the page change
1167 evt.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED);
1168 (void)GetEventHandler()->ProcessEvent(evt);
1169
1170
1171
1172 wxAuiTabCtrl* ctrl;
1173 int ctrl_idx;
1174 if (FindTab(wnd, &ctrl, &ctrl_idx))
4444d148 1175 {
cd05bf23 1176 m_tabs.SetActivePage(wnd);
4444d148 1177
cd05bf23
BW
1178 ctrl->SetActivePage(ctrl_idx);
1179 DoSizing();
1180 ctrl->DoShowHide();
4444d148 1181
cd05bf23
BW
1182 int old_curpage = m_curpage;
1183 m_curpage = new_page;
1184
1185
1186 // set fonts
1187 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1188 size_t i, pane_count = all_panes.GetCount();
1189 for (i = 0; i < pane_count; ++i)
1190 {
1191 wxPaneInfo& pane = all_panes.Item(i);
1192 if (pane.name == wxT("dummy"))
1193 continue;
1194 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
1195 if (tabctrl != ctrl)
1196 tabctrl->SetSelectedFont(m_normal_font);
1197 else
1198 tabctrl->SetSelectedFont(m_selected_font);
1199 tabctrl->Refresh();
1200 }
1201
1202 wnd->SetFocus();
4444d148 1203
cd05bf23
BW
1204 return old_curpage;
1205 }
1206 }
1207
1208 return m_curpage;
1209}
1210
1211// GetPageCount() returns the total number of
1212// pages managed by the multi-notebook
1213size_t wxAuiMultiNotebook::GetPageCount() const
1214{
1215 return m_tabs.GetPageCount();
1216}
1217
1218// GetPage() returns the wxWindow pointer of the
1219// specified page
1220wxWindow* wxAuiMultiNotebook::GetPage(size_t page_idx) const
1221{
1222 wxASSERT(page_idx < m_tabs.GetPageCount());
4444d148 1223
cd05bf23
BW
1224 return m_tabs.GetWindowFromIdx(page_idx);
1225}
1226
1227// DoSizing() performs all sizing operations in each tab control
1228void wxAuiMultiNotebook::DoSizing()
1229{
1230 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1231 size_t i, pane_count = all_panes.GetCount();
1232 for (i = 0; i < pane_count; ++i)
1233 {
1234 if (all_panes.Item(i).name == wxT("dummy"))
1235 continue;
1236
1237 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1238 tabframe->DoSizing();
1239 }
1240}
1241
1242// GetActiveTabCtrl() returns the active tab control. It is
1243// called to determine which control gets new windows being added
1244wxAuiTabCtrl* wxAuiMultiNotebook::GetActiveTabCtrl()
1245{
1246 if (m_curpage >= 0 && m_curpage < (int)m_tabs.GetPageCount())
1247 {
1248 wxAuiTabCtrl* ctrl;
1249 int idx;
4444d148 1250
cd05bf23
BW
1251 // find the tab ctrl with the current page
1252 if (FindTab(m_tabs.GetPage(m_curpage).window,
1253 &ctrl, &idx))
4444d148 1254 {
cd05bf23
BW
1255 return ctrl;
1256 }
1257 }
4444d148 1258
cd05bf23
BW
1259 // no current page, just find the first tab ctrl
1260 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1261 size_t i, pane_count = all_panes.GetCount();
1262 for (i = 0; i < pane_count; ++i)
1263 {
1264 if (all_panes.Item(i).name == wxT("dummy"))
1265 continue;
4444d148 1266
cd05bf23
BW
1267 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1268 return tabframe->m_tabs;
1269 }
4444d148 1270
cd05bf23
BW
1271 // If there is no tabframe at all, create one
1272 wxTabFrame* tabframe = new wxTabFrame;
da5e85d9 1273 tabframe->SetTabCtrlHeight(m_tab_ctrl_height);
cd05bf23
BW
1274 tabframe->m_tabs = new wxAuiTabCtrl(this,
1275 m_tab_id_counter++,
1276 wxDefaultPosition,
1277 wxDefaultSize,
1278 wxNO_BORDER);
1279 m_mgr.AddPane(tabframe,
4444d148
WS
1280 wxPaneInfo().Center().CaptionVisible(false));
1281
cd05bf23 1282 m_mgr.Update();
4444d148 1283
cd05bf23
BW
1284 return tabframe->m_tabs;
1285}
1286
1287// FindTab() finds the tab control that currently contains the window as well
1288// as the index of the window in the tab control. It returns true if the
1289// window was found, otherwise false.
1290bool wxAuiMultiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx)
1291{
1292 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1293 size_t i, pane_count = all_panes.GetCount();
1294 for (i = 0; i < pane_count; ++i)
1295 {
1296 if (all_panes.Item(i).name == wxT("dummy"))
1297 continue;
4444d148 1298
cd05bf23 1299 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
4444d148 1300
cd05bf23
BW
1301 int page_idx = tabframe->m_tabs->GetIdxFromWindow(page);
1302 if (page_idx != -1)
1303 {
1304 *ctrl = tabframe->m_tabs;
1305 *idx = page_idx;
1306 return true;
1307 }
1308 }
4444d148 1309
cd05bf23
BW
1310 return false;
1311}
1312
1313
1314void wxAuiMultiNotebook::OnEraseBackground(wxEraseEvent&)
1315{
1316}
1317
1318void wxAuiMultiNotebook::OnSize(wxSizeEvent&)
1319{
1320}
1321
1322void wxAuiMultiNotebook::OnTabClicked(wxCommandEvent& command_evt)
1323{
1324 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
4444d148 1325
cd05bf23
BW
1326 wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject();
1327 wxASSERT(ctrl != NULL);
4444d148 1328
cd05bf23
BW
1329 wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection());
1330 wxASSERT(wnd != NULL);
4444d148 1331
cd05bf23
BW
1332 int idx = m_tabs.GetIdxFromWindow(wnd);
1333 wxASSERT(idx != -1);
4444d148 1334
cd05bf23
BW
1335 SetSelection(idx);
1336}
1337
1338void wxAuiMultiNotebook::OnTabBeginDrag(wxCommandEvent&)
1339{
1340}
1341
1342void wxAuiMultiNotebook::OnTabDragMotion(wxCommandEvent& evt)
1343{
1344 wxPoint screen_pt = ::wxGetMousePosition();
1345 wxPoint client_pt = ScreenToClient(screen_pt);
1346 wxPoint zero(0,0);
4444d148 1347
cd05bf23 1348 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4444d148 1349
cd05bf23
BW
1350 wxAuiTabCtrl* tab_ctrl = GetTabCtrlFromPoint(client_pt);
1351 if (tab_ctrl == src_tabs)
1352 {
1353 // inner-tabctrl dragging is not yet implemented
1354 m_mgr.HideHint();
1355 return;
1356 }
4444d148 1357
cd05bf23
BW
1358 if (tab_ctrl)
1359 {
1360 wxRect hint_rect = tab_ctrl->GetRect();
1361 ClientToScreen(&hint_rect.x, &hint_rect.y);
1362 m_mgr.ShowHint(hint_rect);
1363 }
1364 else
1365 {
1366 m_mgr.DrawHintRect(m_dummy_wnd, client_pt, zero);
1367 }
1368}
1369
1370
1371
1372void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
1373{
1374 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1375
1376 m_mgr.HideHint();
4444d148 1377
cd05bf23
BW
1378
1379 // get the mouse position, which will be used to determine the drop point
1380 wxPoint mouse_screen_pt = ::wxGetMousePosition();
1381 wxPoint mouse_client_pt = ScreenToClient(mouse_screen_pt);
1382
1383
1384 // the src tab control is the control that fired this event
1385 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1386 wxAuiTabCtrl* dest_tabs = NULL;
4444d148 1387
cd05bf23
BW
1388
1389 // If the pointer is in an existing tab frame, do a tab insert
1390 wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt);
1391 wxTabFrame* tab_frame = (wxTabFrame*)GetTabFrameFromTabCtrl(hit_wnd);
1392 if (tab_frame)
1393 {
1394 dest_tabs = tab_frame->m_tabs;
4444d148 1395
cd05bf23
BW
1396 if (dest_tabs == src_tabs)
1397 return;
1398 }
1399 else
1400 {
1401 // If there is no tabframe at all, create one
1402 wxTabFrame* new_tabs = new wxTabFrame;
da5e85d9 1403 new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
cd05bf23
BW
1404 new_tabs->m_tabs = new wxAuiTabCtrl(this,
1405 m_tab_id_counter++,
1406 wxDefaultPosition,
1407 wxDefaultSize,
1408 wxNO_BORDER);
1409 m_mgr.AddPane(new_tabs,
1410 wxPaneInfo().Bottom().CaptionVisible(false),
1411 mouse_client_pt);
1412 m_mgr.Update();
1413 dest_tabs = new_tabs->m_tabs;
1414 }
4444d148
WS
1415
1416
1417
cd05bf23
BW
1418 // remove the page from the source tabs
1419 wxAuiNotebookPage page_info = src_tabs->GetPage(evt.GetSelection());
1420 page_info.active = false;
1421 src_tabs->RemovePage(page_info.window);
1422 if (src_tabs->GetPageCount() > 0)
1423 {
1424 src_tabs->SetActivePage((size_t)0);
1425 src_tabs->DoShowHide();
1426 src_tabs->Refresh();
1427 }
1428
4444d148
WS
1429
1430
cd05bf23
BW
1431 // add the page to the destination tabs
1432 dest_tabs->AddPage(page_info.window, page_info);
4444d148 1433
cd05bf23 1434 if (src_tabs->GetPageCount() == 0)
4444d148 1435 {
cd05bf23
BW
1436 RemoveEmptyTabFrames();
1437 }
4444d148 1438
cd05bf23
BW
1439 DoSizing();
1440 dest_tabs->DoShowHide();
1441 dest_tabs->Refresh();
1442
1443 SetSelection(m_tabs.GetIdxFromWindow(page_info.window));
1444}
1445
1446wxAuiTabCtrl* wxAuiMultiNotebook::GetTabCtrlFromPoint(const wxPoint& pt)
1447{
1448 // if we've just removed the last tab from the source
1449 // tab set, the remove the tab control completely
1450 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1451 size_t i, pane_count = all_panes.GetCount();
1452 for (i = 0; i < pane_count; ++i)
1453 {
1454 if (all_panes.Item(i).name == wxT("dummy"))
1455 continue;
4444d148 1456
cd05bf23 1457 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
22a35096 1458 if (tabframe->m_tab_rect.Contains(pt))
cd05bf23
BW
1459 return tabframe->m_tabs;
1460 }
4444d148 1461
cd05bf23
BW
1462 return NULL;
1463}
1464
1465wxWindow* wxAuiMultiNotebook::GetTabFrameFromTabCtrl(wxWindow* tab_ctrl)
1466{
1467 // if we've just removed the last tab from the source
1468 // tab set, the remove the tab control completely
1469 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1470 size_t i, pane_count = all_panes.GetCount();
1471 for (i = 0; i < pane_count; ++i)
1472 {
1473 if (all_panes.Item(i).name == wxT("dummy"))
1474 continue;
4444d148 1475
cd05bf23
BW
1476 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1477 if (tabframe->m_tabs == tab_ctrl)
1478 {
1479 return tabframe;
1480 }
1481 }
4444d148 1482
cd05bf23
BW
1483 return NULL;
1484}
1485
1486void wxAuiMultiNotebook::RemoveEmptyTabFrames()
1487{
1488 bool must_update = false;
4444d148 1489
cd05bf23
BW
1490 // if we've just removed the last tab from the source
1491 // tab set, the remove the tab control completely
1492 wxPaneInfoArray all_panes = m_mgr.GetAllPanes();
1493 size_t i, pane_count = all_panes.GetCount();
1494 for (i = 0; i < pane_count; ++i)
1495 {
1496 if (all_panes.Item(i).name == wxT("dummy"))
1497 continue;
1498
1499 wxTabFrame* tab_frame = (wxTabFrame*)all_panes.Item(i).window;
1500 if (tab_frame->m_tabs->GetPageCount() == 0)
1501 {
1502 m_mgr.DetachPane(tab_frame);
4444d148 1503
cd05bf23
BW
1504 // use pending delete because sometimes during
1505 // window closing, refreshs are pending
1506 if (!wxPendingDelete.Member(tab_frame->m_tabs))
4444d148 1507 wxPendingDelete.Append(tab_frame->m_tabs);
cd05bf23 1508 //tab_frame->m_tabs->Destroy();
4444d148 1509
cd05bf23
BW
1510 delete tab_frame;
1511 must_update = true;
1512 }
1513 }
4444d148
WS
1514
1515
cd05bf23
BW
1516 // check to see if there is still a center pane;
1517 // if there isn't, make a frame the center pane
1518 wxPaneInfoArray panes = m_mgr.GetAllPanes();
1519 pane_count = panes.GetCount();
1520 wxWindow* first_good = NULL;
1521 bool center_found = false;
1522 for (i = 0; i < pane_count; ++i)
1523 {
1524 if (panes.Item(i).name == wxT("dummy"))
1525 continue;
1526 if (panes.Item(i).dock_direction == wxAUI_DOCK_CENTRE)
1527 center_found = true;
1528 if (!first_good)
1529 first_good = panes.Item(i).window;
1530 }
1531
1532 if (!center_found && first_good)
1533 {
1534 m_mgr.GetPane(first_good).Centre();
1535 must_update = true;
1536 }
1537
4444d148 1538 m_mgr.Update();
cd05bf23
BW
1539}
1540
1541void wxAuiMultiNotebook::OnChildFocus(wxChildFocusEvent& evt)
1542{
1543 int idx = m_tabs.GetIdxFromWindow(evt.GetWindow());
1544 if (idx != -1 && idx != m_curpage)
1545 {
4444d148 1546 SetSelection(idx);
cd05bf23
BW
1547 }
1548}
1549
1550
1551void wxAuiMultiNotebook::OnTabButton(wxCommandEvent& command_evt)
1552{
1553 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1554 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4444d148 1555
cd05bf23 1556 int button_id = evt.GetInt();
4444d148 1557
cd05bf23
BW
1558 if (button_id == wxAuiButtonClose)
1559 {
1560 int selection = tabs->GetActivePage();
4444d148 1561
cd05bf23
BW
1562 if (selection != -1)
1563 {
1564 wxWindow* close_wnd = tabs->GetWindowFromIdx(selection);
4444d148 1565
cd05bf23
BW
1566 if (close_wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
1567 {
1568 close_wnd->Close();
1569 }
1570 else
1571 {
1572 int main_idx = m_tabs.GetIdxFromWindow(close_wnd);
1573 DeletePage(main_idx);
1574 }
1575 }
1576 }
1577}
1578
1579
1580
1581
1582#endif // wxUSE_AUI