1
///////////////////////////////////////////////////////////////////////////////
3
// Purpose: wxaui: wx advanced user interface - docking window manager
4
// Author: Benjamin I. Williams
8
// Copyright: (C) Copyright 2005-2006, Kirix Corporation, All Rights Reserved
9
// Licence: wxWindows Library Licence, Version 3.1
10
///////////////////////////////////////////////////////////////////////////////
13
#include <wx/minifram.h>
17
#if (!(wxCHECK_VERSION(2, 8, 0)))
19
// -- various array and event implementations --
21
#include <wx/arrimpl.cpp>
22
WX_DECLARE_OBJARRAY(wxRect, wxAuiRectArray);
23
WX_DEFINE_OBJARRAY(wxAuiRectArray)
24
WX_DEFINE_OBJARRAY(wxDockUIPartArray)
25
WX_DEFINE_OBJARRAY(wxDockInfoArray)
26
WX_DEFINE_OBJARRAY(wxPaneButtonArray)
27
WX_DEFINE_OBJARRAY(wxPaneInfoArray)
29
wxPaneInfo wxNullPaneInfo;
30
wxDockInfo wxNullDockInfo;
31
DEFINE_EVENT_TYPE(wxEVT_AUI_PANEBUTTON)
34
// a few defines to avoid nameclashes
35
#define __MAC_OS_X_MEMORY_MANAGER_CLEAN__ 1
37
#include "wx/mac/private.h"
41
// -- wxDefaultDockArt class implementation --
43
// wxDefaultDockArt is an art provider class which does all of the drawing for
44
// wxFrameManager. This allows the library caller to customize the dock art
45
// (probably by deriving from this class), or to completely replace all drawing
46
// with custom dock art (probably by writing a new stand-alone class derived
47
// from the wxDockArt base class). The active dock art class can be set via
48
// wxFrameManager::SetDockArt()
51
// StepColour() it a utility function that simply darkens
52
// or lightens a color, based on the specified percentage
53
static wxColor StepColour(const wxColor& c, int percent)
55
int r = c.Red(), g = c.Green(), b = c.Blue();
56
return wxColour(wxMin((r*percent)/100,255),
57
wxMin((g*percent)/100,255),
58
wxMin((b*percent)/100,255));
61
static wxColor LightContrastColour(const wxColour& c)
65
// if the color is especially dark, then
66
// make the contrast even lighter
67
if (c.Red() < 128 && c.Green() < 128 && c.Blue() < 128)
70
return StepColour(c, amount);
73
// BitmapFromBits() is a utility function that creates a
74
// masked bitmap from raw bits (XBM format)
75
static wxBitmap BitmapFromBits(const unsigned char bits[], int w, int h,
76
const wxColour& color)
78
wxImage img = wxBitmap((const char*)bits, w, h).ConvertToImage();
79
img.Replace(255,255,255,123,123,123);
80
img.Replace(0,0,0,color.Red(),color.Green(),color.Blue());
81
img.SetMaskColour(123,123,123);
86
static void DrawGradientRectangle(wxDC& dc,
88
const wxColour& start_color,
89
const wxColour& end_color,
92
int rd, gd, bd, high = 0;
93
rd = end_color.Red() - start_color.Red();
94
gd = end_color.Green() - start_color.Green();
95
bd = end_color.Blue() - start_color.Blue();
97
if (direction == wxAUI_GRADIENT_VERTICAL)
98
high = rect.GetHeight()-1;
100
high = rect.GetWidth()-1;
102
for (int i = 0; i <= high; ++i)
104
int r = start_color.Red() + ((i*rd*100)/high)/100;
105
int g = start_color.Green() + ((i*gd*100)/high)/100;
106
int b = start_color.Blue() + ((i*bd*100)/high)/100;
108
wxPen p(wxColor(r,g,b));
111
if (direction == wxAUI_GRADIENT_VERTICAL)
112
dc.DrawLine(rect.x, rect.y+i, rect.x+rect.width, rect.y+i);
114
dc.DrawLine(rect.x+i, rect.y, rect.x+i, rect.y+rect.height);
119
wxDefaultDockArt::wxDefaultDockArt()
122
wxBrush toolbarbrush;
123
toolbarbrush.MacSetTheme( kThemeBrushToolbarBackground );
124
wxColor base_color = toolbarbrush.GetColour();
126
wxColor base_color = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
129
wxColor darker1_color = StepColour(base_color, 85);
130
wxColor darker2_color = StepColour(base_color, 70);
131
wxColor darker3_color = StepColour(base_color, 60);
132
wxColor darker4_color = StepColour(base_color, 50);
133
wxColor darker5_color = StepColour(base_color, 40);
135
m_active_caption_colour = LightContrastColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
136
m_active_caption_gradient_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
137
m_active_caption_text_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
138
m_inactive_caption_colour = StepColour(darker1_color, 80);
139
m_inactive_caption_gradient_colour = darker1_color;
140
m_inactive_caption_text_colour = *wxBLACK;
143
m_sash_brush = toolbarbrush;
144
m_background_brush = toolbarbrush;
145
m_gripper_brush = toolbarbrush;
147
m_sash_brush = wxBrush(base_color);
148
m_background_brush = wxBrush(base_color);
149
m_gripper_brush = wxBrush(base_color);
151
m_border_pen = wxPen(darker2_color);
152
m_gripper_pen1 = wxPen(darker5_color);
153
m_gripper_pen2 = wxPen(darker3_color);
154
m_gripper_pen3 = *wxWHITE_PEN;
157
m_caption_font = *wxSMALL_FONT;
159
m_caption_font = wxFont(8, wxDEFAULT, wxNORMAL, wxNORMAL, FALSE);
162
// some built in bitmaps
164
static unsigned char close_bits[]={
165
0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
166
0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
167
0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
169
static unsigned char close_bits[]={
170
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
171
0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
172
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
175
static unsigned char pin_bits[]={
176
0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xfc,0xdf,0xfc,0xdf,0xfc,
177
0xdf,0xfc,0xdf,0xfc,0xdf,0xfc,0x0f,0xf8,0x7f,0xff,0x7f,0xff,
178
0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
181
m_inactive_close_bitmap = BitmapFromBits(close_bits, 16, 16, *wxWHITE);
183
m_inactive_close_bitmap = BitmapFromBits(close_bits, 16, 16, m_inactive_caption_text_colour);
185
m_inactive_pin_bitmap = BitmapFromBits(pin_bits, 16, 16, m_inactive_caption_text_colour);
187
m_active_close_bitmap = BitmapFromBits(close_bits, 16, 16, *wxWHITE );
189
m_active_close_bitmap = BitmapFromBits(close_bits, 16, 16, m_active_caption_text_colour);
191
m_active_pin_bitmap = BitmapFromBits(pin_bits, 16, 16, m_active_caption_text_colour);
193
// default metric values
196
GetThemeMetric( kThemeMetricSmallPaneSplitterHeight , &height );
197
m_sash_size = height;
205
m_gradient_type = wxAUI_GRADIENT_VERTICAL;
208
int wxDefaultDockArt::GetMetric(int id)
212
case wxAUI_ART_SASH_SIZE: return m_sash_size;
213
case wxAUI_ART_CAPTION_SIZE: return m_caption_size;
214
case wxAUI_ART_GRIPPER_SIZE: return m_gripper_size;
215
case wxAUI_ART_PANE_BORDER_SIZE: return m_border_size;
216
case wxAUI_ART_PANE_BUTTON_SIZE: return m_button_size;
217
case wxAUI_ART_GRADIENT_TYPE: return m_gradient_type;
218
default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
224
void wxDefaultDockArt::SetMetric(int id, int new_val)
228
case wxAUI_ART_SASH_SIZE: m_sash_size = new_val; break;
229
case wxAUI_ART_CAPTION_SIZE: m_caption_size = new_val; break;
230
case wxAUI_ART_GRIPPER_SIZE: m_gripper_size = new_val; break;
231
case wxAUI_ART_PANE_BORDER_SIZE: m_border_size = new_val; break;
232
case wxAUI_ART_PANE_BUTTON_SIZE: m_button_size = new_val; break;
233
case wxAUI_ART_GRADIENT_TYPE: m_gradient_type = new_val; break;
234
default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
238
wxColour wxDefaultDockArt::GetColour(int id)
242
case wxAUI_ART_BACKGROUND_COLOUR: return m_background_brush.GetColour(); break;
243
case wxAUI_ART_SASH_COLOUR: return m_sash_brush.GetColour(); break;
244
case wxAUI_ART_INACTIVE_CAPTION_COLOUR: return m_inactive_caption_colour; break;
245
case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR: return m_inactive_caption_gradient_colour; break;
246
case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR: return m_inactive_caption_text_colour; break;
247
case wxAUI_ART_ACTIVE_CAPTION_COLOUR: return m_active_caption_colour; break;
248
case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR: return m_active_caption_gradient_colour; break;
249
case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR: return m_active_caption_text_colour; break;
250
case wxAUI_ART_BORDER_COLOUR: return m_border_pen.GetColour(); break;
251
case wxAUI_ART_GRIPPER_COLOUR: return m_gripper_brush.GetColour(); break;
252
default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
258
void wxDefaultDockArt::SetColour(int id, const wxColor& colour)
262
case wxAUI_ART_BACKGROUND_COLOUR: m_background_brush.SetColour(colour); break;
263
case wxAUI_ART_SASH_COLOUR: m_sash_brush.SetColour(colour); break;
264
case wxAUI_ART_INACTIVE_CAPTION_COLOUR: m_inactive_caption_colour = colour; break;
265
case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR: m_inactive_caption_gradient_colour = colour; break;
266
case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR: m_inactive_caption_text_colour = colour; break;
267
case wxAUI_ART_ACTIVE_CAPTION_COLOUR: m_active_caption_colour = colour; break;
268
case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR: m_active_caption_gradient_colour = colour; break;
269
case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR: m_active_caption_text_colour = colour; break;
270
case wxAUI_ART_BORDER_COLOUR: m_border_pen.SetColour(colour); break;
271
case wxAUI_ART_GRIPPER_COLOUR:
272
m_gripper_brush.SetColour(colour);
273
m_gripper_pen1.SetColour(StepColour(colour, 40));
274
m_gripper_pen2.SetColour(StepColour(colour, 60));
276
default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
280
void wxDefaultDockArt::SetFont(int id, const wxFont& font)
282
if (id == wxAUI_ART_CAPTION_FONT)
283
m_caption_font = font;
286
wxFont wxDefaultDockArt::GetFont(int id)
288
if (id == wxAUI_ART_CAPTION_FONT)
289
return m_caption_font;
293
void wxDefaultDockArt::DrawSash(wxDC& dc, int, const wxRect& rect)
296
HIRect splitterRect = CGRectMake( rect.x , rect.y , rect.width , rect.height );
297
CGContextRef cgContext ;
298
#if wxMAC_USE_CORE_GRAPHICS
299
cgContext = ((wxMacCGContext*)(dc.GetGraphicContext()))->GetNativeContext() ;
302
GetPortBounds( (CGrafPtr) dc.m_macPort , &bounds ) ;
303
QDBeginCGContext( (CGrafPtr) dc.m_macPort , &cgContext ) ;
304
CGContextTranslateCTM( cgContext , 0 , bounds.bottom - bounds.top ) ;
305
CGContextScaleCTM( cgContext , 1 , -1 ) ;
308
HIThemeSplitterDrawInfo drawInfo ;
309
drawInfo.version = 0 ;
310
drawInfo.state = kThemeStateActive ;
311
drawInfo.adornment = kHIThemeSplitterAdornmentNone ;
312
HIThemeDrawPaneSplitter( &splitterRect , &drawInfo , cgContext , kHIThemeOrientationNormal ) ;
314
#if wxMAC_USE_CORE_GRAPHICS
316
QDEndCGContext( (CGrafPtr) dc.m_macPort , &cgContext ) ;
320
dc.SetPen(*wxTRANSPARENT_PEN);
321
dc.SetBrush(m_sash_brush);
322
dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
327
void wxDefaultDockArt::DrawBackground(wxDC& dc, int, const wxRect& rect)
329
dc.SetPen(*wxTRANSPARENT_PEN);
331
// we have to clear first, otherwise we are drawing a light striped pattern
332
// over an already darker striped background
333
dc.SetBrush(*wxWHITE_BRUSH) ;
334
dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
336
dc.SetBrush(m_background_brush);
337
dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
340
void wxDefaultDockArt::DrawBorder(wxDC& dc, const wxRect& _rect,
343
dc.SetPen(m_border_pen);
344
dc.SetBrush(*wxTRANSPARENT_BRUSH);
347
int i, border_width = GetMetric(wxAUI_ART_PANE_BORDER_SIZE);
349
if (pane.IsToolbar())
351
for (i = 0; i < border_width; ++i)
353
dc.SetPen(*wxWHITE_PEN);
354
dc.DrawLine(rect.x, rect.y, rect.x+rect.width, rect.y);
355
dc.DrawLine(rect.x, rect.y, rect.x, rect.y+rect.height);
356
dc.SetPen(m_border_pen);
357
dc.DrawLine(rect.x, rect.y+rect.height-1,
358
rect.x+rect.width, rect.y+rect.height-1);
359
dc.DrawLine(rect.x+rect.width-1, rect.y,
360
rect.x+rect.width-1, rect.y+rect.height);
366
for (i = 0; i < border_width; ++i)
368
dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
375
void wxDefaultDockArt::DrawCaptionBackground(wxDC& dc, const wxRect& rect, bool active)
377
if (m_gradient_type == wxAUI_GRADIENT_NONE)
380
dc.SetBrush(wxBrush(m_active_caption_colour));
382
dc.SetBrush(wxBrush(m_inactive_caption_colour));
384
dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
390
// on mac the gradients are expected to become darker from the top
392
DrawGradientRectangle(dc, rect,
393
m_active_caption_gradient_colour,
394
m_active_caption_colour,
397
DrawGradientRectangle(dc, rect,
398
m_active_caption_colour,
399
m_active_caption_gradient_colour,
405
// on mac the gradients are expected to become darker from the top
407
DrawGradientRectangle(dc, rect,
408
m_inactive_caption_gradient_colour,
409
m_inactive_caption_colour,
412
DrawGradientRectangle(dc, rect,
413
m_inactive_caption_colour,
414
m_inactive_caption_gradient_colour,
422
void wxDefaultDockArt::DrawCaption(wxDC& dc,
423
const wxString& text,
427
dc.SetPen(*wxTRANSPARENT_PEN);
428
dc.SetFont(m_caption_font);
430
DrawCaptionBackground(dc, rect,
431
(pane.state & wxPaneInfo::optionActive)?true:false);
433
if (pane.state & wxPaneInfo::optionActive)
434
dc.SetTextForeground(m_active_caption_text_colour);
436
dc.SetTextForeground(m_inactive_caption_text_colour);
440
dc.GetTextExtent(wxT("ABCDEFHXfgkj"), &w, &h);
442
dc.SetClippingRegion(rect);
443
dc.DrawText(text, rect.x+3, rect.y+(rect.height/2)-(h/2)-1);
444
dc.DestroyClippingRegion();
447
void wxDefaultDockArt::DrawGripper(wxDC& dc,
451
dc.SetPen(*wxTRANSPARENT_PEN);
452
dc.SetBrush(m_gripper_brush);
454
dc.DrawRectangle(rect.x, rect.y, rect.width,rect.height);
456
if (!pane.HasGripperTop())
461
dc.SetPen(m_gripper_pen1);
462
dc.DrawPoint(rect.x+3, rect.y+y);
463
dc.SetPen(m_gripper_pen2);
464
dc.DrawPoint(rect.x+3, rect.y+y+1);
465
dc.DrawPoint(rect.x+4, rect.y+y);
466
dc.SetPen(m_gripper_pen3);
467
dc.DrawPoint(rect.x+5, rect.y+y+1);
468
dc.DrawPoint(rect.x+5, rect.y+y+2);
469
dc.DrawPoint(rect.x+4, rect.y+y+2);
472
if (y > rect.GetHeight()-5)
481
dc.SetPen(m_gripper_pen1);
482
dc.DrawPoint(rect.x+x, rect.y+3);
483
dc.SetPen(m_gripper_pen2);
484
dc.DrawPoint(rect.x+x+1, rect.y+3);
485
dc.DrawPoint(rect.x+x, rect.y+4);
486
dc.SetPen(m_gripper_pen3);
487
dc.DrawPoint(rect.x+x+1, rect.y+5);
488
dc.DrawPoint(rect.x+x+2, rect.y+5);
489
dc.DrawPoint(rect.x+x+2, rect.y+4);
492
if (x > rect.GetWidth()-5)
498
void wxDefaultDockArt::DrawPaneButton(wxDC& dc,
508
if (button_state == wxAUI_BUTTON_STATE_PRESSED)
514
if (button_state == wxAUI_BUTTON_STATE_HOVER ||
515
button_state == wxAUI_BUTTON_STATE_PRESSED)
517
if (pane.state & wxPaneInfo::optionActive)
519
dc.SetBrush(wxBrush(StepColour(m_active_caption_colour, 120)));
520
dc.SetPen(wxPen(StepColour(m_active_caption_colour, 70)));
524
dc.SetBrush(wxBrush(StepColour(m_inactive_caption_colour, 120)));
525
dc.SetPen(wxPen(StepColour(m_inactive_caption_colour, 70)));
528
// draw the background behind the button
529
dc.DrawRectangle(rect.x, rect.y, 15, 15);
536
case wxPaneInfo::buttonClose:
537
if (pane.state & wxPaneInfo::optionActive)
538
bmp = m_active_close_bitmap;
540
bmp = m_inactive_close_bitmap;
542
case wxPaneInfo::buttonPin:
543
if (pane.state & wxPaneInfo::optionActive)
544
bmp = m_active_pin_bitmap;
546
bmp = m_inactive_pin_bitmap;
550
// draw the button itself
551
dc.DrawBitmap(bmp, rect.x, rect.y, true);
555
// -- wxFloatingPane class implementation --
558
// wxFloatingPane implements a frame class with some special functionality
559
// which allows the library to sense when the frame move starts, is active,
560
// and completes. Note that it contains it's own wxFrameManager instance,
561
// which, in the future, would allow for nested managed frames.
562
// For now, with wxMSW, the wxMiniFrame window is used, but on wxGTK, wxFrame
564
#if defined( __WXMSW__ ) || defined( __WXMAC__ )
565
#define wxFloatingPaneBaseClass wxMiniFrame
567
#define wxFloatingPaneBaseClass wxFrame
571
extern "C" { void* gdk_window_get_pointer(void*, int*, int*, unsigned int*); }
574
class wxFloatingPane : public wxFloatingPaneBaseClass
577
wxFloatingPane(wxWindow* parent,
578
wxFrameManager* owner_mgr,
580
const wxPoint& pos = wxDefaultPosition,
581
const wxSize& size = wxDefaultSize)
582
: wxFloatingPaneBaseClass(parent, id, wxT(""), pos, size,
583
wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION |
584
wxCLOSE_BOX | wxFRAME_NO_TASKBAR |
585
wxFRAME_FLOAT_ON_PARENT | wxCLIP_CHILDREN)
587
m_owner_mgr = owner_mgr;
589
m_last_rect = wxRect();
590
m_mgr.SetFrame(this);
591
SetExtraStyle(wxWS_EX_PROCESS_IDLE);
599
void SetPaneWindow(const wxPaneInfo& pane)
601
m_pane_window = pane.window;
602
m_pane_window->Reparent(this);
604
wxPaneInfo contained_pane = pane;
605
contained_pane.Dock().Center().Show().
606
CaptionVisible(false).
608
Layer(0).Row(0).Position(0);
610
m_mgr.AddPane(m_pane_window, contained_pane);
613
if (pane.min_size.IsFullySpecified())
615
// because SetSizeHints() calls Fit() too (which sets the window
616
// size to its minimum allowed), we keep the size before calling
617
// SetSizeHints() and reset it afterwards...
618
wxSize tmp = GetSize();
619
GetSizer()->SetSizeHints(this);
623
SetTitle(pane.caption);
625
if (contained_pane.IsFixed())
626
SetWindowStyle(GetWindowStyle() & ~wxRESIZE_BORDER);
628
if (pane.floating_size != wxDefaultSize)
630
SetSize(pane.floating_size);
634
wxSize size = pane.best_size;
635
if (size == wxDefaultSize)
636
size = pane.min_size;
637
if (size == wxDefaultSize)
638
size = m_pane_window->GetSize();
639
if (pane.HasGripper())
641
if (pane.HasGripperTop())
642
size.y += m_owner_mgr->m_art->GetMetric(wxAUI_ART_GRIPPER_SIZE);
644
size.x += m_owner_mgr->m_art->GetMetric(wxAUI_ART_GRIPPER_SIZE);
653
void OnSize(wxSizeEvent& event)
655
m_owner_mgr->OnFloatingPaneResized(m_pane_window, event.GetSize());
658
void OnClose(wxCloseEvent& event)
660
m_owner_mgr->OnFloatingPaneClosed(m_pane_window);
664
void OnMoveEvent(wxMoveEvent& event)
666
wxRect win_rect = GetRect();
668
// skip the first move event
669
if (m_last_rect.IsEmpty())
671
m_last_rect = win_rect;
675
// prevent frame redocking during resize
676
if (m_last_rect.GetSize() != win_rect.GetSize())
678
m_last_rect = win_rect;
682
m_last_rect = win_rect;
693
OnMoving(event.GetRect());
696
void OnIdle(wxIdleEvent& event)
714
// notify the owner manager that the pane has started to move
715
m_owner_mgr->OnFloatingPaneMoveStart(m_pane_window);
718
void OnMoving(const wxRect& window_rect)
720
// notify the owner manager that the pane is moving
721
m_owner_mgr->OnFloatingPaneMoving(m_pane_window);
724
void OnMoveFinished()
726
// notify the owner manager that the pane has finished moving
727
m_owner_mgr->OnFloatingPaneMoved(m_pane_window);
730
void OnActivate(wxActivateEvent& event)
732
if (event.GetActive())
734
m_owner_mgr->OnFloatingPaneActivated(m_pane_window);
738
// utility function which determines the state of the mouse button
739
// (independant of having a wxMouseEvent handy) - utimately a better
740
// mechanism for this should be found (possibly by adding the
741
// functionality to wxWidgets itself)
742
static bool isMouseDown()
745
return (GetKeyState( VK_LBUTTON ) & (1<<15)) ? true : false;
751
gdk_window_get_pointer(NULL, &x, &y, &m);
752
return (m & 0x100) ? true : false;
753
//return (m & 0x1F00) ? true : false;
757
return GetCurrentEventButtonState() & 0x01 ;
762
wxWindow* m_pane_window; // pane window being managed
767
wxFrameManager* m_owner_mgr;
768
wxFrameManager m_mgr;
770
DECLARE_EVENT_TABLE()
773
BEGIN_EVENT_TABLE(wxFloatingPane, wxFloatingPaneBaseClass)
774
EVT_SIZE(wxFloatingPane::OnSize)
775
EVT_MOVE(wxFloatingPane::OnMoveEvent)
776
EVT_MOVING(wxFloatingPane::OnMoveEvent)
777
EVT_CLOSE(wxFloatingPane::OnClose)
778
EVT_IDLE(wxFloatingPane::OnIdle)
779
EVT_ACTIVATE(wxFloatingPane::OnActivate)
783
class wxPseudoTransparentFrame : public wxFrame
786
wxPseudoTransparentFrame(wxWindow* parent = NULL,
788
const wxString& title = wxT(""),
789
const wxPoint& pos = wxDefaultPosition,
790
const wxSize& size = wxDefaultSize,
791
long style = wxDEFAULT_FRAME_STYLE,
792
const wxString &name = wxT("frame"))
793
: wxFrame(parent, id, title, pos, size, style | wxFRAME_SHAPED, name)
795
SetBackgroundStyle(wxBG_STYLE_CUSTOM);
800
m_CanSetShape = false; // have to wait for window create event on GTK
802
m_CanSetShape = true;
804
m_Region = wxRegion(0, 0, 0, 0);
808
void SetTransparency(int amount)
812
int w=100; // some defaults
814
GetClientSize(&w, &h);
821
// m_Region.Union(0, 0, 1, m_MaxWidth);
824
for (int y=0; y<m_MaxHeight; y++)
826
// Reverse the order of the bottom 4 bits
827
int j=((y&8)?1:0)|((y&4)?2:0)|((y&2)?4:0)|((y&1)?8:0);
828
if ((j*16+8)<m_Amount)
829
m_Region.Union(0, y, m_MaxWidth, 1);
838
void OnPaint(wxPaintEvent & event)
842
if (m_Region.IsEmpty())
846
dc.SetBrush(wxColour(128, 192, 255));
848
dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION));
850
dc.SetPen(*wxTRANSPARENT_PEN);
852
wxRegionIterator upd(GetUpdateRegion()); // get the update rect list
856
wxRect rect(upd.GetRect());
857
dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
864
void OnWindowCreate(wxWindowCreateEvent& WXUNUSED(event)) {m_CanSetShape=true; SetTransparency(0);}
867
void OnSize(wxSizeEvent& event)
869
SetTransparency(m_Amount);
870
m_Region.Intersect(0, 0, event.GetSize().GetWidth(),
871
event.GetSize().GetHeight());
885
DECLARE_DYNAMIC_CLASS(wxPseudoTransparentFrame);
886
DECLARE_EVENT_TABLE();
890
IMPLEMENT_DYNAMIC_CLASS( wxPseudoTransparentFrame, wxFrame )
892
BEGIN_EVENT_TABLE(wxPseudoTransparentFrame, wxFrame)
893
EVT_PAINT(wxPseudoTransparentFrame::OnPaint)
894
EVT_SIZE(wxPseudoTransparentFrame::OnSize)
896
EVT_WINDOW_CREATE(wxPseudoTransparentFrame::OnWindowCreate)
901
// -- static utility functions --
903
static wxBitmap wxPaneCreateStippleBitmap()
905
unsigned char data[] = { 0,0,0,192,192,192, 192,192,192,0,0,0 };
906
wxImage img(2,2,data,true);
907
return wxBitmap(img);
910
static void DrawResizeHint(wxDC& dc, const wxRect& rect)
912
wxBitmap stipple = wxPaneCreateStippleBitmap();
913
wxBrush brush(stipple);
915
dc.SetPen(*wxTRANSPARENT_PEN);
917
dc.SetLogicalFunction(wxXOR);
918
dc.DrawRectangle(rect);
922
// on supported windows systems (Win2000 and greater), this function
923
// will make a frame window transparent by a certain amount
924
static void MakeWindowTransparent(wxWindow* wnd, int amount)
926
bool realtransparency = !(wnd && wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame)));
927
if (realtransparency)
930
// this API call is not in all SDKs, only the newer ones, so
931
// we will runtime bind this
932
typedef DWORD (WINAPI *PSETLAYEREDWINDOWATTR)(HWND, DWORD, BYTE, DWORD);
933
static PSETLAYEREDWINDOWATTR pSetLayeredWindowAttributes = NULL;
934
static HMODULE h = NULL;
935
HWND hwnd = (HWND)wnd->GetHWND();
938
h = LoadLibrary(_T("user32"));
940
if (!pSetLayeredWindowAttributes)
942
pSetLayeredWindowAttributes =
943
(PSETLAYEREDWINDOWATTR)GetProcAddress(h,"SetLayeredWindowAttributes");
946
if (pSetLayeredWindowAttributes == NULL)
949
LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
950
if (0 == (exstyle & 0x80000) /*WS_EX_LAYERED*/)
951
SetWindowLong(hwnd, GWL_EXSTYLE, exstyle | 0x80000 /*WS_EX_LAYERED*/);
953
pSetLayeredWindowAttributes(hwnd, 0, amount, 2 /*LWA_ALPHA*/);
960
((wxPseudoTransparentFrame *)wnd)->SetTransparency(amount);
969
// CopyDocksAndPanes() - this utility function creates copies of
970
// the dock and pane info. wxDockInfo's usually contain pointers
971
// to wxPaneInfo classes, thus this function is necessary to reliably
972
// reconstruct that relationship in the new dock info and pane info arrays
974
static void CopyDocksAndPanes(wxDockInfoArray& dest_docks,
975
wxPaneInfoArray& dest_panes,
976
const wxDockInfoArray& src_docks,
977
const wxPaneInfoArray& src_panes)
979
dest_docks = src_docks;
980
dest_panes = src_panes;
981
int i, j, k, dock_count, pc1, pc2;
982
for (i = 0, dock_count = dest_docks.GetCount(); i < dock_count; ++i)
984
wxDockInfo& dock = dest_docks.Item(i);
985
for (j = 0, pc1 = dock.panes.GetCount(); j < pc1; ++j)
986
for (k = 0, pc2 = src_panes.GetCount(); k < pc2; ++k)
987
if (dock.panes.Item(j) == &src_panes.Item(k))
988
dock.panes.Item(j) = &dest_panes.Item(k);
992
// GetMaxLayer() is an internal function which returns
993
// the highest layer inside the specified dock
994
static int GetMaxLayer(const wxDockInfoArray& docks, int dock_direction)
996
int i, dock_count, max_layer = 0;
997
for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
999
wxDockInfo& dock = docks.Item(i);
1000
if (dock.dock_direction == dock_direction &&
1001
dock.dock_layer > max_layer && !dock.fixed)
1002
max_layer = dock.dock_layer;
1008
// GetMaxRow() is an internal function which returns
1009
// the highest layer inside the specified dock
1010
static int GetMaxRow(const wxPaneInfoArray& panes, int direction, int layer)
1012
int i, pane_count, max_row = 0;
1013
for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
1015
wxPaneInfo& pane = panes.Item(i);
1016
if (pane.dock_direction == direction &&
1017
pane.dock_layer == layer &&
1018
pane.dock_row > max_row)
1019
max_row = pane.dock_row;
1026
// DoInsertDockLayer() is an internal function that inserts a new dock
1027
// layer by incrementing all existing dock layer values by one
1028
static void DoInsertDockLayer(wxPaneInfoArray& panes,
1033
for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
1035
wxPaneInfo& pane = panes.Item(i);
1036
if (!pane.IsFloating() &&
1037
pane.dock_direction == dock_direction &&
1038
pane.dock_layer >= dock_layer)
1043
// DoInsertDockLayer() is an internal function that inserts a new dock
1044
// row by incrementing all existing dock row values by one
1045
static void DoInsertDockRow(wxPaneInfoArray& panes,
1051
for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
1053
wxPaneInfo& pane = panes.Item(i);
1054
if (!pane.IsFloating() &&
1055
pane.dock_direction == dock_direction &&
1056
pane.dock_layer == dock_layer &&
1057
pane.dock_row >= dock_row)
1062
// DoInsertDockLayer() is an internal function that inserts a space for
1063
// another dock pane by incrementing all existing dock row values by one
1064
static void DoInsertPane(wxPaneInfoArray& panes,
1071
for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
1073
wxPaneInfo& pane = panes.Item(i);
1074
if (!pane.IsFloating() &&
1075
pane.dock_direction == dock_direction &&
1076
pane.dock_layer == dock_layer &&
1077
pane.dock_row == dock_row &&
1078
pane.dock_pos >= dock_pos)
1083
// FindDocks() is an internal function that returns a list of docks which meet
1084
// the specified conditions in the parameters and returns a sorted array
1085
// (sorted by layer and then row)
1086
static void FindDocks(wxDockInfoArray& docks,
1090
wxDockInfoPtrArray& arr)
1092
int begin_layer = dock_layer;
1093
int end_layer = dock_layer;
1094
int begin_row = dock_row;
1095
int end_row = dock_row;
1096
int dock_count = docks.GetCount();
1097
int layer, row, i, max_row = 0, max_layer = 0;
1099
// discover the maximum dock layer and the max row
1100
for (i = 0; i < dock_count; ++i)
1102
max_row = wxMax(max_row, docks.Item(i).dock_row);
1103
max_layer = wxMax(max_layer, docks.Item(i).dock_layer);
1106
// if no dock layer was specified, search all dock layers
1107
if (dock_layer == -1)
1110
end_layer = max_layer;
1113
// if no dock row was specified, search all dock row
1122
for (layer = begin_layer; layer <= end_layer; ++layer)
1123
for (row = begin_row; row <= end_row; ++row)
1124
for (i = 0; i < dock_count; ++i)
1126
wxDockInfo& d = docks.Item(i);
1127
if (dock_direction == -1 || dock_direction == d.dock_direction)
1129
if (d.dock_layer == layer && d.dock_row == row)
1135
// FindPaneInDock() looks up a specified window pointer inside a dock.
1136
// If found, the corresponding wxPaneInfo pointer is returned, otherwise NULL.
1137
static wxPaneInfo* FindPaneInDock(const wxDockInfo& dock, wxWindow* window)
1139
int i, count = dock.panes.GetCount();
1140
for (i = 0; i < count; ++i)
1142
wxPaneInfo* p = dock.panes.Item(i);
1143
if (p->window == window)
1149
// RemovePaneFromDocks() removes a pane window from all docks
1150
// with a possible exception specified by parameter "except"
1151
static void RemovePaneFromDocks(wxDockInfoArray& docks,
1153
wxDockInfo* except = NULL)
1156
for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
1158
wxDockInfo& d = docks.Item(i);
1161
wxPaneInfo* pi = FindPaneInDock(d, pane.window);
1167
// RenumberDockRows() takes a dock and assigns sequential numbers
1168
// to existing rows. Basically it takes out the gaps; so if a
1169
// dock has rows with numbers 0,2,5, they will become 0,1,2
1170
static void RenumberDockRows(wxDockInfoPtrArray& docks)
1172
int i, dock_count, j, pane_count;
1173
for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
1175
wxDockInfo& dock = *docks.Item(i);
1177
for (j = 0, pane_count = dock.panes.GetCount(); j < pane_count; ++j)
1178
dock.panes.Item(j)->dock_row = i;
1184
static void SetActivePane(wxPaneInfoArray& panes, wxWindow* active_pane)
1187
for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
1189
wxPaneInfo& pane = panes.Item(i);
1190
pane.state &= ~wxPaneInfo::optionActive;
1191
if (pane.window == active_pane)
1192
pane.state |= wxPaneInfo::optionActive;
1197
// this function is used to sort panes by dock position
1198
static int PaneSortFunc(wxPaneInfo** p1, wxPaneInfo** p2)
1200
return ((*p1)->dock_pos < (*p2)->dock_pos) ? -1 : 1;
1204
// -- wxFrameManager class implementation --
1207
BEGIN_EVENT_TABLE(wxFrameManager, wxEvtHandler)
1208
EVT_AUI_PANEBUTTON(wxFrameManager::OnPaneButton)
1209
EVT_PAINT(wxFrameManager::OnPaint)
1210
EVT_ERASE_BACKGROUND(wxFrameManager::OnEraseBackground)
1211
EVT_SIZE(wxFrameManager::OnSize)
1212
EVT_SET_CURSOR(wxFrameManager::OnSetCursor)
1213
EVT_LEFT_DOWN(wxFrameManager::OnLeftDown)
1214
EVT_LEFT_UP(wxFrameManager::OnLeftUp)
1215
EVT_MOTION(wxFrameManager::OnMotion)
1216
EVT_LEAVE_WINDOW(wxFrameManager::OnLeaveWindow)
1217
EVT_CHILD_FOCUS(wxFrameManager::OnChildFocus)
1218
EVT_TIMER(101, wxFrameManager::OnHintFadeTimer)
1222
wxFrameManager::wxFrameManager(wxFrame* frame, unsigned int flags)
1224
m_action = actionNone;
1225
m_last_mouse_move = wxPoint();
1226
m_hover_button = NULL;
1227
m_art = new wxDefaultDockArt;
1237
wxFrameManager::~wxFrameManager()
1242
// GetPane() looks up a wxPaneInfo structure based
1243
// on the supplied window pointer. Upon failure, GetPane()
1244
// returns an empty wxPaneInfo, a condition which can be checked
1245
// by calling wxPaneInfo::IsOk().
1247
// The pane info's structure may then be modified. Once a pane's
1248
// info is modified, wxFrameManager::Update() must be called to
1249
// realize the changes in the UI.
1251
wxPaneInfo& wxFrameManager::GetPane(wxWindow* window)
1254
for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i)
1256
wxPaneInfo& p = m_panes.Item(i);
1257
if (p.window == window)
1260
return wxNullPaneInfo;
1263
// this version of GetPane() looks up a pane based on a
1264
// 'pane name', see above comment for more info
1265
wxPaneInfo& wxFrameManager::GetPane(const wxString& name)
1268
for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i)
1270
wxPaneInfo& p = m_panes.Item(i);
1274
return wxNullPaneInfo;
1277
// GetAllPanes() returns a reference to all the pane info structures
1278
wxPaneInfoArray& wxFrameManager::GetAllPanes()
1283
// HitTest() is an internal function which determines
1284
// which UI item the specified coordinates are over
1285
// (x,y) specify a position in client coordinates
1286
wxDockUIPart* wxFrameManager::HitTest(int x, int y)
1288
wxDockUIPart* result = NULL;
1291
for (i = 0, part_count = m_uiparts.GetCount(); i < part_count; ++i)
1293
wxDockUIPart* item = &m_uiparts.Item(i);
1295
// we are not interested in typeDock, because this space
1296
// isn't used to draw anything, just for measurements;
1297
// besides, the entire dock area is covered with other
1298
// rectangles, which we are interested in.
1299
if (item->type == wxDockUIPart::typeDock)
1302
// if we already have a hit on a more specific item, we are not
1303
// interested in a pane hit. If, however, we don't already have
1304
// a hit, returning a pane hit is necessary for some operations
1305
if ((item->type == wxDockUIPart::typePane ||
1306
item->type == wxDockUIPart::typePaneBorder) && result)
1309
// if the point is inside the rectangle, we have a hit
1310
if (item->rect.Inside(x,y))
1318
// SetFlags() and GetFlags() allow the owner to set various
1319
// options which are global to wxFrameManager
1320
void wxFrameManager::SetFlags(unsigned int flags)
1325
unsigned int wxFrameManager::GetFlags() const
1331
// SetFrame() is usually called once when the frame
1332
// manager class is being initialized. "frame" specifies
1333
// the frame which should be managed by the frame mananger
1334
void wxFrameManager::SetFrame(wxFrame* frame)
1336
wxASSERT_MSG(frame, wxT("specified frame must be non-NULL"));
1339
m_frame->PushEventHandler(this);
1342
// if the owner is going to manage an MDI parent frame,
1343
// we need to add the MDI client window as the default
1346
if (frame->IsKindOf(CLASSINFO(wxMDIParentFrame)))
1348
wxMDIParentFrame* mdi_frame = (wxMDIParentFrame*)frame;
1349
wxMDIClientWindow* client_window = mdi_frame->GetClientWindow();
1351
wxASSERT_MSG(client_window, wxT("Client window is NULL!"));
1353
AddPane(client_window,
1354
wxPaneInfo().Name(wxT("mdiclient")).
1355
CenterPane().PaneBorder(false));
1361
// UnInit() must be called, usually in the destructor
1362
// of the frame class. If it is not called, usually this
1363
// will result in a crash upon program exit
1364
void wxFrameManager::UnInit()
1367
m_frame->RemoveEventHandler(this);
1370
// GetFrame() returns the frame pointer being managed by wxFrameManager
1371
wxFrame* wxFrameManager::GetFrame() const
1376
wxDockArt* wxFrameManager::GetArtProvider() const
1381
void wxFrameManager::ProcessMgrEvent(wxFrameManagerEvent& event)
1383
// first, give the owner frame a chance to override
1386
if (m_frame->ProcessEvent(event))
1390
ProcessEvent(event);
1393
// SetArtProvider() instructs wxFrameManager to use the
1394
// specified art provider for all drawing calls. This allows
1395
// plugable look-and-feel features
1396
void wxFrameManager::SetArtProvider(wxDockArt* art_provider)
1398
// delete the last art provider, if any
1401
// assign the new art provider
1402
m_art = art_provider;
1405
bool wxFrameManager::AddPane(wxWindow* window, const wxPaneInfo& pane_info)
1407
// check if the pane has a valid window
1411
// check if the pane already exists
1412
if (GetPane(pane_info.window).IsOk())
1415
m_panes.Add(pane_info);
1417
wxPaneInfo& pinfo = m_panes.Last();
1419
// set the pane window
1420
pinfo.window = window;
1422
// if the pane's name identifier is blank, create a random string
1423
if (pinfo.name.IsEmpty())
1425
pinfo.name.Printf(wxT("%08x%08x%08x%08x"),
1426
((unsigned long)pinfo.window) & 0xffffffff,
1427
(unsigned int)time(NULL),
1428
(unsigned int)clock(), m_panes.GetCount());
1431
// set initial proportion (if not already set)
1432
if (pinfo.dock_proportion == 0)
1433
pinfo.dock_proportion = 100000;
1435
if (pinfo.HasCloseButton() &&
1436
pinfo.buttons.size() == 0)
1438
wxPaneButton button;
1439
button.button_id = wxPaneInfo::buttonClose;
1440
pinfo.buttons.Add(button);
1443
if (pinfo.best_size == wxDefaultSize &&
1446
pinfo.best_size = pinfo.window->GetClientSize();
1448
if (pinfo.window->IsKindOf(CLASSINFO(wxToolBar)))
1450
// GetClientSize() doesn't get the best size for
1451
// a toolbar under some newer versions of wxWidgets,
1452
// so use GetBestSize()
1453
pinfo.best_size = pinfo.window->GetBestSize();
1455
// for some reason, wxToolBar::GetBestSize() is returning
1456
// a size that is a pixel shy of the correct amount.
1457
// I believe this to be the correct action, until
1458
// wxToolBar::GetBestSize() is fixed. Is this assumption
1460
pinfo.best_size.y++;
1463
if (pinfo.min_size != wxDefaultSize)
1465
if (pinfo.best_size.x < pinfo.min_size.x)
1466
pinfo.best_size.x = pinfo.min_size.x;
1467
if (pinfo.best_size.y < pinfo.min_size.y)
1468
pinfo.best_size.y = pinfo.min_size.y;
1475
bool wxFrameManager::AddPane(wxWindow* window,
1477
const wxString& caption)
1480
pinfo.Caption(caption);
1483
case wxTOP: pinfo.Top(); break;
1484
case wxBOTTOM: pinfo.Bottom(); break;
1485
case wxLEFT: pinfo.Left(); break;
1486
case wxRIGHT: pinfo.Right(); break;
1487
case wxCENTER: pinfo.CenterPane(); break;
1489
return AddPane(window, pinfo);
1492
bool wxFrameManager::InsertPane(wxWindow* window, const wxPaneInfo& pane_info,
1495
// shift the panes around, depending on the insert level
1496
switch (insert_level)
1498
case wxAUI_INSERT_PANE:
1499
DoInsertPane(m_panes,
1500
pane_info.dock_direction,
1501
pane_info.dock_layer,
1503
pane_info.dock_pos);
1505
case wxAUI_INSERT_ROW:
1506
DoInsertDockRow(m_panes,
1507
pane_info.dock_direction,
1508
pane_info.dock_layer,
1509
pane_info.dock_row);
1511
case wxAUI_INSERT_DOCK:
1512
DoInsertDockLayer(m_panes,
1513
pane_info.dock_direction,
1514
pane_info.dock_layer);
1518
// if the window already exists, we are basically just moving/inserting the
1519
// existing window. If it doesn't exist, we need to add it and insert it
1520
wxPaneInfo& existing_pane = GetPane(window);
1521
if (!existing_pane.IsOk())
1523
return AddPane(window, pane_info);
1527
if (pane_info.IsFloating())
1529
existing_pane.Float();
1530
if (pane_info.floating_pos != wxDefaultPosition)
1531
existing_pane.FloatingPosition(pane_info.floating_pos);
1532
if (pane_info.floating_size != wxDefaultSize)
1533
existing_pane.FloatingSize(pane_info.floating_size);
1537
existing_pane.Direction(pane_info.dock_direction);
1538
existing_pane.Layer(pane_info.dock_layer);
1539
existing_pane.Row(pane_info.dock_row);
1540
existing_pane.Position(pane_info.dock_pos);
1548
bool wxFrameManager::DetachPane(wxWindow* window)
1551
for (i = 0, count = m_panes.GetCount(); i < count; ++i)
1553
wxPaneInfo& p = m_panes.Item(i);
1554
if (p.window == window)
1558
// we have a floating frame which is being detached. We need to
1559
// reparent it to m_frame and destroy the floating frame
1562
p.window->SetSize(1,1);
1563
p.frame->Show(false);
1565
// reparent to m_frame and destroy the pane
1566
p.window->Reparent(m_frame);
1567
p.frame->SetSizer(NULL);
1568
// Set m_action_window to NULL if its pointing to this frame
1569
if ( m_action_window == p.frame )
1570
m_action_window = NULL;
1574
m_panes.RemoveAt(i);
1582
// EscapeDelimiters() changes ";" into "\;" and "|" into "\|"
1583
// in the input string. This is an internal functions which is
1584
// used for saving perspectives
1585
static wxString EscapeDelimiters(const wxString& s)
1588
result.Alloc(s.Length());
1589
const wxChar* ch = s.c_str();
1592
if (*ch == wxT(';') || *ch == wxT('|'))
1593
result += wxT('\\');
1601
// SavePerspective() saves all pane information as a single string.
1602
// This string may later be fed into LoadPerspective() to restore
1603
// all pane settings. This save and load mechanism allows an
1604
// exact pane configuration to be saved and restored at a later time
1606
wxString wxFrameManager::SavePerspective()
1610
result = wxT("layout1|");
1612
int pane_i, pane_count = m_panes.GetCount();
1613
for (pane_i = 0; pane_i < pane_count; ++pane_i)
1615
wxPaneInfo& pane = m_panes.Item(pane_i);
1617
result += wxT("name=");
1618
result += EscapeDelimiters(pane.name);
1621
result += wxT("caption=");
1622
result += EscapeDelimiters(pane.caption);
1625
result += wxString::Format(wxT("state=%u;"), pane.state);
1626
result += wxString::Format(wxT("dir=%d;"), pane.dock_direction);
1627
result += wxString::Format(wxT("layer=%d;"), pane.dock_layer);
1628
result += wxString::Format(wxT("row=%d;"), pane.dock_row);
1629
result += wxString::Format(wxT("pos=%d;"), pane.dock_pos);
1630
result += wxString::Format(wxT("prop=%d;"), pane.dock_proportion);
1631
result += wxString::Format(wxT("bestw=%d;"), pane.best_size.x);
1632
result += wxString::Format(wxT("besth=%d;"), pane.best_size.y);
1633
result += wxString::Format(wxT("minw=%d;"), pane.min_size.x);
1634
result += wxString::Format(wxT("minh=%d;"), pane.min_size.y);
1635
result += wxString::Format(wxT("maxw=%d;"), pane.max_size.x);
1636
result += wxString::Format(wxT("maxh=%d;"), pane.max_size.y);
1637
result += wxString::Format(wxT("floatx=%d;"), pane.floating_pos.x);
1638
result += wxString::Format(wxT("floaty=%d;"), pane.floating_pos.y);
1639
result += wxString::Format(wxT("floatw=%d;"), pane.floating_size.x);
1640
result += wxString::Format(wxT("floath=%d"), pane.floating_size.y);
1644
int dock_i, dock_count = m_docks.GetCount();
1645
for (dock_i = 0; dock_i < dock_count; ++dock_i)
1647
wxDockInfo& dock = m_docks.Item(dock_i);
1649
result += wxString::Format(wxT("dock_size(%d,%d,%d)=%d|"),
1650
dock.dock_direction, dock.dock_layer,
1651
dock.dock_row, dock.size);
1657
// LoadPerspective() loads a layout which was saved with SavePerspective()
1658
// If the "update" flag parameter is true, the GUI will immediately be updated
1660
bool wxFrameManager::LoadPerspective(const wxString& layout, bool update)
1662
wxString input = layout;
1665
// check layout string version
1666
part = input.BeforeFirst(wxT('|'));
1667
input = input.AfterFirst(wxT('|'));
1670
if (part != wxT("layout1"))
1674
// mark all panes currently managed as docked and hidden
1675
int pane_i, pane_count = m_panes.GetCount();
1676
for (pane_i = 0; pane_i < pane_count; ++pane_i)
1677
m_panes.Item(pane_i).Dock().Hide();
1679
// clear out the dock array; this will be reconstructed
1682
// replace escaped characters so we can
1683
// split up the string easily
1684
input.Replace(wxT("\\|"), wxT("\a"));
1685
input.Replace(wxT("\\;"), wxT("\b"));
1691
wxString pane_part = input.BeforeFirst(wxT('|'));
1692
input = input.AfterFirst(wxT('|'));
1693
pane_part.Trim(true);
1695
// if the string is empty, we're done parsing
1696
if (pane_part.IsEmpty())
1700
if (pane_part.Left(9) == wxT("dock_size"))
1702
wxString val_name = pane_part.BeforeFirst(wxT('='));
1703
wxString value = pane_part.AfterFirst(wxT('='));
1705
long dir, layer, row, size;
1706
wxString piece = val_name.AfterFirst(wxT('('));
1707
piece = piece.BeforeLast(wxT(')'));
1708
piece.BeforeFirst(wxT(',')).ToLong(&dir);
1709
piece = piece.AfterFirst(wxT(','));
1710
piece.BeforeFirst(wxT(',')).ToLong(&layer);
1711
piece.AfterFirst(wxT(',')).ToLong(&row);
1712
value.ToLong(&size);
1715
dock.dock_direction = dir;
1716
dock.dock_layer = layer;
1717
dock.dock_row = row;
1725
wxString val_part = pane_part.BeforeFirst(wxT(';'));
1726
pane_part = pane_part.AfterFirst(wxT(';'));
1727
wxString val_name = val_part.BeforeFirst(wxT('='));
1728
wxString value = val_part.AfterFirst(wxT('='));
1729
val_name.MakeLower();
1730
val_name.Trim(true);
1731
val_name.Trim(false);
1735
if (val_name.IsEmpty())
1738
if (val_name == wxT("name"))
1740
else if (val_name == wxT("caption"))
1741
pane.caption = value;
1742
else if (val_name == wxT("state"))
1743
pane.state = (unsigned int)wxAtoi(value.c_str());
1744
else if (val_name == wxT("dir"))
1745
pane.dock_direction = wxAtoi(value.c_str());
1746
else if (val_name == wxT("layer"))
1747
pane.dock_layer = wxAtoi(value.c_str());
1748
else if (val_name == wxT("row"))
1749
pane.dock_row = wxAtoi(value.c_str());
1750
else if (val_name == wxT("pos"))
1751
pane.dock_pos = wxAtoi(value.c_str());
1752
else if (val_name == wxT("prop"))
1753
pane.dock_proportion = wxAtoi(value.c_str());
1754
else if (val_name == wxT("bestw"))
1755
pane.best_size.x = wxAtoi(value.c_str());
1756
else if (val_name == wxT("besth"))
1757
pane.best_size.y = wxAtoi(value.c_str());
1758
else if (val_name == wxT("minw"))
1759
pane.min_size.x = wxAtoi(value.c_str());
1760
else if (val_name == wxT("minh"))
1761
pane.min_size.y = wxAtoi(value.c_str());
1762
else if (val_name == wxT("maxw"))
1763
pane.max_size.x = wxAtoi(value.c_str());
1764
else if (val_name == wxT("maxh"))
1765
pane.max_size.y = wxAtoi(value.c_str());
1766
else if (val_name == wxT("floatx"))
1767
pane.floating_pos.x = wxAtoi(value.c_str());
1768
else if (val_name == wxT("floaty"))
1769
pane.floating_pos.y = wxAtoi(value.c_str());
1770
else if (val_name == wxT("floatw"))
1771
pane.floating_size.x = wxAtoi(value.c_str());
1772
else if (val_name == wxT("floath"))
1773
pane.floating_size.y = wxAtoi(value.c_str());
1775
wxFAIL_MSG(wxT("Bad Perspective String"));
1779
// replace escaped characters so we can
1780
// split up the string easily
1781
pane.name.Replace(wxT("\a"), wxT("|"));
1782
pane.name.Replace(wxT("\b"), wxT(";"));
1783
pane.caption.Replace(wxT("\a"), wxT("|"));
1784
pane.caption.Replace(wxT("\b"), wxT(";"));
1786
wxPaneInfo& p = GetPane(pane.name);
1789
// the pane window couldn't be found
1790
// in the existing layout
1794
pane.window = p.window;
1795
pane.frame = p.frame;
1796
pane.buttons = p.buttons;
1807
void wxFrameManager::GetPanePositionsAndSizes(wxDockInfo& dock,
1808
wxArrayInt& positions,
1811
int caption_size = m_art->GetMetric(wxAUI_ART_CAPTION_SIZE);
1812
int pane_border_size = m_art->GetMetric(wxAUI_ART_PANE_BORDER_SIZE);
1813
int gripper_size = m_art->GetMetric(wxAUI_ART_GRIPPER_SIZE);
1818
int offset, action_pane = -1;
1819
int pane_i, pane_count = dock.panes.GetCount();
1821
// find the pane marked as our action pane
1822
for (pane_i = 0; pane_i < pane_count; ++pane_i)
1824
wxPaneInfo& pane = *(dock.panes.Item(pane_i));
1826
if (pane.state & wxPaneInfo::actionPane)
1828
wxASSERT_MSG(action_pane==-1, wxT("Too many fixed action panes"));
1829
action_pane = pane_i;
1833
// set up each panes default position, and
1834
// determine the size (width or height, depending
1835
// on the dock's orientation) of each pane
1836
for (pane_i = 0; pane_i < pane_count; ++pane_i)
1838
wxPaneInfo& pane = *(dock.panes.Item(pane_i));
1839
positions.Add(pane.dock_pos);
1842
if (pane.HasBorder())
1843
size += (pane_border_size*2);
1845
if (dock.IsHorizontal())
1847
if (pane.HasGripper() && !pane.HasGripperTop())
1848
size += gripper_size;
1849
size += pane.best_size.x;
1853
if (pane.HasGripper() && pane.HasGripperTop())
1854
size += gripper_size;
1856
if (pane.HasCaption())
1857
size += caption_size;
1858
size += pane.best_size.y;
1864
// if there is no action pane, just return the default
1865
// positions (as specified in pane.pane_pos)
1866
if (action_pane == -1)
1870
for (pane_i = action_pane-1; pane_i >= 0; --pane_i)
1872
int amount = positions[pane_i+1] - (positions[pane_i] + sizes[pane_i]);
1877
positions[pane_i] -= -amount;
1879
offset += sizes[pane_i];
1882
// if the dock mode is fixed, make sure none of the panes
1883
// overlap; we will bump panes that overlap
1885
for (pane_i = action_pane; pane_i < pane_count; ++pane_i)
1887
int amount = positions[pane_i] - offset;
1891
positions[pane_i] += -amount;
1893
offset += sizes[pane_i];
1898
void wxFrameManager::LayoutAddPane(wxSizer* cont,
1901
wxDockUIPartArray& uiparts,
1905
wxSizerItem* sizer_item;
1907
int caption_size = m_art->GetMetric(wxAUI_ART_CAPTION_SIZE);
1908
int gripper_size = m_art->GetMetric(wxAUI_ART_GRIPPER_SIZE);
1909
int pane_border_size = m_art->GetMetric(wxAUI_ART_PANE_BORDER_SIZE);
1910
int pane_button_size = m_art->GetMetric(wxAUI_ART_PANE_BUTTON_SIZE);
1912
// find out the orientation of the item (orientation for panes
1913
// is the same as the dock's orientation)
1915
if (dock.IsHorizontal())
1916
orientation = wxHORIZONTAL;
1918
orientation = wxVERTICAL;
1920
// this variable will store the proportion
1921
// value that the pane will receive
1922
int pane_proportion = pane.dock_proportion;
1924
wxBoxSizer* horz_pane_sizer = new wxBoxSizer(wxHORIZONTAL);
1925
wxBoxSizer* vert_pane_sizer = new wxBoxSizer(wxVERTICAL);
1927
if (pane.HasGripper())
1929
if (pane.HasGripperTop())
1930
sizer_item = vert_pane_sizer ->Add(1, gripper_size, 0, wxEXPAND);
1932
sizer_item = horz_pane_sizer ->Add(gripper_size, 1, 0, wxEXPAND);
1934
part.type = wxDockUIPart::typeGripper;
1938
part.orientation = orientation;
1939
part.cont_sizer = horz_pane_sizer;
1940
part.sizer_item = sizer_item;
1944
if (pane.HasCaption())
1946
// create the caption sizer
1947
wxBoxSizer* caption_sizer = new wxBoxSizer(wxHORIZONTAL);
1949
sizer_item = caption_sizer->Add(1, caption_size, 1, wxEXPAND);
1951
part.type = wxDockUIPart::typeCaption;
1955
part.orientation = orientation;
1956
part.cont_sizer = vert_pane_sizer;
1957
part.sizer_item = sizer_item;
1958
int caption_part_idx = uiparts.GetCount();
1961
// add pane buttons to the caption
1962
int i, button_count;
1963
for (i = 0, button_count = pane.buttons.GetCount();
1964
i < button_count; ++i)
1966
wxPaneButton& button = pane.buttons.Item(i);
1968
sizer_item = caption_sizer->Add(pane_button_size,
1972
part.type = wxDockUIPart::typePaneButton;
1975
part.button = &button;
1976
part.orientation = orientation;
1977
part.cont_sizer = caption_sizer;
1978
part.sizer_item = sizer_item;
1982
// add the caption sizer
1983
sizer_item = vert_pane_sizer->Add(caption_sizer, 0, wxEXPAND);
1985
uiparts.Item(caption_part_idx).sizer_item = sizer_item;
1988
// add the pane window itself
1991
sizer_item = vert_pane_sizer->Add(1, 1, 1, wxEXPAND);
1995
sizer_item = vert_pane_sizer->Add(pane.window, 1, wxEXPAND);
1996
vert_pane_sizer->SetItemMinSize(pane.window, 1, 1);
1999
part.type = wxDockUIPart::typePane;
2003
part.orientation = orientation;
2004
part.cont_sizer = vert_pane_sizer;
2005
part.sizer_item = sizer_item;
2009
// determine if the pane should have a minimum size; if the pane is
2010
// non-resizable (fixed) then we must set a minimum size. Alternitavely,
2011
// if the pane.min_size is set, we must use that value as well
2013
wxSize min_size = pane.min_size;
2016
if (min_size == wxDefaultSize)
2018
min_size = pane.best_size;
2019
pane_proportion = 0;
2023
if (min_size != wxDefaultSize)
2025
vert_pane_sizer->SetItemMinSize(
2026
vert_pane_sizer->GetChildren().GetCount()-1,
2027
min_size.x, min_size.y);
2031
// add the verticle sizer (caption, pane window) to the
2032
// horizontal sizer (gripper, verticle sizer)
2033
horz_pane_sizer->Add(vert_pane_sizer, 1, wxEXPAND);
2035
// finally, add the pane sizer to the dock sizer
2037
if (pane.HasBorder())
2039
// allowing space for the pane's border
2040
sizer_item = cont->Add(horz_pane_sizer, pane_proportion,
2041
wxEXPAND | wxALL, pane_border_size);
2043
part.type = wxDockUIPart::typePaneBorder;
2047
part.orientation = orientation;
2048
part.cont_sizer = cont;
2049
part.sizer_item = sizer_item;
2054
sizer_item = cont->Add(horz_pane_sizer, pane_proportion, wxEXPAND);
2058
void wxFrameManager::LayoutAddDock(wxSizer* cont,
2060
wxDockUIPartArray& uiparts,
2063
wxSizerItem* sizer_item;
2066
int sash_size = m_art->GetMetric(wxAUI_ART_SASH_SIZE);
2067
int orientation = dock.IsHorizontal() ? wxHORIZONTAL : wxVERTICAL;
2069
// resizable bottom and right docks have a sash before them
2070
if (!dock.fixed && (dock.dock_direction == wxAUI_DOCK_BOTTOM ||
2071
dock.dock_direction == wxAUI_DOCK_RIGHT))
2073
sizer_item = cont->Add(sash_size, sash_size, 0, wxEXPAND);
2075
part.type = wxDockUIPart::typeDockSizer;
2076
part.orientation = orientation;
2080
part.cont_sizer = cont;
2081
part.sizer_item = sizer_item;
2085
// create the sizer for the dock
2086
wxSizer* dock_sizer = new wxBoxSizer(orientation);
2088
// add each pane to the dock
2089
int pane_i, pane_count = dock.panes.GetCount();
2093
wxArrayInt pane_positions, pane_sizes;
2095
// figure out the real pane positions we will
2096
// use, without modifying the each pane's pane_pos member
2097
GetPanePositionsAndSizes(dock, pane_positions, pane_sizes);
2100
for (pane_i = 0; pane_i < pane_count; ++pane_i)
2102
wxPaneInfo& pane = *(dock.panes.Item(pane_i));
2103
int pane_pos = pane_positions.Item(pane_i);
2105
int amount = pane_pos - offset;
2108
if (dock.IsVertical())
2109
sizer_item = dock_sizer->Add(1, amount, 0, wxEXPAND);
2111
sizer_item = dock_sizer->Add(amount, 1, 0, wxEXPAND);
2113
part.type = wxDockUIPart::typeBackground;
2117
part.orientation = (orientation==wxHORIZONTAL) ? wxVERTICAL:wxHORIZONTAL;
2118
part.cont_sizer = dock_sizer;
2119
part.sizer_item = sizer_item;
2125
LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only);
2127
offset += pane_sizes.Item(pane_i);
2130
// at the end add a very small stretchable background area
2131
sizer_item = dock_sizer->Add(1,1, 1, wxEXPAND);
2133
part.type = wxDockUIPart::typeBackground;
2137
part.orientation = orientation;
2138
part.cont_sizer = dock_sizer;
2139
part.sizer_item = sizer_item;
2144
for (pane_i = 0; pane_i < pane_count; ++pane_i)
2146
wxPaneInfo& pane = *(dock.panes.Item(pane_i));
2148
// if this is not the first pane being added,
2149
// we need to add a pane sizer
2152
sizer_item = dock_sizer->Add(sash_size, sash_size, 0, wxEXPAND);
2154
part.type = wxDockUIPart::typePaneSizer;
2156
part.pane = dock.panes.Item(pane_i-1);
2158
part.orientation = (orientation==wxHORIZONTAL) ? wxVERTICAL:wxHORIZONTAL;
2159
part.cont_sizer = dock_sizer;
2160
part.sizer_item = sizer_item;
2164
LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only);
2168
if (dock.dock_direction == wxAUI_DOCK_CENTER)
2169
sizer_item = cont->Add(dock_sizer, 1, wxEXPAND);
2171
sizer_item = cont->Add(dock_sizer, 0, wxEXPAND);
2173
part.type = wxDockUIPart::typeDock;
2177
part.orientation = orientation;
2178
part.cont_sizer = cont;
2179
part.sizer_item = sizer_item;
2182
if (dock.IsHorizontal())
2183
cont->SetItemMinSize(dock_sizer, 0, dock.size);
2185
cont->SetItemMinSize(dock_sizer, dock.size, 0);
2187
// top and left docks have a sash after them
2188
if (!dock.fixed && (dock.dock_direction == wxAUI_DOCK_TOP ||
2189
dock.dock_direction == wxAUI_DOCK_LEFT))
2191
sizer_item = cont->Add(sash_size, sash_size, 0, wxEXPAND);
2193
part.type = wxDockUIPart::typeDockSizer;
2197
part.orientation = orientation;
2198
part.cont_sizer = cont;
2199
part.sizer_item = sizer_item;
2204
wxSizer* wxFrameManager::LayoutAll(wxPaneInfoArray& panes,
2205
wxDockInfoArray& docks,
2206
wxDockUIPartArray& uiparts,
2209
wxBoxSizer* container = new wxBoxSizer(wxVERTICAL);
2211
int pane_border_size = m_art->GetMetric(wxAUI_ART_PANE_BORDER_SIZE);
2212
int caption_size = m_art->GetMetric(wxAUI_ART_CAPTION_SIZE);
2213
wxSize cli_size = m_frame->GetClientSize();
2214
int i, dock_count, pane_count;
2217
// empty all docks out
2218
for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
2219
docks.Item(i).panes.Empty();
2221
// iterate through all known panes, filing each
2222
// of them into the appropriate dock. If the
2223
// pane does not exist in the dock, add it
2224
for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
2226
wxPaneInfo& p = panes.Item(i);
2228
// find any docks in this layer
2230
wxDockInfoPtrArray arr;
2231
FindDocks(docks, p.dock_direction, p.dock_layer, p.dock_row, arr);
2233
if (arr.GetCount() > 0)
2239
// dock was not found, so we need to create a new one
2241
d.dock_direction = p.dock_direction;
2242
d.dock_layer = p.dock_layer;
2243
d.dock_row = p.dock_row;
2245
dock = &docks.Last();
2249
if (p.IsDocked() && p.IsShown())
2251
// remove the pane from any existing docks except this one
2252
RemovePaneFromDocks(docks, p, dock);
2254
// pane needs to be added to the dock,
2255
// if it doesn't already exist
2256
if (!FindPaneInDock(*dock, p.window))
2257
dock->panes.Add(&p);
2261
// remove the pane from any existing docks
2262
RemovePaneFromDocks(docks, p);
2267
// remove any empty docks
2268
for (i = docks.GetCount()-1; i >= 0; --i)
2270
if (docks.Item(i).panes.GetCount() == 0)
2274
// configure the docks further
2275
for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
2277
wxDockInfo& dock = docks.Item(i);
2278
int j, dock_pane_count = dock.panes.GetCount();
2280
// sort the dock pane array by the pane's
2281
// dock position (dock_pos), in ascending order
2282
dock.panes.Sort(PaneSortFunc);
2284
// for newly created docks, set up their initial size
2289
for (j = 0; j < dock_pane_count; ++j)
2291
wxPaneInfo& pane = *dock.panes.Item(j);
2292
wxSize pane_size = pane.best_size;
2293
if (pane_size == wxDefaultSize)
2294
pane_size = pane.min_size;
2295
if (pane_size == wxDefaultSize)
2296
pane_size = pane.window->GetSize();
2298
if (dock.IsHorizontal())
2299
size = wxMax(pane_size.y, size);
2301
size = wxMax(pane_size.x, size);
2304
// add space for the border (two times), but only
2305
// if at least one pane inside the dock has a pane border
2306
for (j = 0; j < dock_pane_count; ++j)
2308
if (dock.panes.Item(j)->HasBorder())
2310
size += (pane_border_size*2);
2315
// if pane is on the top or bottom, add the caption height,
2316
// but only if at least one pane inside the dock has a caption
2317
if (dock.IsHorizontal())
2319
for (j = 0; j < dock_pane_count; ++j)
2321
if (dock.panes.Item(j)->HasCaption())
2323
size += caption_size;
2329
// new dock's size may not be more than 1/3 of the frame size
2330
if (dock.IsHorizontal())
2331
size = wxMin(size, cli_size.y/3);
2333
size = wxMin(size, cli_size.x/3);
2341
// determine the dock's minimum size
2342
bool plus_border = false;
2343
bool plus_caption = false;
2344
int dock_min_size = 0;
2345
for (j = 0; j < dock_pane_count; ++j)
2347
wxPaneInfo& pane = *dock.panes.Item(j);
2348
if (pane.min_size != wxDefaultSize)
2350
if (pane.HasBorder())
2352
if (pane.HasCaption())
2353
plus_caption = true;
2354
if (dock.IsHorizontal())
2356
if (pane.min_size.y > dock_min_size)
2357
dock_min_size = pane.min_size.y;
2361
if (pane.min_size.x > dock_min_size)
2362
dock_min_size = pane.min_size.x;
2368
dock_min_size += (pane_border_size*2);
2369
if (plus_caption && dock.IsHorizontal())
2370
dock_min_size += (caption_size);
2372
dock.min_size = dock_min_size;
2375
// if the pane's current size is less than it's
2376
// minimum, increase the dock's size to it's minimum
2377
if (dock.size < dock.min_size)
2378
dock.size = dock.min_size;
2381
// determine the dock's mode (fixed or proportional);
2382
// determine whether the dock has only toolbars
2383
bool action_pane_marked = false;
2385
dock.toolbar = true;
2386
for (j = 0; j < dock_pane_count; ++j)
2388
wxPaneInfo& pane = *dock.panes.Item(j);
2389
if (!pane.IsFixed())
2391
if (!pane.IsToolbar())
2392
dock.toolbar = false;
2393
if (pane.state & wxPaneInfo::actionPane)
2394
action_pane_marked = true;
2398
// if the dock mode is proportional and not fixed-pixel,
2399
// reassign the dock_pos to the sequential 0, 1, 2, 3;
2400
// e.g. remove gaps like 1, 2, 30, 500
2403
for (j = 0; j < dock_pane_count; ++j)
2405
wxPaneInfo& pane = *dock.panes.Item(j);
2410
// if the dock mode is fixed, and none of the panes
2411
// are being moved right now, make sure the panes
2412
// do not overlap each other. If they do, we will
2413
// adjust the panes' positions
2414
if (dock.fixed && !action_pane_marked)
2416
wxArrayInt pane_positions, pane_sizes;
2417
GetPanePositionsAndSizes(dock, pane_positions, pane_sizes);
2420
for (j = 0; j < dock_pane_count; ++j)
2422
wxPaneInfo& pane = *(dock.panes.Item(j));
2423
pane.dock_pos = pane_positions[j];
2425
int amount = pane.dock_pos - offset;
2429
pane.dock_pos += -amount;
2431
offset += pane_sizes[j];
2436
// discover the maximum dock layer
2438
for (i = 0; i < dock_count; ++i)
2439
max_layer = wxMax(max_layer, docks.Item(i).dock_layer);
2442
// clear out uiparts
2445
// create a bunch of box sizers,
2446
// from the innermost level outwards.
2447
wxSizer* cont = NULL;
2448
wxSizer* middle = NULL;
2452
for (layer = 0; layer <= max_layer; ++layer)
2454
wxDockInfoPtrArray arr;
2456
// find any docks in this layer
2457
FindDocks(docks, -1, layer, -1, arr);
2459
// if there aren't any, skip to the next layer
2463
wxSizer* old_cont = cont;
2465
// create a container which will hold this layer's
2466
// docks (top, bottom, left, right)
2467
cont = new wxBoxSizer(wxVERTICAL);
2470
// find any top docks in this layer
2471
FindDocks(docks, wxAUI_DOCK_TOP, layer, -1, arr);
2472
RenumberDockRows(arr);
2475
for (row = 0, row_count = arr.GetCount(); row < row_count; ++row)
2476
LayoutAddDock(cont, *arr.Item(row), uiparts, spacer_only);
2480
// fill out the middle layer (which consists
2481
// of left docks, content area and right docks)
2483
middle = new wxBoxSizer(wxHORIZONTAL);
2485
// find any left docks in this layer
2486
FindDocks(docks, wxAUI_DOCK_LEFT, layer, -1, arr);
2487
RenumberDockRows(arr);
2490
for (row = 0, row_count = arr.GetCount(); row < row_count; ++row)
2491
LayoutAddDock(middle, *arr.Item(row), uiparts, spacer_only);
2494
// add content dock (or previous layer's sizer
2498
// find any center docks
2499
FindDocks(docks, wxAUI_DOCK_CENTER, -1, -1, arr);
2502
for (row = 0,row_count = arr.GetCount(); row<row_count; ++row)
2503
LayoutAddDock(middle, *arr.Item(row), uiparts, spacer_only);
2507
// there are no center docks, add a background area
2508
wxSizerItem* sizer_item = middle->Add(1,1, 1, wxEXPAND);
2510
part.type = wxDockUIPart::typeBackground;
2514
part.cont_sizer = middle;
2515
part.sizer_item = sizer_item;
2521
middle->Add(old_cont, 1, wxEXPAND);
2524
// find any right docks in this layer
2525
FindDocks(docks, wxAUI_DOCK_RIGHT, layer, -1, arr);
2526
RenumberDockRows(arr);
2529
for (row = arr.GetCount()-1; row >= 0; --row)
2530
LayoutAddDock(middle, *arr.Item(row), uiparts, spacer_only);
2533
cont->Add(middle, 1, wxEXPAND);
2537
// find any bottom docks in this layer
2538
FindDocks(docks, wxAUI_DOCK_BOTTOM, layer, -1, arr);
2539
RenumberDockRows(arr);
2542
for (row = arr.GetCount()-1; row >= 0; --row)
2543
LayoutAddDock(cont, *arr.Item(row), uiparts, spacer_only);
2550
// no sizer available, because there are no docks,
2551
// therefore we will create a simple background area
2552
cont = new wxBoxSizer(wxVERTICAL);
2553
wxSizerItem* sizer_item = cont->Add(1,1, 1, wxEXPAND);
2555
part.type = wxDockUIPart::typeBackground;
2559
part.cont_sizer = middle;
2560
part.sizer_item = sizer_item;
2564
container->Add(cont, 1, wxEXPAND);
2569
// Update() updates the layout. Whenever changes are made to
2570
// one or more panes, this function should be called. It is the
2571
// external entry point for running the layout engine.
2573
void wxFrameManager::Update()
2576
int i, pane_count = m_panes.GetCount();
2578
// delete old sizer first
2579
m_frame->SetSizer(NULL);
2581
// destroy floating panes which have been
2582
// redocked or are becoming non-floating
2583
for (i = 0; i < pane_count; ++i)
2585
wxPaneInfo& p = m_panes.Item(i);
2587
if (!p.IsFloating() && p.frame)
2589
// because the pane is no longer in a floating, we need to
2590
// reparent it to m_frame and destroy the floating frame
2593
p.window->SetSize(1,1);
2594
p.frame->Show(false);
2596
// reparent to m_frame and destroy the pane
2597
p.window->Reparent(m_frame);
2598
p.frame->SetSizer(NULL);
2599
// Set m_action_window to NULL if its pointing to this frame
2600
if ( m_action_window == p.frame )
2601
m_action_window = NULL;
2608
// create a layout for all of the panes
2609
sizer = LayoutAll(m_panes, m_docks, m_uiparts, false);
2611
// hide or show panes as necessary,
2612
// and float panes as necessary
2613
for (i = 0; i < pane_count; ++i)
2615
wxPaneInfo& p = m_panes.Item(i);
2619
if (p.frame == NULL)
2621
// we need to create a frame for this
2622
// pane, which has recently been floated
2623
wxFloatingPane* frame = new wxFloatingPane(m_frame,
2628
// on MSW, if the owner desires transparent dragging, and
2629
// the dragging is happening right now, then the floating
2630
// window should have this style by default
2632
if (m_action == actionDragFloatingPane &&
2633
(m_flags & wxAUI_MGR_TRANSPARENT_DRAG))
2634
MakeWindowTransparent(frame, 150);
2637
frame->SetPaneWindow(p);
2647
// frame already exists, make sure it's position
2648
// and size reflect the information in wxPaneInfo
2649
if (p.frame->GetPosition() != p.floating_pos)
2651
p.frame->SetSize(p.floating_pos.x, p.floating_pos.y,
2652
-1, -1, wxSIZE_USE_EXISTING);
2653
//p.frame->Move(p.floating_pos.x, p.floating_pos.y);
2656
p.frame->Show(p.IsShown());
2661
p.window->Show(p.IsShown());
2664
// if "active panes" are no longer allowed, clear
2665
// any optionActive values from the pane states
2666
if ((m_flags & wxAUI_MGR_ALLOW_ACTIVE_PANE) == 0)
2668
p.state &= ~wxPaneInfo::optionActive;
2673
// keep track of the old window rectangles so we can
2674
// refresh those windows whose rect has changed
2675
wxAuiRectArray old_pane_rects;
2676
for (i = 0; i < pane_count; ++i)
2679
wxPaneInfo& p = m_panes.Item(i);
2681
if (p.window && p.IsShown() && p.IsDocked())
2684
old_pane_rects.Add(r);
2690
// apply the new sizer
2691
m_frame->SetSizer(sizer);
2692
m_frame->SetAutoLayout(false);
2697
// now that the frame layout is done, we need to check
2698
// the new pane rectangles against the old rectangles that
2699
// we saved a few lines above here. If the rectangles have
2700
// changed, the corresponding panes must also be updated
2701
for (i = 0; i < pane_count; ++i)
2703
wxPaneInfo& p = m_panes.Item(i);
2704
if (p.window && p.window->IsShown() && p.IsDocked())
2706
if (p.rect != old_pane_rects[i])
2708
p.window->Refresh();
2717
// set frame's minimum size
2720
// N.B. More work needs to be done on frame minimum sizes;
2721
// this is some intresting code that imposes the minimum size,
2722
// but we may want to include a more flexible mechanism or
2723
// options for multiple minimum-size modes, e.g. strict or lax
2724
wxSize min_size = sizer->GetMinSize();
2725
wxSize frame_size = m_frame->GetSize();
2726
wxSize client_size = m_frame->GetClientSize();
2728
wxSize minframe_size(min_size.x+frame_size.x-client_size.x,
2729
min_size.y+frame_size.y-client_size.y );
2731
m_frame->SetMinSize(minframe_size);
2733
if (frame_size.x < minframe_size.x ||
2734
frame_size.y < minframe_size.y)
2735
sizer->Fit(m_frame);
2740
// DoFrameLayout() is an internal function which invokes wxSizer::Layout
2741
// on the frame's main sizer, then measures all the various UI items
2742
// and updates their internal rectangles. This should always be called
2743
// instead of calling m_frame->Layout() directly
2745
void wxFrameManager::DoFrameLayout()
2750
for (i = 0, part_count = m_uiparts.GetCount(); i < part_count; ++i)
2752
wxDockUIPart& part = m_uiparts.Item(i);
2754
// get the rectangle of the UI part
2755
// originally, this code looked like this:
2756
// part.rect = wxRect(part.sizer_item->GetPosition(),
2757
// part.sizer_item->GetSize());
2758
// this worked quite well, with one exception: the mdi
2759
// client window had a "deferred" size variable
2760
// that returned the wrong size. It looks like
2761
// a bug in wx, because the former size of the window
2762
// was being returned. So, we will retrieve the part's
2763
// rectangle via other means
2766
part.rect = part.sizer_item->GetRect();
2767
int flag = part.sizer_item->GetFlag();
2768
int border = part.sizer_item->GetBorder();
2771
part.rect.y -= border;
2772
part.rect.height += border;
2776
part.rect.x -= border;
2777
part.rect.width += border;
2779
if (flag & wxBOTTOM)
2780
part.rect.height += border;
2782
part.rect.width += border;
2785
if (part.type == wxDockUIPart::typeDock)
2786
part.dock->rect = part.rect;
2787
if (part.type == wxDockUIPart::typePane)
2788
part.pane->rect = part.rect;
2792
// GetPanePart() looks up the pane the pane border UI part (or the regular
2793
// pane part if there is no border). This allows the caller to get the exact
2794
// rectangle of the pane in question, including decorations like
2795
// caption and border (if any).
2797
wxDockUIPart* wxFrameManager::GetPanePart(wxWindow* wnd)
2800
for (i = 0, part_count = m_uiparts.GetCount(); i < part_count; ++i)
2802
wxDockUIPart& part = m_uiparts.Item(i);
2803
if (part.type == wxDockUIPart::typePaneBorder &&
2804
part.pane && part.pane->window == wnd)
2807
for (i = 0, part_count = m_uiparts.GetCount(); i < part_count; ++i)
2809
wxDockUIPart& part = m_uiparts.Item(i);
2810
if (part.type == wxDockUIPart::typePane &&
2811
part.pane && part.pane->window == wnd)
2819
// GetDockPixelOffset() is an internal function which returns
2820
// a dock's offset in pixels from the left side of the window
2821
// (for horizontal docks) or from the top of the window (for
2822
// vertical docks). This value is necessary for calculating
2823
// fixel-pane/toolbar offsets when they are dragged.
2825
int wxFrameManager::GetDockPixelOffset(wxPaneInfo& test)
2827
// the only way to accurately calculate the dock's
2828
// offset is to actually run a theoretical layout
2830
int i, part_count, dock_count;
2831
wxDockInfoArray docks;
2832
wxPaneInfoArray panes;
2833
wxDockUIPartArray uiparts;
2834
CopyDocksAndPanes(docks, panes, m_docks, m_panes);
2837
wxSizer* sizer = LayoutAll(panes, docks, uiparts, true);
2838
wxSize client_size = m_frame->GetClientSize();
2839
sizer->SetDimension(0, 0, client_size.x, client_size.y);
2842
for (i = 0, part_count = uiparts.GetCount(); i < part_count; ++i)
2844
wxDockUIPart& part = uiparts.Item(i);
2845
part.rect = wxRect(part.sizer_item->GetPosition(),
2846
part.sizer_item->GetSize());
2847
if (part.type == wxDockUIPart::typeDock)
2848
part.dock->rect = part.rect;
2853
for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
2855
wxDockInfo& dock = docks.Item(i);
2856
if (test.dock_direction == dock.dock_direction &&
2857
test.dock_layer==dock.dock_layer && test.dock_row==dock.dock_row)
2859
if (dock.IsVertical())
2871
// ProcessDockResult() is a utility function used by DoDrop() - it checks
2872
// if a dock operation is allowed, the new dock position is copied into
2873
// the target info. If the operation was allowed, the function returns true.
2875
static bool ProcessDockResult(wxPaneInfo& target,
2876
const wxPaneInfo& new_pos)
2878
bool allowed = false;
2879
switch (new_pos.dock_direction)
2881
case wxAUI_DOCK_TOP: allowed = target.IsTopDockable(); break;
2882
case wxAUI_DOCK_BOTTOM: allowed = target.IsBottomDockable(); break;
2883
case wxAUI_DOCK_LEFT: allowed = target.IsLeftDockable(); break;
2884
case wxAUI_DOCK_RIGHT: allowed = target.IsRightDockable(); break;
2894
// DoDrop() is an important function. It basically takes a mouse position,
2895
// and determines where the pane's new position would be. If the pane is to be
2896
// dropped, it performs the drop operation using the specified dock and pane
2897
// arrays. By specifying copied dock and pane arrays when calling, a "what-if"
2898
// scenario can be performed, giving precise coordinates for drop hints.
2899
// If, however, wxFrameManager:m_docks and wxFrameManager::m_panes are specified
2900
// as parameters, the changes will be made to the main state arrays
2902
const int auiInsertRowPixels = 10;
2903
const int auiNewRowPixels = 40;
2904
const int auiLayerInsertPixels = 40;
2905
const int auiLayerInsertOffset = 5;
2907
bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
2908
wxPaneInfoArray& panes,
2911
const wxPoint& offset)
2913
wxSize cli_size = m_frame->GetClientSize();
2915
wxPaneInfo drop = target;
2918
// The result should always be shown
2922
// Check to see if the pane has been dragged outside of the window
2923
// (or near to the outside of the window), if so, dock it along the edge
2926
int layer_insert_offset = auiLayerInsertOffset;
2927
if (target.IsToolbar())
2928
layer_insert_offset = 0;
2930
if (pt.x < layer_insert_offset &&
2931
pt.x > layer_insert_offset-auiLayerInsertPixels)
2933
int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_LEFT),
2934
GetMaxLayer(docks, wxAUI_DOCK_BOTTOM)),
2935
GetMaxLayer(docks, wxAUI_DOCK_TOP)) + 1;
2939
Position(pt.y - GetDockPixelOffset(drop) - offset.y);
2940
return ProcessDockResult(target, drop);
2942
else if (pt.y < layer_insert_offset &&
2943
pt.y > layer_insert_offset-auiLayerInsertPixels)
2945
int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_TOP),
2946
GetMaxLayer(docks, wxAUI_DOCK_LEFT)),
2947
GetMaxLayer(docks, wxAUI_DOCK_RIGHT)) + 1;
2951
Position(pt.x - GetDockPixelOffset(drop) - offset.x);
2952
return ProcessDockResult(target, drop);
2954
else if (pt.x >= cli_size.x - layer_insert_offset &&
2955
pt.x < cli_size.x - layer_insert_offset + auiLayerInsertPixels)
2957
int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_RIGHT),
2958
GetMaxLayer(docks, wxAUI_DOCK_TOP)),
2959
GetMaxLayer(docks, wxAUI_DOCK_BOTTOM)) + 1;
2960
drop.Dock().Right().
2963
Position(pt.y - GetDockPixelOffset(drop) - offset.y);
2964
return ProcessDockResult(target, drop);
2966
else if (pt.y >= cli_size.y - layer_insert_offset &&
2967
pt.y < cli_size.y - layer_insert_offset + auiLayerInsertPixels)
2969
int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_BOTTOM),
2970
GetMaxLayer(docks, wxAUI_DOCK_LEFT)),
2971
GetMaxLayer(docks, wxAUI_DOCK_RIGHT)) + 1;
2972
drop.Dock().Bottom().
2975
Position(pt.x - GetDockPixelOffset(drop) - offset.x);
2976
return ProcessDockResult(target, drop);
2980
wxDockUIPart* part = HitTest(pt.x, pt.y);
2983
if (drop.IsToolbar())
2985
if (!part || !part->dock)
2989
// calculate the offset from where the dock begins
2990
// to the point where the user dropped the pane
2991
int dock_drop_offset = 0;
2992
if (part->dock->IsHorizontal())
2993
dock_drop_offset = pt.x - part->dock->rect.x - offset.x;
2995
dock_drop_offset = pt.y - part->dock->rect.y - offset.y;
2998
// toolbars may only be moved in and to fixed-pane docks,
2999
// otherwise we will try to float the pane. Also, the pane
3000
// should float if being dragged over center pane windows
3001
if (!part->dock->fixed || part->dock->dock_direction == wxAUI_DOCK_CENTER)
3003
if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) &&
3004
(drop.IsFloatable() ||
3005
(part->dock->dock_direction != wxAUI_DOCK_CENTER &&
3006
part->dock->dock_direction != wxAUI_DOCK_NONE)))
3011
return ProcessDockResult(target, drop);
3015
Direction(part->dock->dock_direction).
3016
Layer(part->dock->dock_layer).
3017
Row(part->dock->dock_row).
3018
Position(dock_drop_offset);
3021
((pt.y < part->dock->rect.y + 2) && part->dock->IsHorizontal()) ||
3022
((pt.x < part->dock->rect.x + 2) && part->dock->IsVertical())
3023
) && part->dock->panes.GetCount() > 1)
3025
int row = drop.dock_row;
3026
DoInsertDockRow(panes, part->dock->dock_direction,
3027
part->dock->dock_layer,
3028
part->dock->dock_row);
3029
drop.dock_row = row;
3033
((pt.y > part->dock->rect.y + part->dock->rect.height - 2 ) && part->dock->IsHorizontal()) ||
3034
((pt.x > part->dock->rect.x + part->dock->rect.width - 2 ) && part->dock->IsVertical())
3035
) && part->dock->panes.GetCount() > 1)
3037
DoInsertDockRow(panes, part->dock->dock_direction,
3038
part->dock->dock_layer,
3039
part->dock->dock_row+1);
3040
drop.dock_row = part->dock->dock_row+1;
3043
return ProcessDockResult(target, drop);
3052
if (part->type == wxDockUIPart::typePaneBorder ||
3053
part->type == wxDockUIPart::typeCaption ||
3054
part->type == wxDockUIPart::typeGripper ||
3055
part->type == wxDockUIPart::typePaneButton ||
3056
part->type == wxDockUIPart::typePane ||
3057
part->type == wxDockUIPart::typePaneSizer ||
3058
part->type == wxDockUIPart::typeDockSizer ||
3059
part->type == wxDockUIPart::typeBackground)
3061
if (part->type == wxDockUIPart::typeDockSizer)
3063
if (part->dock->panes.GetCount() != 1)
3065
part = GetPanePart(part->dock->panes.Item(0)->window);
3072
// If a normal frame is being dragged over a toolbar, insert it
3073
// along the edge under the toolbar, but over all other panes.
3074
// (this could be done much better, but somehow factoring this
3075
// calculation with the one at the beginning of this function)
3076
if (part->dock && part->dock->toolbar)
3080
switch (part->dock->dock_direction)
3082
case wxAUI_DOCK_LEFT:
3083
layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_LEFT),
3084
GetMaxLayer(docks, wxAUI_DOCK_BOTTOM)),
3085
GetMaxLayer(docks, wxAUI_DOCK_TOP));
3087
case wxAUI_DOCK_TOP:
3088
layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_TOP),
3089
GetMaxLayer(docks, wxAUI_DOCK_LEFT)),
3090
GetMaxLayer(docks, wxAUI_DOCK_RIGHT));
3092
case wxAUI_DOCK_RIGHT:
3093
layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_RIGHT),
3094
GetMaxLayer(docks, wxAUI_DOCK_TOP)),
3095
GetMaxLayer(docks, wxAUI_DOCK_BOTTOM));
3097
case wxAUI_DOCK_BOTTOM:
3098
layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_BOTTOM),
3099
GetMaxLayer(docks, wxAUI_DOCK_LEFT)),
3100
GetMaxLayer(docks, wxAUI_DOCK_RIGHT));
3104
DoInsertDockRow(panes, part->dock->dock_direction,
3107
Direction(part->dock->dock_direction).
3108
Layer(layer).Row(0).Position(0);
3109
return ProcessDockResult(target, drop);
3116
part = GetPanePart(part->pane->window);
3120
bool insert_dock_row = false;
3121
int insert_row = part->pane->dock_row;
3122
int insert_dir = part->pane->dock_direction;
3123
int insert_layer = part->pane->dock_layer;
3125
switch (part->pane->dock_direction)
3127
case wxAUI_DOCK_TOP:
3128
if (pt.y >= part->rect.y &&
3129
pt.y < part->rect.y+auiInsertRowPixels)
3130
insert_dock_row = true;
3132
case wxAUI_DOCK_BOTTOM:
3133
if (pt.y > part->rect.y+part->rect.height-auiInsertRowPixels &&
3134
pt.y <= part->rect.y + part->rect.height)
3135
insert_dock_row = true;
3137
case wxAUI_DOCK_LEFT:
3138
if (pt.x >= part->rect.x &&
3139
pt.x < part->rect.x+auiInsertRowPixels)
3140
insert_dock_row = true;
3142
case wxAUI_DOCK_RIGHT:
3143
if (pt.x > part->rect.x+part->rect.width-auiInsertRowPixels &&
3144
pt.x <= part->rect.x+part->rect.width)
3145
insert_dock_row = true;
3147
case wxAUI_DOCK_CENTER:
3149
// "new row pixels" will be set to the default, but
3150
// must never exceed 20% of the window size
3151
int new_row_pixels_x = auiNewRowPixels;
3152
int new_row_pixels_y = auiNewRowPixels;
3154
if (new_row_pixels_x > (part->rect.width*20)/100)
3155
new_row_pixels_x = (part->rect.width*20)/100;
3157
if (new_row_pixels_y > (part->rect.height*20)/100)
3158
new_row_pixels_y = (part->rect.height*20)/100;
3161
// determine if the mouse pointer is in a location that
3162
// will cause a new row to be inserted. The hot spot positions
3163
// are along the borders of the center pane
3166
insert_dock_row = true;
3167
if (pt.x >= part->rect.x &&
3168
pt.x < part->rect.x+new_row_pixels_x)
3169
insert_dir = wxAUI_DOCK_LEFT;
3171
if (pt.y >= part->rect.y &&
3172
pt.y < part->rect.y+new_row_pixels_y)
3173
insert_dir = wxAUI_DOCK_TOP;
3175
if (pt.x >= part->rect.x + part->rect.width-new_row_pixels_x &&
3176
pt.x < part->rect.x + part->rect.width)
3177
insert_dir = wxAUI_DOCK_RIGHT;
3179
if (pt.y >= part->rect.y+ part->rect.height-new_row_pixels_y &&
3180
pt.y < part->rect.y + part->rect.height)
3181
insert_dir = wxAUI_DOCK_BOTTOM;
3185
insert_row = GetMaxRow(panes, insert_dir, insert_layer) + 1;
3189
if (insert_dock_row)
3191
DoInsertDockRow(panes, insert_dir, insert_layer, insert_row);
3192
drop.Dock().Direction(insert_dir).
3193
Layer(insert_layer).
3196
return ProcessDockResult(target, drop);
3199
// determine the mouse offset and the pane size, both in the
3200
// direction of the dock itself, and perpendicular to the dock
3204
if (part->orientation == wxVERTICAL)
3206
offset = pt.y - part->rect.y;
3207
size = part->rect.GetHeight();
3211
offset = pt.x - part->rect.x;
3212
size = part->rect.GetWidth();
3215
int drop_position = part->pane->dock_pos;
3217
// if we are in the top/left part of the pane,
3218
// insert the pane before the pane being hovered over
3219
if (offset <= size/2)
3221
drop_position = part->pane->dock_pos;
3223
part->pane->dock_direction,
3224
part->pane->dock_layer,
3225
part->pane->dock_row,
3226
part->pane->dock_pos);
3229
// if we are in the bottom/right part of the pane,
3230
// insert the pane before the pane being hovered over
3231
if (offset > size/2)
3233
drop_position = part->pane->dock_pos+1;
3235
part->pane->dock_direction,
3236
part->pane->dock_layer,
3237
part->pane->dock_row,
3238
part->pane->dock_pos+1);
3242
Direction(part->dock->dock_direction).
3243
Layer(part->dock->dock_layer).
3244
Row(part->dock->dock_row).
3245
Position(drop_position);
3246
return ProcessDockResult(target, drop);
3253
void wxFrameManager::OnHintFadeTimer(wxTimerEvent& event)
3255
bool realtransparency = !(m_hint_wnd && m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame)));
3256
if (!m_hint_wnd || m_hint_fadeamt >= (realtransparency?50:128))
3258
m_hint_fadetimer.Stop();
3262
m_hint_fadeamt += 5;
3263
MakeWindowTransparent(m_hint_wnd, m_hint_fadeamt);
3266
void wxFrameManager::ShowHint(const wxRect& rect)
3269
static bool realtransparency = false;
3271
// First, determine if the operating system can handle transparency.
3272
// Transparency is available on Win2000 and above
3274
static int os_type = -1;
3275
static int ver_major = -1;
3278
os_type = ::wxGetOsVersion(&ver_major);
3280
realtransparency = (m_flags & wxAUI_MGR_TRANSPARENT_HINT) && os_type == wxWINDOWS_NT && ver_major >= 5;
3283
// If the transparent flag is set, and the OS supports it,
3284
// go ahead and use a transparent hint
3286
if (m_last_hint == rect)
3290
int initial_fade = realtransparency?50:128;
3291
if (m_flags & wxAUI_MGR_TRANSPARENT_HINT_FADE)
3294
if (m_hint_wnd == NULL)
3296
wxPoint pt = rect.GetPosition();
3297
wxSize size = rect.GetSize();
3299
if (realtransparency)
3302
m_hint_wnd = new wxFrame(m_frame, -1, wxEmptyString, pt, size,
3303
wxFRAME_TOOL_WINDOW |
3304
wxFRAME_FLOAT_ON_PARENT |
3305
wxFRAME_NO_TASKBAR |
3307
m_hint_wnd->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION));
3312
m_hint_wnd = new wxPseudoTransparentFrame (m_frame, -1, wxEmptyString, pt, size,
3313
wxFRAME_TOOL_WINDOW |
3314
wxFRAME_FLOAT_ON_PARENT |
3315
wxFRAME_NO_TASKBAR |
3318
MakeWindowTransparent(m_hint_wnd, initial_fade);
3321
// if we are dragging a floating pane, set the focus
3322
// back to that floating pane (otherwise it becomes unfocused)
3323
if (m_action == actionDragFloatingPane && m_action_window)
3324
m_action_window->SetFocus();
3329
wxPoint pt = rect.GetPosition();
3330
wxSize size = rect.GetSize();
3331
MakeWindowTransparent(m_hint_wnd, initial_fade);
3332
m_hint_wnd->SetSize(pt.x, pt.y, rect.width, rect.height);
3334
if (m_action == actionDragFloatingPane && m_action_window)
3335
m_action_window->SetFocus();
3338
if (m_flags & wxAUI_MGR_TRANSPARENT_HINT_FADE)
3340
// start fade in timer
3342
m_hint_fadetimer.SetOwner(this, 101);
3343
m_hint_fadetimer.Start(5);
3349
void wxFrameManager::HideHint()
3351
// hides a transparent window hint (currently wxMSW only)
3354
MakeWindowTransparent(m_hint_wnd, 0);
3355
m_hint_fadetimer.Stop();
3356
m_last_hint = wxRect();
3359
// We don't need to destroy the hint window here, as it gets reused, but let's try.
3360
m_hint_wnd->Destroy();
3369
// DrawHintRect() draws a drop hint rectangle. First calls DoDrop() to
3370
// determine the exact position the pane would be at were if dropped. If
3371
// the pame would indeed become docked at the specified drop point,
3372
// DrawHintRect() then calls ShowHint() to indicate this drop rectangle.
3373
// "pane_window" is the window pointer of the pane being dragged, pt is
3374
// the mouse position, in client coordinates
3375
void wxFrameManager::DrawHintRect(wxWindow* pane_window,
3377
const wxPoint& offset)
3381
// we need to paint a hint rectangle; to find out the exact hint rectangle,
3382
// we will create a new temporary layout and then measure the resulting
3383
// rectangle; we will create a copy of the docking structures (m_dock)
3384
// so that we don't modify the real thing on screen
3386
int i, pane_count, part_count;
3387
wxDockInfoArray docks;
3388
wxPaneInfoArray panes;
3389
wxDockUIPartArray uiparts;
3390
wxPaneInfo hint = GetPane(pane_window);
3391
hint.name = wxT("__HINT__");
3396
CopyDocksAndPanes(docks, panes, m_docks, m_panes);
3398
// remove any pane already there which bears the same window;
3399
// this happens when you are moving a pane around in a dock
3400
for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
3402
if (panes.Item(i).window == pane_window)
3404
RemovePaneFromDocks(docks, panes.Item(i));
3410
// find out where the new pane would be
3411
if (!DoDrop(docks, panes, hint, pt, offset))
3419
wxSizer* sizer = LayoutAll(panes, docks, uiparts, true);
3420
wxSize client_size = m_frame->GetClientSize();
3421
sizer->SetDimension(0, 0, client_size.x, client_size.y);
3424
for (i = 0, part_count = uiparts.GetCount();
3425
i < part_count; ++i)
3427
wxDockUIPart& part = uiparts.Item(i);
3429
if (part.type == wxDockUIPart::typePaneBorder &&
3430
part.pane && part.pane->name == wxT("__HINT__"))
3432
rect = wxRect(part.sizer_item->GetPosition(),
3433
part.sizer_item->GetSize());
3446
// actually show the hint rectangle on the screen
3447
m_frame->ClientToScreen(&rect.x, &rect.y);
3451
void wxFrameManager::OnFloatingPaneMoveStart(wxWindow* wnd)
3453
// try to find the pane
3454
wxPaneInfo& pane = GetPane(wnd);
3455
wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
3458
if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG)
3459
MakeWindowTransparent(pane.frame, 150);
3463
void wxFrameManager::OnFloatingPaneMoving(wxWindow* wnd)
3465
// try to find the pane
3466
wxPaneInfo& pane = GetPane(wnd);
3467
wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
3469
wxPoint pt = ::wxGetMousePosition();
3470
wxPoint client_pt = m_frame->ScreenToClient(pt);
3472
// calculate the offset from the upper left-hand corner
3473
// of the frame to the mouse pointer
3474
wxPoint frame_pos = pane.frame->GetPosition();
3475
wxPoint action_offset(pt.x-frame_pos.x, pt.y-frame_pos.y);
3477
// no hint for toolbar floating windows
3478
if (pane.IsToolbar() && m_action == actionDragFloatingPane)
3480
if (m_action == actionDragFloatingPane)
3482
wxDockInfoArray docks;
3483
wxPaneInfoArray panes;
3484
wxDockUIPartArray uiparts;
3485
wxPaneInfo hint = pane;
3487
CopyDocksAndPanes(docks, panes, m_docks, m_panes);
3489
// find out where the new pane would be
3490
if (!DoDrop(docks, panes, hint, client_pt))
3492
if (hint.IsFloating())
3496
m_action = actionDragToolbarPane;
3497
m_action_window = pane.window;
3506
// if a key modifier is pressed while dragging the frame,
3507
// don't dock the window
3508
if (wxGetKeyState(WXK_CONTROL) || wxGetKeyState(WXK_ALT))
3515
DrawHintRect(wnd, client_pt, action_offset);
3518
// this cleans up some screen artifacts that are caused on GTK because
3519
// we aren't getting the exact size of the window (see comment
3529
void wxFrameManager::OnFloatingPaneMoved(wxWindow* wnd)
3531
// try to find the pane
3532
wxPaneInfo& pane = GetPane(wnd);
3533
wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
3535
wxPoint pt = ::wxGetMousePosition();
3536
wxPoint client_pt = m_frame->ScreenToClient(pt);
3538
// calculate the offset from the upper left-hand corner
3539
// of the frame to the mouse pointer
3540
wxPoint frame_pos = pane.frame->GetPosition();
3541
wxPoint action_offset(pt.x-frame_pos.x, pt.y-frame_pos.y);
3544
// if a key modifier is pressed while dragging the frame,
3545
// don't dock the window
3546
if (wxGetKeyState(WXK_CONTROL) || wxGetKeyState(WXK_ALT))
3553
// do the drop calculation
3554
DoDrop(m_docks, m_panes, pane, client_pt, action_offset);
3556
// if the pane is still floating, update it's floating
3557
// position (that we store)
3558
if (pane.IsFloating())
3560
pane.floating_pos = pane.frame->GetPosition();
3563
if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG)
3564
MakeWindowTransparent(pane.frame, 255);
3573
void wxFrameManager::OnFloatingPaneResized(wxWindow* wnd, const wxSize& size)
3575
// try to find the pane
3576
wxPaneInfo& pane = GetPane(wnd);
3577
wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
3579
pane.floating_size = size;
3582
void wxFrameManager::OnFloatingPaneClosed(wxWindow* wnd)
3584
// try to find the pane
3585
wxPaneInfo& pane = GetPane(wnd);
3586
wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
3588
// reparent the pane window back to us and
3589
// prepare the frame window for destruction
3590
pane.window->Show(false);
3591
pane.window->Reparent(m_frame);
3596
void wxFrameManager::OnFloatingPaneActivated(wxWindow* wnd)
3598
if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE)
3600
// try to find the pane
3601
wxASSERT_MSG(GetPane(wnd).IsOk(), wxT("Pane window not found"));
3603
SetActivePane(m_panes, wnd);
3608
// Render() draws all of the pane captions, sashes,
3609
// backgrounds, captions, grippers, pane borders and buttons.
3610
// It renders the entire user interface.
3612
void wxFrameManager::Render(wxDC* dc)
3618
for (i = 0, part_count = m_uiparts.GetCount();
3619
i < part_count; ++i)
3621
wxDockUIPart& part = m_uiparts.Item(i);
3623
// don't draw hidden pane items
3624
if (part.sizer_item && !part.sizer_item->IsShown())
3629
case wxDockUIPart::typeDockSizer:
3630
case wxDockUIPart::typePaneSizer:
3631
m_art->DrawSash(*dc, part.orientation, part.rect);
3633
case wxDockUIPart::typeBackground:
3634
m_art->DrawBackground(*dc, part.orientation, part.rect);
3636
case wxDockUIPart::typeCaption:
3637
m_art->DrawCaption(*dc, part.pane->caption, part.rect, *part.pane);
3639
case wxDockUIPart::typeGripper:
3640
m_art->DrawGripper(*dc, part.rect, *part.pane);
3642
case wxDockUIPart::typePaneBorder:
3643
m_art->DrawBorder(*dc, part.rect, *part.pane);
3645
case wxDockUIPart::typePaneButton:
3646
m_art->DrawPaneButton(*dc, part.button->button_id,
3647
wxAUI_BUTTON_STATE_NORMAL, part.rect, *part.pane);
3653
void wxFrameManager::Repaint(wxDC* dc)
3658
m_frame->Refresh() ;
3664
m_frame->GetClientSize(&w, &h);
3666
// figure out which dc to use; if one
3667
// has been specified, use it, otherwise
3669
wxClientDC* client_dc = NULL;
3672
client_dc = new wxClientDC(m_frame);
3676
// if the frame has a toolbar, the client area
3677
// origin will not be (0,0).
3678
wxPoint pt = m_frame->GetClientAreaOrigin();
3679
if (pt.x != 0 || pt.y != 0)
3680
dc->SetDeviceOrigin(pt.x, pt.y);
3682
// render all the items
3685
// if we created a client_dc, delete it
3690
void wxFrameManager::OnPaint(wxPaintEvent& event)
3692
wxPaintDC dc(m_frame);
3696
void wxFrameManager::OnEraseBackground(wxEraseEvent& event)
3703
void wxFrameManager::OnSize(wxSizeEvent& event)
3714
void wxFrameManager::OnSetCursor(wxSetCursorEvent& event)
3717
wxDockUIPart* part = HitTest(event.GetX(), event.GetY());
3718
wxCursor cursor = wxNullCursor;
3722
if (part->type == wxDockUIPart::typeDockSizer ||
3723
part->type == wxDockUIPart::typePaneSizer)
3725
// a dock may not be resized if it has a single
3726
// pane which is not resizable
3727
if (part->type == wxDockUIPart::typeDockSizer && part->dock &&
3728
part->dock->panes.GetCount() == 1 &&
3729
part->dock->panes.Item(0)->IsFixed())
3732
// panes that may not be resized do not get a sizing cursor
3733
if (part->pane && part->pane->IsFixed())
3736
if (part->orientation == wxVERTICAL)
3737
cursor = wxCursor(wxCURSOR_SIZEWE);
3739
cursor = wxCursor(wxCURSOR_SIZENS);
3741
else if (part->type == wxDockUIPart::typeGripper)
3743
cursor = wxCursor(wxCURSOR_SIZING);
3747
event.SetCursor(cursor);
3752
void wxFrameManager::UpdateButtonOnScreen(wxDockUIPart* button_ui_part,
3753
const wxMouseEvent& event)
3755
wxDockUIPart* hit_test = HitTest(event.GetX(), event.GetY());
3757
int state = wxAUI_BUTTON_STATE_NORMAL;
3759
if (hit_test == button_ui_part)
3761
if (event.LeftDown())
3762
state = wxAUI_BUTTON_STATE_PRESSED;
3764
state = wxAUI_BUTTON_STATE_HOVER;
3768
if (event.LeftDown())
3769
state = wxAUI_BUTTON_STATE_HOVER;
3772
// now repaint the button with hover state
3773
wxClientDC cdc(m_frame);
3775
// if the frame has a toolbar, the client area
3776
// origin will not be (0,0).
3777
wxPoint pt = m_frame->GetClientAreaOrigin();
3778
if (pt.x != 0 || pt.y != 0)
3779
cdc.SetDeviceOrigin(pt.x, pt.y);
3781
m_art->DrawPaneButton(cdc,
3782
button_ui_part->button->button_id,
3784
button_ui_part->rect,
3788
void wxFrameManager::OnLeftDown(wxMouseEvent& event)
3790
wxDockUIPart* part = HitTest(event.GetX(), event.GetY());
3793
if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER)
3796
if (part->type == wxDockUIPart::typeDockSizer ||
3797
part->type == wxDockUIPart::typePaneSizer)
3799
// a dock may not be resized if it has a single
3800
// pane which is not resizable
3801
if (part->type == wxDockUIPart::typeDockSizer && part->dock &&
3802
part->dock->panes.GetCount() == 1 &&
3803
part->dock->panes.Item(0)->IsFixed())
3806
// panes that may not be resized should be ignored here
3807
if (part->pane && part->pane->IsFixed())
3810
m_action = actionResize;
3811
m_action_part = part;
3812
m_action_hintrect = wxRect();
3813
m_action_start = wxPoint(event.m_x, event.m_y);
3814
m_action_offset = wxPoint(event.m_x - part->rect.x,
3815
event.m_y - part->rect.y);
3816
m_frame->CaptureMouse();
3818
else if (part->type == wxDockUIPart::typePaneButton)
3820
m_action = actionClickButton;
3821
m_action_part = part;
3822
m_action_start = wxPoint(event.m_x, event.m_y);
3823
m_frame->CaptureMouse();
3825
UpdateButtonOnScreen(part, event);
3827
else if (part->type == wxDockUIPart::typeCaption ||
3828
part->type == wxDockUIPart::typeGripper)
3830
if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE)
3832
// set the caption as active
3833
SetActivePane(m_panes, part->pane->window);
3837
m_action = actionClickCaption;
3838
m_action_part = part;
3839
m_action_start = wxPoint(event.m_x, event.m_y);
3840
m_action_offset = wxPoint(event.m_x - part->rect.x,
3841
event.m_y - part->rect.y);
3842
m_frame->CaptureMouse();
3862
void wxFrameManager::OnLeftUp(wxMouseEvent& event)
3864
if (m_action == actionResize)
3866
m_frame->ReleaseMouse();
3868
// get rid of the hint rectangle
3870
DrawResizeHint(dc, m_action_hintrect);
3872
// resize the dock or the pane
3873
if (m_action_part && m_action_part->type==wxDockUIPart::typeDockSizer)
3875
wxRect& rect = m_action_part->dock->rect;
3877
wxPoint new_pos(event.m_x - m_action_offset.x,
3878
event.m_y - m_action_offset.y);
3880
switch (m_action_part->dock->dock_direction)
3882
case wxAUI_DOCK_LEFT:
3883
m_action_part->dock->size = new_pos.x - rect.x;
3885
case wxAUI_DOCK_TOP:
3886
m_action_part->dock->size = new_pos.y - rect.y;
3888
case wxAUI_DOCK_RIGHT:
3889
m_action_part->dock->size = rect.x + rect.width -
3890
new_pos.x - m_action_part->rect.GetWidth();
3892
case wxAUI_DOCK_BOTTOM:
3893
m_action_part->dock->size = rect.y + rect.height -
3894
new_pos.y - m_action_part->rect.GetHeight();
3901
else if (m_action_part &&
3902
m_action_part->type == wxDockUIPart::typePaneSizer)
3904
wxDockInfo& dock = *m_action_part->dock;
3905
wxPaneInfo& pane = *m_action_part->pane;
3907
int total_proportion = 0;
3908
int dock_pixels = 0;
3909
int new_pixsize = 0;
3911
int caption_size = m_art->GetMetric(wxAUI_ART_CAPTION_SIZE);
3912
int pane_border_size = m_art->GetMetric(wxAUI_ART_PANE_BORDER_SIZE);
3913
int sash_size = m_art->GetMetric(wxAUI_ART_SASH_SIZE);
3915
wxPoint new_pos(event.m_x - m_action_offset.x,
3916
event.m_y - m_action_offset.y);
3918
// determine the pane rectangle by getting the pane part
3919
wxDockUIPart* pane_part = GetPanePart(pane.window);
3920
wxASSERT_MSG(pane_part,
3921
wxT("Pane border part not found -- shouldn't happen"));
3923
// determine the new pixel size that the user wants;
3924
// this will help us recalculate the pane's proportion
3925
if (dock.IsHorizontal())
3926
new_pixsize = new_pos.x - pane_part->rect.x;
3928
new_pixsize = new_pos.y - pane_part->rect.y;
3930
// determine the size of the dock, based on orientation
3931
if (dock.IsHorizontal())
3932
dock_pixels = dock.rect.GetWidth();
3934
dock_pixels = dock.rect.GetHeight();
3936
// determine the total proportion of all resizable panes,
3937
// and the total size of the dock minus the size of all
3939
int i, dock_pane_count = dock.panes.GetCount();
3940
int pane_position = -1;
3941
for (i = 0; i < dock_pane_count; ++i)
3943
wxPaneInfo& p = *dock.panes.Item(i);
3944
if (p.window == pane.window)
3947
// while we're at it, subtract the pane sash
3948
// width from the dock width, because this would
3949
// skew our proportion calculations
3951
dock_pixels -= sash_size;
3953
// also, the whole size (including decorations) of
3954
// all fixed panes must also be subtracted, because they
3955
// are not part of the proportion calculation
3958
if (dock.IsHorizontal())
3959
dock_pixels -= p.best_size.x;
3961
dock_pixels -= p.best_size.y;
3965
total_proportion += p.dock_proportion;
3969
// find a pane in our dock to 'steal' space from or to 'give'
3970
// space to -- this is essentially what is done when a pane is
3971
// resized; the pane should usually be the first non-fixed pane
3972
// to the right of the action pane
3973
int borrow_pane = -1;
3974
for (i = pane_position+1; i < dock_pane_count; ++i)
3976
wxPaneInfo& p = *dock.panes.Item(i);
3985
// demand that the pane being resized is found in this dock
3986
// (this assert really never should be raised)
3987
wxASSERT_MSG(pane_position != -1, wxT("Pane not found in dock"));
3989
// prevent division by zero
3990
if (dock_pixels == 0 || total_proportion == 0 || borrow_pane == -1)
3992
m_action = actionNone;
3996
// calculate the new proportion of the pane
3997
int new_proportion = (new_pixsize*total_proportion)/dock_pixels;
3999
// default minimum size
4002
// check against the pane's minimum size, if specified. please note
4003
// that this is not enough to ensure that the minimum size will
4004
// not be violated, because the whole frame might later be shrunk,
4005
// causing the size of the pane to violate it's minimum size
4006
if (pane.min_size.IsFullySpecified())
4010
if (pane.HasBorder())
4011
min_size += (pane_border_size*2);
4013
// calculate minimum size with decorations (border,caption)
4014
if (pane_part->orientation == wxVERTICAL)
4016
min_size += pane.min_size.y;
4017
if (pane.HasCaption())
4018
min_size += caption_size;
4022
min_size += pane.min_size.x;
4027
// for some reason, an arithmatic error somewhere is causing
4028
// the proportion calculations to always be off by 1 pixel;
4029
// for now we will add the 1 pixel on, but we really should
4030
// determine what's causing this.
4033
int min_proportion = (min_size*total_proportion)/dock_pixels;
4035
if (new_proportion < min_proportion)
4036
new_proportion = min_proportion;
4040
int prop_diff = new_proportion - pane.dock_proportion;
4042
// borrow the space from our neighbor pane to the
4043
// right or bottom (depending on orientation)
4044
dock.panes.Item(borrow_pane)->dock_proportion -= prop_diff;
4045
pane.dock_proportion = new_proportion;
4052
else if (m_action == actionClickButton)
4054
m_hover_button = NULL;
4055
m_frame->ReleaseMouse();
4056
UpdateButtonOnScreen(m_action_part, event);
4058
// make sure we're still over the item that was originally clicked
4059
if (m_action_part == HitTest(event.GetX(), event.GetY()))
4061
// fire button-click event
4062
wxFrameManagerEvent e(wxEVT_AUI_PANEBUTTON);
4063
e.SetPane(m_action_part->pane);
4064
e.SetButton(m_action_part->button->button_id);
4068
else if (m_action == actionClickCaption)
4070
m_frame->ReleaseMouse();
4072
else if (m_action == actionDragFloatingPane)
4074
m_frame->ReleaseMouse();
4076
else if (m_action == actionDragToolbarPane)
4078
m_frame->ReleaseMouse();
4080
wxPaneInfo& pane = GetPane(m_action_window);
4081
wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
4083
// save the new positions
4084
wxDockInfoPtrArray docks;
4085
FindDocks(m_docks, pane.dock_direction,
4086
pane.dock_layer, pane.dock_row, docks);
4087
if (docks.GetCount() == 1)
4089
wxDockInfo& dock = *docks.Item(0);
4091
wxArrayInt pane_positions, pane_sizes;
4092
GetPanePositionsAndSizes(dock, pane_positions, pane_sizes);
4094
int i, dock_pane_count = dock.panes.GetCount();
4095
for (i = 0; i < dock_pane_count; ++i)
4096
dock.panes.Item(i)->dock_pos = pane_positions[i];
4099
pane.state &= ~wxPaneInfo::actionPane;
4107
m_action = actionNone;
4108
m_last_mouse_move = wxPoint(); // see comment in OnMotion()
4112
void wxFrameManager::OnMotion(wxMouseEvent& event)
4114
// sometimes when Update() is called from inside this method,
4115
// a spurious mouse move event is generated; this check will make
4116
// sure that only real mouse moves will get anywhere in this method;
4117
// this appears to be a bug somewhere, and I don't know where the
4118
// mouse move event is being generated. only verified on MSW
4120
wxPoint mouse_pos = event.GetPosition();
4121
if (m_last_mouse_move == mouse_pos)
4123
m_last_mouse_move = mouse_pos;
4126
if (m_action == actionResize)
4128
wxPoint pos = m_action_part->rect.GetPosition();
4129
if (m_action_part->orientation == wxHORIZONTAL)
4130
pos.y = wxMax(0, event.m_y - m_action_offset.y);
4132
pos.x = wxMax(0, event.m_x - m_action_offset.x);
4134
wxRect rect(m_frame->ClientToScreen(pos),
4135
m_action_part->rect.GetSize());
4138
if (!m_action_hintrect.IsEmpty())
4139
DrawResizeHint(dc, m_action_hintrect);
4140
DrawResizeHint(dc, rect);
4141
m_action_hintrect = rect;
4143
else if (m_action == actionClickCaption)
4145
int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
4146
int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
4148
// caption has been clicked. we need to check if the mouse
4149
// is now being dragged. if it is, we need to change the
4150
// mouse action to 'drag'
4151
if (abs(event.m_x - m_action_start.x) > drag_x_threshold ||
4152
abs(event.m_y - m_action_start.y) > drag_y_threshold)
4154
wxPaneInfo* pane_info = m_action_part->pane;
4156
if (!pane_info->IsToolbar())
4158
if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) &&
4159
pane_info->IsFloatable())
4161
m_action = actionDragFloatingPane;
4163
// set initial float position
4164
wxPoint pt = m_frame->ClientToScreen(event.GetPosition());
4165
pane_info->floating_pos = wxPoint(pt.x - m_action_offset.x,
4166
pt.y - m_action_offset.y);
4171
m_action_window = pane_info->frame;
4173
// action offset is used here to make it feel "natural" to the user
4174
// to drag a docked pane and suddenly have it become a floating frame.
4175
// Sometimes, however, the offset where the user clicked on the docked
4176
// caption is bigger than the width of the floating frame itself, so
4177
// in that case we need to set the action offset to a sensible value
4178
wxSize frame_size = m_action_window->GetSize();
4179
if (frame_size.x <= m_action_offset.x)
4180
m_action_offset.x = 30;
4185
m_action = actionDragToolbarPane;
4186
m_action_window = pane_info->window;
4190
else if (m_action == actionDragFloatingPane)
4192
// m_action_window might have gone away already
4193
if ( m_action_window )
4195
wxPoint pt = m_frame->ClientToScreen(event.GetPosition());
4196
m_action_window->Move(pt.x - m_action_offset.x,
4197
pt.y - m_action_offset.y);
4200
else if (m_action == actionDragToolbarPane)
4202
wxPaneInfo& pane = GetPane(m_action_window);
4203
wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
4205
pane.state |= wxPaneInfo::actionPane;
4207
wxPoint pt = event.GetPosition();
4208
DoDrop(m_docks, m_panes, pane, pt, m_action_offset);
4210
// if DoDrop() decided to float the pane, set up
4211
// the floating pane's initial position
4212
if (pane.IsFloating())
4214
wxPoint pt = m_frame->ClientToScreen(event.GetPosition());
4215
pane.floating_pos = wxPoint(pt.x - m_action_offset.x,
4216
pt.y - m_action_offset.y);
4219
// this will do the actiual move operation;
4220
// in the case that the pane has been floated,
4221
// this call will create the floating pane
4222
// and do the reparenting
4225
// if the pane has been floated, change the mouse
4226
// action actionDragFloatingPane so that subsequent
4227
// EVT_MOTION() events will move the floating pane
4228
if (pane.IsFloating())
4230
pane.state &= ~wxPaneInfo::actionPane;
4231
m_action = actionDragFloatingPane;
4232
m_action_window = pane.frame;
4237
wxDockUIPart* part = HitTest(event.GetX(), event.GetY());
4238
if (part && part->type == wxDockUIPart::typePaneButton)
4240
if (part != m_hover_button)
4242
// make the old button normal
4244
UpdateButtonOnScreen(m_hover_button, event);
4246
// mouse is over a button, so repaint the
4247
// button in hover mode
4248
UpdateButtonOnScreen(part, event);
4249
m_hover_button = part;
4256
m_hover_button = NULL;
4267
void wxFrameManager::OnLeaveWindow(wxMouseEvent& event)
4271
m_hover_button = NULL;
4276
void wxFrameManager::OnChildFocus(wxChildFocusEvent& event)
4278
// when a child pane has it's focus set, we should change the
4279
// pane's active state to reflect this. (this is only true if
4280
// active panes are allowed by the owner)
4281
if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE)
4283
if (GetPane(event.GetWindow()).IsOk())
4285
SetActivePane(m_panes, event.GetWindow());
4292
// OnPaneButton() is an event handler that is called
4293
// when a pane button has been pressed.
4294
void wxFrameManager::OnPaneButton(wxFrameManagerEvent& event)
4296
wxPaneInfo& pane = *(event.pane);
4298
if (event.button == wxPaneInfo::buttonClose)
4303
else if (event.button == wxPaneInfo::buttonPin)
4305
if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) &&
4312
#endif // wxCHECK_VERSION