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