~ubuntu-branches/ubuntu/raring/codeblocks/raring-proposed

« back to all changes in this revision

Viewing changes to src/src/wxAUI/manager.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cosme Domínguez Díaz
  • Date: 2010-08-09 04:38:38 UTC
  • mfrom: (1.1.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20100809043838-a59ygguym4eg0jgw
Tags: 10.05-0ubuntu1
* New upstream release. Closes (LP: #322350)
 - Switch to dpkg-source 3.0 (quilt) format
 - Remove unneeded README.source
 - Add debian/get-source-orig script that removes all
   Windows prebuilt binaries
* Bump Standards-Version to 3.9.1
 - Stop shipping *.la files
* debian/control
 - Add cdbs package as Build-Depend
 - Add libbz2-dev and zlib1g-dev packages as
   Build-Depends (needed by libhelp_plugin.so)
 - Remove dpatch package of Build-Depends
 - Add codeblocks-contrib-debug package
 - Split architecture-independent files of codeblocks
   package in codeblocks-common package
* debian/rules
 - Switch to CDBS rules system
 - Add parallel build support
 - Add a call to debian/get-source-orig script
 - Use lzma compression (saves 23,5 MB of free space)
* debian/patches
 - Refresh 01_codeblocks_plugin_path
 - Add 02_no_Makefiles_in_debian_dir to remove any link
   in codeblocks build system to deleted Makefiles of debian directory
 - Drop 02_ftbfs_gcc44 and 03_ftbfs_glib221 (merged in upstream)
* debian/watch
 - Update to use the new host (berlios.de)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
///////////////////////////////////////////////////////////////////////////////
2
 
// Name:        manager.cpp
3
 
// Purpose:     wxaui: wx advanced user interface - docking window manager
4
 
// Author:      Benjamin I. Williams
5
 
// Modified by:
6
 
// Created:     2005-05-17
7
 
// RCS-ID:
8
 
// Copyright:   (C) Copyright 2005-2006, Kirix Corporation, All Rights Reserved
9
 
// Licence:     wxWindows Library Licence, Version 3.1
10
 
///////////////////////////////////////////////////////////////////////////////
11
 
 
12
 
#include <wx/wx.h>
13
 
#include <wx/minifram.h>
14
 
#include <wx/image.h>
15
 
#include "manager.h"
16
 
 
17
 
#if (!(wxCHECK_VERSION(2, 8, 0)))
18
 
 
19
 
// -- various array and event implementations --
20
 
 
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)
28
 
 
29
 
wxPaneInfo wxNullPaneInfo;
30
 
wxDockInfo wxNullDockInfo;
31
 
DEFINE_EVENT_TYPE(wxEVT_AUI_PANEBUTTON)
32
 
 
33
 
#ifdef __WXMAC__
34
 
    // a few defines to avoid nameclashes
35
 
    #define __MAC_OS_X_MEMORY_MANAGER_CLEAN__ 1
36
 
    #define __AIFF__
37
 
    #include "wx/mac/private.h"
38
 
#endif
39
 
 
40
 
 
41
 
// -- wxDefaultDockArt class implementation --
42
 
 
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()
49
 
 
50
 
 
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)
54
 
{
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));
59
 
}
60
 
 
61
 
static wxColor LightContrastColour(const wxColour& c)
62
 
{
63
 
    int amount = 120;
64
 
 
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)
68
 
        amount = 160;
69
 
 
70
 
    return StepColour(c, amount);
71
 
}
72
 
 
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)
77
 
{
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);
82
 
    return wxBitmap(img);
83
 
}
84
 
 
85
 
 
86
 
static void DrawGradientRectangle(wxDC& dc,
87
 
                                  const wxRect& rect,
88
 
                                  const wxColour& start_color,
89
 
                                  const wxColour& end_color,
90
 
                                  int direction)
91
 
{
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();
96
 
 
97
 
    if (direction == wxAUI_GRADIENT_VERTICAL)
98
 
        high = rect.GetHeight()-1;
99
 
         else
100
 
        high = rect.GetWidth()-1;
101
 
 
102
 
    for (int i = 0; i <= high; ++i)
103
 
    {
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;
107
 
 
108
 
        wxPen p(wxColor(r,g,b));
109
 
        dc.SetPen(p);
110
 
 
111
 
        if (direction == wxAUI_GRADIENT_VERTICAL)
112
 
            dc.DrawLine(rect.x, rect.y+i, rect.x+rect.width, rect.y+i);
113
 
             else
114
 
            dc.DrawLine(rect.x+i, rect.y, rect.x+i, rect.y+rect.height);
115
 
    }
116
 
 
117
 
}
118
 
 
119
 
wxDefaultDockArt::wxDefaultDockArt()
120
 
{
121
 
#ifdef __WXMAC__
122
 
    wxBrush toolbarbrush;
123
 
    toolbarbrush.MacSetTheme( kThemeBrushToolbarBackground );
124
 
    wxColor base_color = toolbarbrush.GetColour();
125
 
#else
126
 
    wxColor base_color = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
127
 
#endif
128
 
 
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);
134
 
 
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;
141
 
 
142
 
#ifdef __WXMAC__
143
 
    m_sash_brush = toolbarbrush;
144
 
    m_background_brush = toolbarbrush;
145
 
    m_gripper_brush = toolbarbrush;
146
 
#else
147
 
    m_sash_brush = wxBrush(base_color);
148
 
    m_background_brush = wxBrush(base_color);
149
 
    m_gripper_brush = wxBrush(base_color);
150
 
#endif
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;
155
 
 
156
 
#ifdef __WXMAC__
157
 
    m_caption_font = *wxSMALL_FONT;
158
 
#else
159
 
    m_caption_font = wxFont(8, wxDEFAULT, wxNORMAL, wxNORMAL, FALSE);
160
 
#endif
161
 
 
162
 
    // some built in bitmaps
163
 
#ifdef __WXMAC__
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 };
168
 
#else
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};
173
 
#endif
174
 
 
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};
179
 
 
180
 
#ifdef __WXMAC__
181
 
    m_inactive_close_bitmap = BitmapFromBits(close_bits, 16, 16, *wxWHITE);
182
 
#else
183
 
    m_inactive_close_bitmap = BitmapFromBits(close_bits, 16, 16, m_inactive_caption_text_colour);
184
 
#endif
185
 
    m_inactive_pin_bitmap = BitmapFromBits(pin_bits, 16, 16, m_inactive_caption_text_colour);
186
 
#ifdef __WXMAC__
187
 
    m_active_close_bitmap = BitmapFromBits(close_bits, 16, 16, *wxWHITE );
188
 
#else
189
 
    m_active_close_bitmap = BitmapFromBits(close_bits, 16, 16, m_active_caption_text_colour);
190
 
#endif
191
 
    m_active_pin_bitmap = BitmapFromBits(pin_bits, 16, 16, m_active_caption_text_colour);
192
 
 
193
 
    // default metric values
194
 
#ifdef __WXMAC__
195
 
    SInt32 height;
196
 
    GetThemeMetric( kThemeMetricSmallPaneSplitterHeight , &height );
197
 
    m_sash_size = height;
198
 
#else
199
 
    m_sash_size = 4;
200
 
#endif
201
 
    m_caption_size = 17;
202
 
    m_border_size = 1;
203
 
    m_button_size = 14;
204
 
    m_gripper_size = 9;
205
 
    m_gradient_type = wxAUI_GRADIENT_VERTICAL;
206
 
}
207
 
 
208
 
int wxDefaultDockArt::GetMetric(int id)
209
 
{
210
 
    switch (id)
211
 
    {
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;
219
 
    }
220
 
 
221
 
    return 0;
222
 
}
223
 
 
224
 
void wxDefaultDockArt::SetMetric(int id, int new_val)
225
 
{
226
 
    switch (id)
227
 
    {
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;
235
 
    }
236
 
}
237
 
 
238
 
wxColour wxDefaultDockArt::GetColour(int id)
239
 
{
240
 
    switch (id)
241
 
    {
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;
253
 
    }
254
 
 
255
 
    return wxColour();
256
 
}
257
 
 
258
 
void wxDefaultDockArt::SetColour(int id, const wxColor& colour)
259
 
{
260
 
    switch (id)
261
 
    {
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));
275
 
            break;
276
 
        default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
277
 
    }
278
 
}
279
 
 
280
 
void wxDefaultDockArt::SetFont(int id, const wxFont& font)
281
 
{
282
 
    if (id == wxAUI_ART_CAPTION_FONT)
283
 
        m_caption_font = font;
284
 
}
285
 
 
286
 
wxFont wxDefaultDockArt::GetFont(int id)
287
 
{
288
 
    if (id == wxAUI_ART_CAPTION_FONT)
289
 
        return m_caption_font;
290
 
    return wxNullFont;
291
 
}
292
 
 
293
 
void wxDefaultDockArt::DrawSash(wxDC& dc, int, const wxRect& rect)
294
 
{
295
 
#ifdef __WXMAC__
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() ;
300
 
#else
301
 
    Rect bounds ;
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 ) ;
306
 
#endif
307
 
 
308
 
    HIThemeSplitterDrawInfo drawInfo ;
309
 
    drawInfo.version = 0 ;
310
 
    drawInfo.state = kThemeStateActive ;
311
 
    drawInfo.adornment = kHIThemeSplitterAdornmentNone ;
312
 
    HIThemeDrawPaneSplitter( &splitterRect , &drawInfo , cgContext , kHIThemeOrientationNormal ) ;
313
 
 
314
 
#if wxMAC_USE_CORE_GRAPHICS
315
 
#else
316
 
    QDEndCGContext( (CGrafPtr) dc.m_macPort , &cgContext ) ;
317
 
#endif
318
 
 
319
 
#else
320
 
    dc.SetPen(*wxTRANSPARENT_PEN);
321
 
    dc.SetBrush(m_sash_brush);
322
 
    dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
323
 
#endif
324
 
}
325
 
 
326
 
 
327
 
void wxDefaultDockArt::DrawBackground(wxDC& dc, int, const wxRect& rect)
328
 
{
329
 
    dc.SetPen(*wxTRANSPARENT_PEN);
330
 
#ifdef __WXMAC__
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);
335
 
#endif
336
 
    dc.SetBrush(m_background_brush);
337
 
    dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
338
 
}
339
 
 
340
 
void wxDefaultDockArt::DrawBorder(wxDC& dc, const wxRect& _rect,
341
 
                                  wxPaneInfo& pane)
342
 
{
343
 
    dc.SetPen(m_border_pen);
344
 
    dc.SetBrush(*wxTRANSPARENT_BRUSH);
345
 
 
346
 
    wxRect rect = _rect;
347
 
    int i, border_width = GetMetric(wxAUI_ART_PANE_BORDER_SIZE);
348
 
 
349
 
    if (pane.IsToolbar())
350
 
    {
351
 
        for (i = 0; i < border_width; ++i)
352
 
        {
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);
361
 
            rect.Deflate(1);
362
 
        }
363
 
    }
364
 
     else
365
 
    {
366
 
        for (i = 0; i < border_width; ++i)
367
 
        {
368
 
            dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
369
 
            rect.Deflate(1);
370
 
        }
371
 
    }
372
 
}
373
 
 
374
 
 
375
 
void wxDefaultDockArt::DrawCaptionBackground(wxDC& dc, const wxRect& rect, bool active)
376
 
{
377
 
    if (m_gradient_type == wxAUI_GRADIENT_NONE)
378
 
    {
379
 
        if (active)
380
 
            dc.SetBrush(wxBrush(m_active_caption_colour));
381
 
             else
382
 
            dc.SetBrush(wxBrush(m_inactive_caption_colour));
383
 
 
384
 
        dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
385
 
    }
386
 
     else
387
 
    {
388
 
        if (active)
389
 
        {
390
 
            // on mac the gradients are expected to become darker from the top
391
 
#ifdef __WXMAC__
392
 
            DrawGradientRectangle(dc, rect,
393
 
                                 m_active_caption_gradient_colour,
394
 
                                 m_active_caption_colour,
395
 
                                 m_gradient_type);
396
 
#else
397
 
            DrawGradientRectangle(dc, rect,
398
 
                                 m_active_caption_colour,
399
 
                                 m_active_caption_gradient_colour,
400
 
                                 m_gradient_type);
401
 
#endif
402
 
        }
403
 
         else
404
 
        {
405
 
            // on mac the gradients are expected to become darker from the top
406
 
#ifdef __WXMAC__
407
 
            DrawGradientRectangle(dc, rect,
408
 
                                 m_inactive_caption_gradient_colour,
409
 
                                 m_inactive_caption_colour,
410
 
                                 m_gradient_type);
411
 
#else
412
 
            DrawGradientRectangle(dc, rect,
413
 
                                 m_inactive_caption_colour,
414
 
                                 m_inactive_caption_gradient_colour,
415
 
                                 m_gradient_type);
416
 
#endif
417
 
        }
418
 
    }
419
 
}
420
 
 
421
 
 
422
 
void wxDefaultDockArt::DrawCaption(wxDC& dc,
423
 
                                   const wxString& text,
424
 
                                   const wxRect& rect,
425
 
                                   wxPaneInfo& pane)
426
 
{
427
 
    dc.SetPen(*wxTRANSPARENT_PEN);
428
 
    dc.SetFont(m_caption_font);
429
 
 
430
 
    DrawCaptionBackground(dc, rect,
431
 
                          (pane.state & wxPaneInfo::optionActive)?true:false);
432
 
 
433
 
    if (pane.state & wxPaneInfo::optionActive)
434
 
        dc.SetTextForeground(m_active_caption_text_colour);
435
 
     else
436
 
        dc.SetTextForeground(m_inactive_caption_text_colour);
437
 
 
438
 
 
439
 
    wxCoord w,h;
440
 
    dc.GetTextExtent(wxT("ABCDEFHXfgkj"), &w, &h);
441
 
 
442
 
    dc.SetClippingRegion(rect);
443
 
    dc.DrawText(text, rect.x+3, rect.y+(rect.height/2)-(h/2)-1);
444
 
    dc.DestroyClippingRegion();
445
 
}
446
 
 
447
 
void wxDefaultDockArt::DrawGripper(wxDC& dc,
448
 
                                   const wxRect& rect,
449
 
                                   wxPaneInfo& pane)
450
 
{
451
 
    dc.SetPen(*wxTRANSPARENT_PEN);
452
 
    dc.SetBrush(m_gripper_brush);
453
 
 
454
 
    dc.DrawRectangle(rect.x, rect.y, rect.width,rect.height);
455
 
 
456
 
    if (!pane.HasGripperTop())
457
 
    {
458
 
        int y = 5;
459
 
        while (1)
460
 
        {
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);
470
 
 
471
 
            y += 4;
472
 
            if (y > rect.GetHeight()-5)
473
 
                break;
474
 
        }
475
 
    }
476
 
    else
477
 
    {
478
 
        int x = 5;
479
 
        while (1)
480
 
        {
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);
490
 
 
491
 
            x += 4;
492
 
            if (x > rect.GetWidth()-5)
493
 
                break;
494
 
        }
495
 
    }
496
 
}
497
 
 
498
 
void wxDefaultDockArt::DrawPaneButton(wxDC& dc,
499
 
                                      int button,
500
 
                                      int button_state,
501
 
                                      const wxRect& _rect,
502
 
                                      wxPaneInfo& pane)
503
 
{
504
 
    wxRect rect = _rect;
505
 
    if (!(&pane))
506
 
        return;
507
 
 
508
 
    if (button_state == wxAUI_BUTTON_STATE_PRESSED)
509
 
    {
510
 
        rect.x++;
511
 
        rect.y++;
512
 
    }
513
 
 
514
 
    if (button_state == wxAUI_BUTTON_STATE_HOVER ||
515
 
        button_state == wxAUI_BUTTON_STATE_PRESSED)
516
 
    {
517
 
        if (pane.state & wxPaneInfo::optionActive)
518
 
        {
519
 
            dc.SetBrush(wxBrush(StepColour(m_active_caption_colour, 120)));
520
 
            dc.SetPen(wxPen(StepColour(m_active_caption_colour, 70)));
521
 
        }
522
 
        else
523
 
        {
524
 
            dc.SetBrush(wxBrush(StepColour(m_inactive_caption_colour, 120)));
525
 
            dc.SetPen(wxPen(StepColour(m_inactive_caption_colour, 70)));
526
 
        }
527
 
 
528
 
        // draw the background behind the button
529
 
        dc.DrawRectangle(rect.x, rect.y, 15, 15);
530
 
    }
531
 
 
532
 
    wxBitmap bmp;
533
 
    switch (button)
534
 
    {
535
 
        default:
536
 
        case wxPaneInfo::buttonClose:
537
 
            if (pane.state & wxPaneInfo::optionActive)
538
 
                bmp = m_active_close_bitmap;
539
 
                 else
540
 
                bmp = m_inactive_close_bitmap;
541
 
            break;
542
 
        case wxPaneInfo::buttonPin:
543
 
            if (pane.state & wxPaneInfo::optionActive)
544
 
                bmp = m_active_pin_bitmap;
545
 
                 else
546
 
                bmp = m_inactive_pin_bitmap;
547
 
            break;
548
 
    }
549
 
 
550
 
    // draw the button itself
551
 
    dc.DrawBitmap(bmp, rect.x, rect.y, true);
552
 
}
553
 
 
554
 
 
555
 
// -- wxFloatingPane class implementation --
556
 
 
557
 
 
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
563
 
 
564
 
#if defined( __WXMSW__ ) || defined( __WXMAC__ )
565
 
#define wxFloatingPaneBaseClass wxMiniFrame
566
 
#else
567
 
#define wxFloatingPaneBaseClass wxFrame
568
 
#endif
569
 
 
570
 
#ifdef __WXGTK__
571
 
extern "C" { void* gdk_window_get_pointer(void*, int*, int*, unsigned int*); }
572
 
#endif
573
 
 
574
 
class wxFloatingPane : public wxFloatingPaneBaseClass
575
 
{
576
 
public:
577
 
    wxFloatingPane(wxWindow* parent,
578
 
                   wxFrameManager* owner_mgr,
579
 
                   wxWindowID id = -1,
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)
586
 
    {
587
 
        m_owner_mgr = owner_mgr;
588
 
        m_moving = false;
589
 
        m_last_rect = wxRect();
590
 
        m_mgr.SetFrame(this);
591
 
        SetExtraStyle(wxWS_EX_PROCESS_IDLE);
592
 
    }
593
 
 
594
 
    ~wxFloatingPane()
595
 
    {
596
 
        m_mgr.UnInit();
597
 
    }
598
 
 
599
 
    void SetPaneWindow(const wxPaneInfo& pane)
600
 
    {
601
 
        m_pane_window = pane.window;
602
 
        m_pane_window->Reparent(this);
603
 
 
604
 
        wxPaneInfo contained_pane = pane;
605
 
        contained_pane.Dock().Center().Show().
606
 
                       CaptionVisible(false).
607
 
                       PaneBorder(false).
608
 
                       Layer(0).Row(0).Position(0);
609
 
 
610
 
        m_mgr.AddPane(m_pane_window, contained_pane);
611
 
        m_mgr.Update();
612
 
 
613
 
        if (pane.min_size.IsFullySpecified())
614
 
        {
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);
620
 
            SetSize(tmp);
621
 
        }
622
 
 
623
 
        SetTitle(pane.caption);
624
 
 
625
 
        if (contained_pane.IsFixed())
626
 
            SetWindowStyle(GetWindowStyle() & ~wxRESIZE_BORDER);
627
 
 
628
 
        if (pane.floating_size != wxDefaultSize)
629
 
        {
630
 
            SetSize(pane.floating_size);
631
 
        }
632
 
         else
633
 
        {
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())
640
 
            {
641
 
                if (pane.HasGripperTop())
642
 
                    size.y += m_owner_mgr->m_art->GetMetric(wxAUI_ART_GRIPPER_SIZE);
643
 
                else
644
 
                    size.x += m_owner_mgr->m_art->GetMetric(wxAUI_ART_GRIPPER_SIZE);
645
 
            }
646
 
 
647
 
            SetClientSize(size);
648
 
        }
649
 
    }
650
 
 
651
 
private:
652
 
 
653
 
    void OnSize(wxSizeEvent& event)
654
 
    {
655
 
        m_owner_mgr->OnFloatingPaneResized(m_pane_window, event.GetSize());
656
 
    }
657
 
 
658
 
    void OnClose(wxCloseEvent& event)
659
 
    {
660
 
        m_owner_mgr->OnFloatingPaneClosed(m_pane_window);
661
 
        Destroy();
662
 
    }
663
 
 
664
 
    void OnMoveEvent(wxMoveEvent& event)
665
 
    {
666
 
        wxRect win_rect = GetRect();
667
 
 
668
 
        // skip the first move event
669
 
        if (m_last_rect.IsEmpty())
670
 
        {
671
 
            m_last_rect = win_rect;
672
 
            return;
673
 
        }
674
 
 
675
 
        // prevent frame redocking during resize
676
 
        if (m_last_rect.GetSize() != win_rect.GetSize())
677
 
        {
678
 
            m_last_rect = win_rect;
679
 
            return;
680
 
        }
681
 
 
682
 
        m_last_rect = win_rect;
683
 
 
684
 
        if (!isMouseDown())
685
 
            return;
686
 
 
687
 
        if (!m_moving)
688
 
        {
689
 
            OnMoveStart();
690
 
            m_moving = true;
691
 
        }
692
 
 
693
 
        OnMoving(event.GetRect());
694
 
    }
695
 
 
696
 
    void OnIdle(wxIdleEvent& event)
697
 
    {
698
 
        if (m_moving)
699
 
        {
700
 
            if (!isMouseDown())
701
 
            {
702
 
                m_moving = false;
703
 
                OnMoveFinished();
704
 
            }
705
 
             else
706
 
            {
707
 
                event.RequestMore();
708
 
            }
709
 
        }
710
 
    }
711
 
 
712
 
    void OnMoveStart()
713
 
    {
714
 
        // notify the owner manager that the pane has started to move
715
 
        m_owner_mgr->OnFloatingPaneMoveStart(m_pane_window);
716
 
    }
717
 
 
718
 
    void OnMoving(const wxRect& window_rect)
719
 
    {
720
 
        // notify the owner manager that the pane is moving
721
 
        m_owner_mgr->OnFloatingPaneMoving(m_pane_window);
722
 
    }
723
 
 
724
 
    void OnMoveFinished()
725
 
    {
726
 
        // notify the owner manager that the pane has finished moving
727
 
        m_owner_mgr->OnFloatingPaneMoved(m_pane_window);
728
 
    }
729
 
 
730
 
    void OnActivate(wxActivateEvent& event)
731
 
    {
732
 
        if (event.GetActive())
733
 
        {
734
 
            m_owner_mgr->OnFloatingPaneActivated(m_pane_window);
735
 
        }
736
 
    }
737
 
 
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()
743
 
    {
744
 
        #ifdef __WXMSW__
745
 
        return (GetKeyState( VK_LBUTTON ) & (1<<15)) ? true : false;
746
 
        #endif
747
 
 
748
 
        #ifdef __WXGTK__
749
 
        int x, y;
750
 
        unsigned int m;
751
 
        gdk_window_get_pointer(NULL, &x, &y, &m);
752
 
        return (m & 0x100) ? true : false;
753
 
        //return (m & 0x1F00) ? true : false;
754
 
        #endif
755
 
 
756
 
        #ifdef __WXMAC__
757
 
        return GetCurrentEventButtonState() & 0x01 ;
758
 
        #endif
759
 
    }
760
 
 
761
 
private:
762
 
    wxWindow* m_pane_window;    // pane window being managed
763
 
    bool m_moving;
764
 
    wxRect m_last_rect;
765
 
    wxSize m_last_size;
766
 
 
767
 
    wxFrameManager* m_owner_mgr;
768
 
    wxFrameManager m_mgr;
769
 
 
770
 
    DECLARE_EVENT_TABLE()
771
 
};
772
 
 
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)
780
 
END_EVENT_TABLE()
781
 
 
782
 
 
783
 
class wxPseudoTransparentFrame : public wxFrame
784
 
{
785
 
public:
786
 
    wxPseudoTransparentFrame(wxWindow* parent = NULL,
787
 
                wxWindowID id = -1,
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)
794
 
    {
795
 
        SetBackgroundStyle(wxBG_STYLE_CUSTOM);
796
 
        m_Amount=0;
797
 
        m_MaxWidth=0;
798
 
        m_MaxHeight=0;
799
 
#ifdef __WXGTK
800
 
        m_CanSetShape = false; // have to wait for window create event on GTK
801
 
#else
802
 
        m_CanSetShape = true;
803
 
#endif
804
 
        m_Region = wxRegion(0, 0, 0, 0);
805
 
        SetTransparency(0);
806
 
    }
807
 
 
808
 
    void SetTransparency(int amount)
809
 
    {
810
 
        if (m_CanSetShape)
811
 
        {
812
 
            int w=100; // some defaults
813
 
            int h=100;
814
 
            GetClientSize(&w, &h);
815
 
 
816
 
            {
817
 
                m_MaxWidth=w;
818
 
                m_MaxHeight=h;
819
 
                m_Amount = amount;
820
 
                m_Region.Clear();
821
 
//                              m_Region.Union(0, 0, 1, m_MaxWidth);
822
 
                if (m_Amount)
823
 
                {
824
 
                    for (int y=0; y<m_MaxHeight; y++)
825
 
                    {
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);
830
 
                    }
831
 
                }
832
 
                SetShape(m_Region);
833
 
                Refresh();
834
 
            }
835
 
        }
836
 
    }
837
 
 
838
 
    void OnPaint(wxPaintEvent & event)
839
 
    {
840
 
        wxPaintDC dc(this);
841
 
 
842
 
        if (m_Region.IsEmpty())
843
 
                     return;
844
 
 
845
 
#ifdef __WXMAC__
846
 
        dc.SetBrush(wxColour(128, 192, 255));
847
 
#else
848
 
        dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION));
849
 
#endif
850
 
        dc.SetPen(*wxTRANSPARENT_PEN);
851
 
 
852
 
        wxRegionIterator upd(GetUpdateRegion()); // get the update rect list
853
 
 
854
 
        while (upd)
855
 
        {
856
 
            wxRect rect(upd.GetRect());
857
 
            dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
858
 
 
859
 
            upd++;
860
 
        }
861
 
    }
862
 
 
863
 
#ifdef __WXGTK__
864
 
    void OnWindowCreate(wxWindowCreateEvent& WXUNUSED(event)) {m_CanSetShape=true; SetTransparency(0);}
865
 
#endif
866
 
 
867
 
    void OnSize(wxSizeEvent& event)
868
 
    {
869
 
        SetTransparency(m_Amount);
870
 
        m_Region.Intersect(0, 0, event.GetSize().GetWidth(),
871
 
                           event.GetSize().GetHeight());
872
 
        SetShape(m_Region);
873
 
        Refresh();
874
 
        event.Skip();
875
 
    }
876
 
 
877
 
private:
878
 
    int m_Amount;
879
 
    int m_MaxWidth;
880
 
    int m_MaxHeight;
881
 
    bool m_CanSetShape;
882
 
 
883
 
    wxRegion m_Region;
884
 
 
885
 
    DECLARE_DYNAMIC_CLASS(wxPseudoTransparentFrame);
886
 
    DECLARE_EVENT_TABLE();
887
 
};
888
 
 
889
 
 
890
 
IMPLEMENT_DYNAMIC_CLASS( wxPseudoTransparentFrame, wxFrame )
891
 
 
892
 
BEGIN_EVENT_TABLE(wxPseudoTransparentFrame, wxFrame)
893
 
    EVT_PAINT(wxPseudoTransparentFrame::OnPaint)
894
 
    EVT_SIZE(wxPseudoTransparentFrame::OnSize)
895
 
#ifdef __WXGTK__
896
 
    EVT_WINDOW_CREATE(wxPseudoTransparentFrame::OnWindowCreate)
897
 
#endif
898
 
END_EVENT_TABLE()
899
 
 
900
 
 
901
 
// -- static utility functions --
902
 
 
903
 
static wxBitmap wxPaneCreateStippleBitmap()
904
 
{
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);
908
 
}
909
 
 
910
 
static void DrawResizeHint(wxDC& dc, const wxRect& rect)
911
 
{
912
 
    wxBitmap stipple = wxPaneCreateStippleBitmap();
913
 
    wxBrush brush(stipple);
914
 
    dc.SetBrush(brush);
915
 
    dc.SetPen(*wxTRANSPARENT_PEN);
916
 
 
917
 
    dc.SetLogicalFunction(wxXOR);
918
 
    dc.DrawRectangle(rect);
919
 
}
920
 
 
921
 
 
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)
925
 
{
926
 
    bool realtransparency = !(wnd && wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame)));
927
 
    if (realtransparency)
928
 
    {
929
 
#ifdef __WXMSW__
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();
936
 
 
937
 
        if (!h)
938
 
            h = LoadLibrary(_T("user32"));
939
 
 
940
 
        if (!pSetLayeredWindowAttributes)
941
 
        {
942
 
            pSetLayeredWindowAttributes =
943
 
            (PSETLAYEREDWINDOWATTR)GetProcAddress(h,"SetLayeredWindowAttributes");
944
 
        }
945
 
 
946
 
        if (pSetLayeredWindowAttributes == NULL)
947
 
            return;
948
 
 
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*/);
952
 
 
953
 
        pSetLayeredWindowAttributes(hwnd, 0, amount, 2 /*LWA_ALPHA*/);
954
 
#endif
955
 
    }
956
 
    else
957
 
    {
958
 
        if (wnd)
959
 
        {
960
 
            ((wxPseudoTransparentFrame *)wnd)->SetTransparency(amount);
961
 
            wnd->Refresh();
962
 
        }
963
 
    }
964
 
}
965
 
 
966
 
 
967
 
 
968
 
 
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
973
 
 
974
 
static void CopyDocksAndPanes(wxDockInfoArray& dest_docks,
975
 
                            wxPaneInfoArray& dest_panes,
976
 
                            const wxDockInfoArray& src_docks,
977
 
                            const wxPaneInfoArray& src_panes)
978
 
{
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)
983
 
    {
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);
989
 
    }
990
 
}
991
 
 
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)
995
 
{
996
 
    int i, dock_count, max_layer = 0;
997
 
    for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
998
 
    {
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;
1003
 
    }
1004
 
    return max_layer;
1005
 
}
1006
 
 
1007
 
 
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)
1011
 
{
1012
 
    int i, pane_count, max_row = 0;
1013
 
    for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
1014
 
    {
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;
1020
 
    }
1021
 
    return max_row;
1022
 
}
1023
 
 
1024
 
 
1025
 
 
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,
1029
 
                              int dock_direction,
1030
 
                              int dock_layer)
1031
 
{
1032
 
    int i, pane_count;
1033
 
    for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
1034
 
    {
1035
 
        wxPaneInfo& pane = panes.Item(i);
1036
 
        if (!pane.IsFloating() &&
1037
 
            pane.dock_direction == dock_direction &&
1038
 
            pane.dock_layer >= dock_layer)
1039
 
                pane.dock_layer++;
1040
 
    }
1041
 
}
1042
 
 
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,
1046
 
                            int dock_direction,
1047
 
                            int dock_layer,
1048
 
                            int dock_row)
1049
 
{
1050
 
    int i, pane_count;
1051
 
    for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
1052
 
    {
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)
1058
 
                pane.dock_row++;
1059
 
    }
1060
 
}
1061
 
 
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,
1065
 
                         int dock_direction,
1066
 
                         int dock_layer,
1067
 
                         int dock_row,
1068
 
                         int dock_pos)
1069
 
{
1070
 
    int i, pane_count;
1071
 
    for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
1072
 
    {
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)
1079
 
                pane.dock_pos++;
1080
 
    }
1081
 
}
1082
 
 
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,
1087
 
                      int dock_direction,
1088
 
                      int dock_layer,
1089
 
                      int dock_row,
1090
 
                      wxDockInfoPtrArray& arr)
1091
 
{
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;
1098
 
 
1099
 
    // discover the maximum dock layer and the max row
1100
 
    for (i = 0; i < dock_count; ++i)
1101
 
    {
1102
 
        max_row = wxMax(max_row, docks.Item(i).dock_row);
1103
 
        max_layer = wxMax(max_layer, docks.Item(i).dock_layer);
1104
 
    }
1105
 
 
1106
 
    // if no dock layer was specified, search all dock layers
1107
 
    if (dock_layer == -1)
1108
 
    {
1109
 
        begin_layer = 0;
1110
 
        end_layer = max_layer;
1111
 
    }
1112
 
 
1113
 
    // if no dock row was specified, search all dock row
1114
 
    if (dock_row == -1)
1115
 
    {
1116
 
        begin_row = 0;
1117
 
        end_row = max_row;
1118
 
    }
1119
 
 
1120
 
    arr.Clear();
1121
 
 
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)
1125
 
            {
1126
 
                wxDockInfo& d = docks.Item(i);
1127
 
                if (dock_direction == -1 || dock_direction == d.dock_direction)
1128
 
                {
1129
 
                    if (d.dock_layer == layer && d.dock_row == row)
1130
 
                        arr.Add(&d);
1131
 
                }
1132
 
            }
1133
 
}
1134
 
 
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)
1138
 
{
1139
 
    int i, count = dock.panes.GetCount();
1140
 
    for (i = 0; i < count; ++i)
1141
 
    {
1142
 
        wxPaneInfo* p = dock.panes.Item(i);
1143
 
        if (p->window == window)
1144
 
            return p;
1145
 
    }
1146
 
    return NULL;
1147
 
}
1148
 
 
1149
 
// RemovePaneFromDocks() removes a pane window from all docks
1150
 
// with a possible exception specified by parameter "except"
1151
 
static void RemovePaneFromDocks(wxDockInfoArray& docks,
1152
 
                                wxPaneInfo& pane,
1153
 
                                wxDockInfo* except = NULL)
1154
 
{
1155
 
    int i, dock_count;
1156
 
    for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
1157
 
    {
1158
 
        wxDockInfo& d = docks.Item(i);
1159
 
        if (&d == except)
1160
 
            continue;
1161
 
        wxPaneInfo* pi = FindPaneInDock(d, pane.window);
1162
 
        if (pi)
1163
 
            d.panes.Remove(pi);
1164
 
    }
1165
 
}
1166
 
 
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)
1171
 
{
1172
 
    int i, dock_count, j, pane_count;
1173
 
    for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
1174
 
    {
1175
 
        wxDockInfo& dock = *docks.Item(i);
1176
 
        dock.dock_row = i;
1177
 
        for (j = 0, pane_count = dock.panes.GetCount(); j < pane_count; ++j)
1178
 
            dock.panes.Item(j)->dock_row = i;
1179
 
    }
1180
 
}
1181
 
 
1182
 
 
1183
 
 
1184
 
static void SetActivePane(wxPaneInfoArray& panes, wxWindow* active_pane)
1185
 
{
1186
 
    int i, pane_count;
1187
 
    for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
1188
 
    {
1189
 
        wxPaneInfo& pane = panes.Item(i);
1190
 
        pane.state &= ~wxPaneInfo::optionActive;
1191
 
        if (pane.window == active_pane)
1192
 
            pane.state |= wxPaneInfo::optionActive;
1193
 
    }
1194
 
}
1195
 
 
1196
 
 
1197
 
// this function is used to sort panes by dock position
1198
 
static int PaneSortFunc(wxPaneInfo** p1, wxPaneInfo** p2)
1199
 
{
1200
 
    return ((*p1)->dock_pos < (*p2)->dock_pos) ? -1 : 1;
1201
 
}
1202
 
 
1203
 
 
1204
 
// -- wxFrameManager class implementation --
1205
 
 
1206
 
 
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)
1219
 
END_EVENT_TABLE()
1220
 
 
1221
 
 
1222
 
wxFrameManager::wxFrameManager(wxFrame* frame, unsigned int flags)
1223
 
{
1224
 
    m_action = actionNone;
1225
 
    m_last_mouse_move = wxPoint();
1226
 
    m_hover_button = NULL;
1227
 
    m_art = new wxDefaultDockArt;
1228
 
    m_hint_wnd = NULL;
1229
 
    m_flags = flags;
1230
 
 
1231
 
    if (frame)
1232
 
    {
1233
 
        SetFrame(frame);
1234
 
    }
1235
 
}
1236
 
 
1237
 
wxFrameManager::~wxFrameManager()
1238
 
{
1239
 
    delete m_art;
1240
 
}
1241
 
 
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().
1246
 
//
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.
1250
 
 
1251
 
wxPaneInfo& wxFrameManager::GetPane(wxWindow* window)
1252
 
{
1253
 
    int i, pane_count;
1254
 
    for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i)
1255
 
    {
1256
 
        wxPaneInfo& p = m_panes.Item(i);
1257
 
        if (p.window == window)
1258
 
            return p;
1259
 
    }
1260
 
    return wxNullPaneInfo;
1261
 
}
1262
 
 
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)
1266
 
{
1267
 
    int i, pane_count;
1268
 
    for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i)
1269
 
    {
1270
 
        wxPaneInfo& p = m_panes.Item(i);
1271
 
        if (p.name == name)
1272
 
            return p;
1273
 
    }
1274
 
    return wxNullPaneInfo;
1275
 
}
1276
 
 
1277
 
// GetAllPanes() returns a reference to all the pane info structures
1278
 
wxPaneInfoArray& wxFrameManager::GetAllPanes()
1279
 
{
1280
 
    return m_panes;
1281
 
}
1282
 
 
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)
1287
 
{
1288
 
    wxDockUIPart* result = NULL;
1289
 
 
1290
 
    int i, part_count;
1291
 
    for (i = 0, part_count = m_uiparts.GetCount(); i < part_count; ++i)
1292
 
    {
1293
 
        wxDockUIPart* item = &m_uiparts.Item(i);
1294
 
 
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)
1300
 
            continue;
1301
 
 
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)
1307
 
            continue;
1308
 
 
1309
 
        // if the point is inside the rectangle, we have a hit
1310
 
        if (item->rect.Inside(x,y))
1311
 
            result = item;
1312
 
    }
1313
 
 
1314
 
    return result;
1315
 
}
1316
 
 
1317
 
 
1318
 
// SetFlags() and GetFlags() allow the owner to set various
1319
 
// options which are global to wxFrameManager
1320
 
void wxFrameManager::SetFlags(unsigned int flags)
1321
 
{
1322
 
    m_flags = flags;
1323
 
}
1324
 
 
1325
 
unsigned int wxFrameManager::GetFlags() const
1326
 
{
1327
 
    return m_flags;
1328
 
}
1329
 
 
1330
 
 
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)
1335
 
{
1336
 
    wxASSERT_MSG(frame, wxT("specified frame must be non-NULL"));
1337
 
 
1338
 
    m_frame = frame;
1339
 
    m_frame->PushEventHandler(this);
1340
 
 
1341
 
#if wxUSE_MDI
1342
 
    // if the owner is going to manage an MDI parent frame,
1343
 
    // we need to add the MDI client window as the default
1344
 
    // center pane
1345
 
 
1346
 
    if (frame->IsKindOf(CLASSINFO(wxMDIParentFrame)))
1347
 
    {
1348
 
        wxMDIParentFrame* mdi_frame = (wxMDIParentFrame*)frame;
1349
 
        wxMDIClientWindow* client_window = mdi_frame->GetClientWindow();
1350
 
 
1351
 
        wxASSERT_MSG(client_window, wxT("Client window is NULL!"));
1352
 
 
1353
 
        AddPane(client_window,
1354
 
                wxPaneInfo().Name(wxT("mdiclient")).
1355
 
                CenterPane().PaneBorder(false));
1356
 
    }
1357
 
#endif
1358
 
}
1359
 
 
1360
 
 
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()
1365
 
{
1366
 
    if (m_frame)
1367
 
        m_frame->RemoveEventHandler(this);
1368
 
}
1369
 
 
1370
 
// GetFrame() returns the frame pointer being managed by wxFrameManager
1371
 
wxFrame* wxFrameManager::GetFrame() const
1372
 
{
1373
 
    return m_frame;
1374
 
}
1375
 
 
1376
 
wxDockArt* wxFrameManager::GetArtProvider() const
1377
 
{
1378
 
    return m_art;
1379
 
}
1380
 
 
1381
 
void wxFrameManager::ProcessMgrEvent(wxFrameManagerEvent& event)
1382
 
{
1383
 
    // first, give the owner frame a chance to override
1384
 
    if (m_frame)
1385
 
    {
1386
 
        if (m_frame->ProcessEvent(event))
1387
 
            return;
1388
 
    }
1389
 
 
1390
 
    ProcessEvent(event);
1391
 
}
1392
 
 
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)
1397
 
{
1398
 
    // delete the last art provider, if any
1399
 
    delete m_art;
1400
 
 
1401
 
    // assign the new art provider
1402
 
    m_art = art_provider;
1403
 
}
1404
 
 
1405
 
bool wxFrameManager::AddPane(wxWindow* window, const wxPaneInfo& pane_info)
1406
 
{
1407
 
    // check if the pane has a valid window
1408
 
    if (!window)
1409
 
        return false;
1410
 
 
1411
 
    // check if the pane already exists
1412
 
    if (GetPane(pane_info.window).IsOk())
1413
 
        return false;
1414
 
 
1415
 
    m_panes.Add(pane_info);
1416
 
 
1417
 
    wxPaneInfo& pinfo = m_panes.Last();
1418
 
 
1419
 
    // set the pane window
1420
 
    pinfo.window = window;
1421
 
 
1422
 
    // if the pane's name identifier is blank, create a random string
1423
 
    if (pinfo.name.IsEmpty())
1424
 
    {
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());
1429
 
    }
1430
 
 
1431
 
    // set initial proportion (if not already set)
1432
 
    if (pinfo.dock_proportion == 0)
1433
 
        pinfo.dock_proportion = 100000;
1434
 
 
1435
 
    if (pinfo.HasCloseButton() &&
1436
 
        pinfo.buttons.size() == 0)
1437
 
    {
1438
 
        wxPaneButton button;
1439
 
        button.button_id = wxPaneInfo::buttonClose;
1440
 
        pinfo.buttons.Add(button);
1441
 
    }
1442
 
 
1443
 
    if (pinfo.best_size == wxDefaultSize &&
1444
 
        pinfo.window)
1445
 
    {
1446
 
        pinfo.best_size = pinfo.window->GetClientSize();
1447
 
 
1448
 
        if (pinfo.window->IsKindOf(CLASSINFO(wxToolBar)))
1449
 
        {
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();
1454
 
 
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
1459
 
            // correct?
1460
 
            pinfo.best_size.y++;
1461
 
        }
1462
 
 
1463
 
        if (pinfo.min_size != wxDefaultSize)
1464
 
        {
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;
1469
 
        }
1470
 
    }
1471
 
 
1472
 
    return true;
1473
 
}
1474
 
 
1475
 
bool wxFrameManager::AddPane(wxWindow* window,
1476
 
                             int direction,
1477
 
                             const wxString& caption)
1478
 
{
1479
 
    wxPaneInfo pinfo;
1480
 
    pinfo.Caption(caption);
1481
 
    switch (direction)
1482
 
    {
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;
1488
 
    }
1489
 
    return AddPane(window, pinfo);
1490
 
}
1491
 
 
1492
 
bool wxFrameManager::InsertPane(wxWindow* window, const wxPaneInfo& pane_info,
1493
 
                                int insert_level)
1494
 
{
1495
 
    // shift the panes around, depending on the insert level
1496
 
    switch (insert_level)
1497
 
    {
1498
 
        case wxAUI_INSERT_PANE:
1499
 
            DoInsertPane(m_panes,
1500
 
                 pane_info.dock_direction,
1501
 
                 pane_info.dock_layer,
1502
 
                 pane_info.dock_row,
1503
 
                 pane_info.dock_pos);
1504
 
            break;
1505
 
        case wxAUI_INSERT_ROW:
1506
 
            DoInsertDockRow(m_panes,
1507
 
                 pane_info.dock_direction,
1508
 
                 pane_info.dock_layer,
1509
 
                 pane_info.dock_row);
1510
 
            break;
1511
 
        case wxAUI_INSERT_DOCK:
1512
 
            DoInsertDockLayer(m_panes,
1513
 
                 pane_info.dock_direction,
1514
 
                 pane_info.dock_layer);
1515
 
            break;
1516
 
    }
1517
 
 
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())
1522
 
    {
1523
 
        return AddPane(window, pane_info);
1524
 
    }
1525
 
     else
1526
 
    {
1527
 
        if (pane_info.IsFloating())
1528
 
        {
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);
1534
 
        }
1535
 
         else
1536
 
        {
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);
1541
 
        }
1542
 
    }
1543
 
 
1544
 
    return true;
1545
 
}
1546
 
 
1547
 
 
1548
 
bool wxFrameManager::DetachPane(wxWindow* window)
1549
 
{
1550
 
    int i, count;
1551
 
    for (i = 0, count = m_panes.GetCount(); i < count; ++i)
1552
 
    {
1553
 
        wxPaneInfo& p = m_panes.Item(i);
1554
 
        if (p.window == window)
1555
 
        {
1556
 
            if (p.frame)
1557
 
            {
1558
 
                // we have a floating frame which is being detached. We need to
1559
 
                // reparent it to m_frame and destroy the floating frame
1560
 
 
1561
 
                // reduce flicker
1562
 
                p.window->SetSize(1,1);
1563
 
                p.frame->Show(false);
1564
 
 
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;
1571
 
                p.frame->Destroy();
1572
 
                p.frame = NULL;
1573
 
            }
1574
 
            m_panes.RemoveAt(i);
1575
 
            return true;
1576
 
        }
1577
 
    }
1578
 
    return false;
1579
 
}
1580
 
 
1581
 
 
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)
1586
 
{
1587
 
    wxString result;
1588
 
    result.Alloc(s.Length());
1589
 
    const wxChar* ch = s.c_str();
1590
 
    while (*ch)
1591
 
    {
1592
 
        if (*ch == wxT(';') || *ch == wxT('|'))
1593
 
            result += wxT('\\');
1594
 
        result += *ch;
1595
 
        ++ch;
1596
 
    }
1597
 
    return result;
1598
 
}
1599
 
 
1600
 
 
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
1605
 
 
1606
 
wxString wxFrameManager::SavePerspective()
1607
 
{
1608
 
    wxString result;
1609
 
    result.Alloc(500);
1610
 
    result = wxT("layout1|");
1611
 
 
1612
 
    int pane_i, pane_count = m_panes.GetCount();
1613
 
    for (pane_i = 0; pane_i < pane_count; ++pane_i)
1614
 
    {
1615
 
        wxPaneInfo& pane = m_panes.Item(pane_i);
1616
 
 
1617
 
        result += wxT("name=");
1618
 
        result += EscapeDelimiters(pane.name);
1619
 
        result += wxT(";");
1620
 
 
1621
 
        result += wxT("caption=");
1622
 
        result += EscapeDelimiters(pane.caption);
1623
 
        result += wxT(";");
1624
 
 
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);
1641
 
        result += wxT("|");
1642
 
    }
1643
 
 
1644
 
    int dock_i, dock_count = m_docks.GetCount();
1645
 
    for (dock_i = 0; dock_i < dock_count; ++dock_i)
1646
 
    {
1647
 
        wxDockInfo& dock = m_docks.Item(dock_i);
1648
 
 
1649
 
        result += wxString::Format(wxT("dock_size(%d,%d,%d)=%d|"),
1650
 
                                   dock.dock_direction, dock.dock_layer,
1651
 
                                   dock.dock_row, dock.size);
1652
 
    }
1653
 
 
1654
 
    return result;
1655
 
}
1656
 
 
1657
 
// LoadPerspective() loads a layout which was saved with SavePerspective()
1658
 
// If the "update" flag parameter is true, the GUI will immediately be updated
1659
 
 
1660
 
bool wxFrameManager::LoadPerspective(const wxString& layout, bool update)
1661
 
{
1662
 
    wxString input = layout;
1663
 
    wxString part;
1664
 
 
1665
 
    // check layout string version
1666
 
    part = input.BeforeFirst(wxT('|'));
1667
 
    input = input.AfterFirst(wxT('|'));
1668
 
    part.Trim(true);
1669
 
    part.Trim(false);
1670
 
    if (part != wxT("layout1"))
1671
 
        return false;
1672
 
 
1673
 
 
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();
1678
 
 
1679
 
    // clear out the dock array; this will be reconstructed
1680
 
    m_docks.Clear();
1681
 
 
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"));
1686
 
 
1687
 
    while (1)
1688
 
    {
1689
 
        wxPaneInfo pane;
1690
 
 
1691
 
        wxString pane_part = input.BeforeFirst(wxT('|'));
1692
 
        input = input.AfterFirst(wxT('|'));
1693
 
        pane_part.Trim(true);
1694
 
 
1695
 
        // if the string is empty, we're done parsing
1696
 
        if (pane_part.IsEmpty())
1697
 
            break;
1698
 
 
1699
 
 
1700
 
        if (pane_part.Left(9) == wxT("dock_size"))
1701
 
        {
1702
 
            wxString val_name = pane_part.BeforeFirst(wxT('='));
1703
 
            wxString value = pane_part.AfterFirst(wxT('='));
1704
 
 
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);
1713
 
 
1714
 
            wxDockInfo dock;
1715
 
            dock.dock_direction = dir;
1716
 
            dock.dock_layer = layer;
1717
 
            dock.dock_row = row;
1718
 
            dock.size = size;
1719
 
            m_docks.Add(dock);
1720
 
            continue;
1721
 
        }
1722
 
 
1723
 
        while (1)
1724
 
        {
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);
1732
 
            value.Trim(true);
1733
 
            value.Trim(false);
1734
 
 
1735
 
            if (val_name.IsEmpty())
1736
 
                break;
1737
 
 
1738
 
            if (val_name == wxT("name"))
1739
 
                pane.name = value;
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());
1774
 
            else {
1775
 
                wxFAIL_MSG(wxT("Bad Perspective String"));
1776
 
            }
1777
 
        }
1778
 
 
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(";"));
1785
 
 
1786
 
        wxPaneInfo& p = GetPane(pane.name);
1787
 
        if (!p.IsOk())
1788
 
        {
1789
 
            // the pane window couldn't be found
1790
 
            // in the existing layout
1791
 
            continue;
1792
 
        }
1793
 
 
1794
 
        pane.window = p.window;
1795
 
        pane.frame = p.frame;
1796
 
        pane.buttons = p.buttons;
1797
 
        p = pane;
1798
 
    }
1799
 
 
1800
 
    if (update)
1801
 
        Update();
1802
 
 
1803
 
    return true;
1804
 
}
1805
 
 
1806
 
 
1807
 
void wxFrameManager::GetPanePositionsAndSizes(wxDockInfo& dock,
1808
 
                                              wxArrayInt& positions,
1809
 
                                              wxArrayInt& sizes)
1810
 
{
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);
1814
 
 
1815
 
    positions.Empty();
1816
 
    sizes.Empty();
1817
 
 
1818
 
    int offset, action_pane = -1;
1819
 
    int pane_i, pane_count = dock.panes.GetCount();
1820
 
 
1821
 
    // find the pane marked as our action pane
1822
 
    for (pane_i = 0; pane_i < pane_count; ++pane_i)
1823
 
    {
1824
 
        wxPaneInfo& pane = *(dock.panes.Item(pane_i));
1825
 
 
1826
 
        if (pane.state & wxPaneInfo::actionPane)
1827
 
        {
1828
 
            wxASSERT_MSG(action_pane==-1, wxT("Too many fixed action panes"));
1829
 
            action_pane = pane_i;
1830
 
        }
1831
 
    }
1832
 
 
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)
1837
 
    {
1838
 
        wxPaneInfo& pane = *(dock.panes.Item(pane_i));
1839
 
        positions.Add(pane.dock_pos);
1840
 
        int size = 0;
1841
 
 
1842
 
        if (pane.HasBorder())
1843
 
            size += (pane_border_size*2);
1844
 
 
1845
 
        if (dock.IsHorizontal())
1846
 
        {
1847
 
            if (pane.HasGripper() && !pane.HasGripperTop())
1848
 
                size += gripper_size;
1849
 
            size += pane.best_size.x;
1850
 
        }
1851
 
         else
1852
 
        {
1853
 
            if (pane.HasGripper() && pane.HasGripperTop())
1854
 
                size += gripper_size;
1855
 
 
1856
 
            if (pane.HasCaption())
1857
 
                size += caption_size;
1858
 
            size += pane.best_size.y;
1859
 
        }
1860
 
 
1861
 
        sizes.Add(size);
1862
 
    }
1863
 
 
1864
 
    // if there is no action pane, just return the default
1865
 
    // positions (as specified in pane.pane_pos)
1866
 
    if (action_pane == -1)
1867
 
        return;
1868
 
 
1869
 
    offset = 0;
1870
 
    for (pane_i = action_pane-1; pane_i >= 0; --pane_i)
1871
 
    {
1872
 
        int amount = positions[pane_i+1] - (positions[pane_i] + sizes[pane_i]);
1873
 
 
1874
 
        if (amount >= 0)
1875
 
            offset += amount;
1876
 
             else
1877
 
            positions[pane_i] -= -amount;
1878
 
 
1879
 
        offset += sizes[pane_i];
1880
 
    }
1881
 
 
1882
 
    // if the dock mode is fixed, make sure none of the panes
1883
 
    // overlap; we will bump panes that overlap
1884
 
    offset = 0;
1885
 
    for (pane_i = action_pane; pane_i < pane_count; ++pane_i)
1886
 
    {
1887
 
        int amount = positions[pane_i] - offset;
1888
 
        if (amount >= 0)
1889
 
            offset += amount;
1890
 
             else
1891
 
            positions[pane_i] += -amount;
1892
 
 
1893
 
        offset += sizes[pane_i];
1894
 
    }
1895
 
}
1896
 
 
1897
 
 
1898
 
void wxFrameManager::LayoutAddPane(wxSizer* cont,
1899
 
                                   wxDockInfo& dock,
1900
 
                                   wxPaneInfo& pane,
1901
 
                                   wxDockUIPartArray& uiparts,
1902
 
                                   bool spacer_only)
1903
 
{
1904
 
    wxDockUIPart part;
1905
 
    wxSizerItem* sizer_item;
1906
 
 
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);
1911
 
 
1912
 
    // find out the orientation of the item (orientation for panes
1913
 
    // is the same as the dock's orientation)
1914
 
    int orientation;
1915
 
    if (dock.IsHorizontal())
1916
 
        orientation = wxHORIZONTAL;
1917
 
         else
1918
 
        orientation = wxVERTICAL;
1919
 
 
1920
 
    // this variable will store the proportion
1921
 
    // value that the pane will receive
1922
 
    int pane_proportion = pane.dock_proportion;
1923
 
 
1924
 
    wxBoxSizer* horz_pane_sizer = new wxBoxSizer(wxHORIZONTAL);
1925
 
    wxBoxSizer* vert_pane_sizer = new wxBoxSizer(wxVERTICAL);
1926
 
 
1927
 
    if (pane.HasGripper())
1928
 
    {
1929
 
        if (pane.HasGripperTop())
1930
 
            sizer_item = vert_pane_sizer ->Add(1, gripper_size, 0, wxEXPAND);
1931
 
        else
1932
 
            sizer_item = horz_pane_sizer ->Add(gripper_size, 1, 0, wxEXPAND);
1933
 
 
1934
 
        part.type = wxDockUIPart::typeGripper;
1935
 
        part.dock = &dock;
1936
 
        part.pane = &pane;
1937
 
        part.button = NULL;
1938
 
        part.orientation = orientation;
1939
 
        part.cont_sizer = horz_pane_sizer;
1940
 
        part.sizer_item = sizer_item;
1941
 
        uiparts.Add(part);
1942
 
    }
1943
 
 
1944
 
    if (pane.HasCaption())
1945
 
    {
1946
 
        // create the caption sizer
1947
 
        wxBoxSizer* caption_sizer = new wxBoxSizer(wxHORIZONTAL);
1948
 
 
1949
 
        sizer_item = caption_sizer->Add(1, caption_size, 1, wxEXPAND);
1950
 
 
1951
 
        part.type = wxDockUIPart::typeCaption;
1952
 
        part.dock = &dock;
1953
 
        part.pane = &pane;
1954
 
        part.button = NULL;
1955
 
        part.orientation = orientation;
1956
 
        part.cont_sizer = vert_pane_sizer;
1957
 
        part.sizer_item = sizer_item;
1958
 
        int caption_part_idx = uiparts.GetCount();
1959
 
        uiparts.Add(part);
1960
 
 
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)
1965
 
        {
1966
 
            wxPaneButton& button = pane.buttons.Item(i);
1967
 
 
1968
 
            sizer_item = caption_sizer->Add(pane_button_size,
1969
 
                                            caption_size,
1970
 
                                            0, wxEXPAND);
1971
 
 
1972
 
            part.type = wxDockUIPart::typePaneButton;
1973
 
            part.dock = &dock;
1974
 
            part.pane = &pane;
1975
 
            part.button = &button;
1976
 
            part.orientation = orientation;
1977
 
            part.cont_sizer = caption_sizer;
1978
 
            part.sizer_item = sizer_item;
1979
 
            uiparts.Add(part);
1980
 
        }
1981
 
 
1982
 
        // add the caption sizer
1983
 
        sizer_item = vert_pane_sizer->Add(caption_sizer, 0, wxEXPAND);
1984
 
 
1985
 
        uiparts.Item(caption_part_idx).sizer_item = sizer_item;
1986
 
    }
1987
 
 
1988
 
    // add the pane window itself
1989
 
    if (spacer_only)
1990
 
    {
1991
 
        sizer_item = vert_pane_sizer->Add(1, 1, 1, wxEXPAND);
1992
 
    }
1993
 
     else
1994
 
    {
1995
 
        sizer_item = vert_pane_sizer->Add(pane.window, 1, wxEXPAND);
1996
 
        vert_pane_sizer->SetItemMinSize(pane.window, 1, 1);
1997
 
    }
1998
 
 
1999
 
    part.type = wxDockUIPart::typePane;
2000
 
    part.dock = &dock;
2001
 
    part.pane = &pane;
2002
 
    part.button = NULL;
2003
 
    part.orientation = orientation;
2004
 
    part.cont_sizer = vert_pane_sizer;
2005
 
    part.sizer_item = sizer_item;
2006
 
    uiparts.Add(part);
2007
 
 
2008
 
 
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
2012
 
 
2013
 
    wxSize min_size = pane.min_size;
2014
 
    if (pane.IsFixed())
2015
 
    {
2016
 
        if (min_size == wxDefaultSize)
2017
 
        {
2018
 
            min_size = pane.best_size;
2019
 
            pane_proportion = 0;
2020
 
        }
2021
 
    }
2022
 
 
2023
 
    if (min_size != wxDefaultSize)
2024
 
    {
2025
 
        vert_pane_sizer->SetItemMinSize(
2026
 
                        vert_pane_sizer->GetChildren().GetCount()-1,
2027
 
                        min_size.x, min_size.y);
2028
 
    }
2029
 
 
2030
 
 
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);
2034
 
 
2035
 
    // finally, add the pane sizer to the dock sizer
2036
 
 
2037
 
    if (pane.HasBorder())
2038
 
    {
2039
 
        // allowing space for the pane's border
2040
 
        sizer_item = cont->Add(horz_pane_sizer, pane_proportion,
2041
 
                               wxEXPAND | wxALL, pane_border_size);
2042
 
 
2043
 
        part.type = wxDockUIPart::typePaneBorder;
2044
 
        part.dock = &dock;
2045
 
        part.pane = &pane;
2046
 
        part.button = NULL;
2047
 
        part.orientation = orientation;
2048
 
        part.cont_sizer = cont;
2049
 
        part.sizer_item = sizer_item;
2050
 
        uiparts.Add(part);
2051
 
    }
2052
 
     else
2053
 
    {
2054
 
        sizer_item = cont->Add(horz_pane_sizer, pane_proportion, wxEXPAND);
2055
 
    }
2056
 
}
2057
 
 
2058
 
void wxFrameManager::LayoutAddDock(wxSizer* cont,
2059
 
                                   wxDockInfo& dock,
2060
 
                                   wxDockUIPartArray& uiparts,
2061
 
                                   bool spacer_only)
2062
 
{
2063
 
    wxSizerItem* sizer_item;
2064
 
    wxDockUIPart part;
2065
 
 
2066
 
    int sash_size = m_art->GetMetric(wxAUI_ART_SASH_SIZE);
2067
 
    int orientation = dock.IsHorizontal() ? wxHORIZONTAL : wxVERTICAL;
2068
 
 
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))
2072
 
    {
2073
 
        sizer_item = cont->Add(sash_size, sash_size, 0, wxEXPAND);
2074
 
 
2075
 
        part.type = wxDockUIPart::typeDockSizer;
2076
 
        part.orientation = orientation;
2077
 
        part.dock = &dock;
2078
 
        part.pane = NULL;
2079
 
        part.button = NULL;
2080
 
        part.cont_sizer = cont;
2081
 
        part.sizer_item = sizer_item;
2082
 
        uiparts.Add(part);
2083
 
    }
2084
 
 
2085
 
    // create the sizer for the dock
2086
 
    wxSizer* dock_sizer = new wxBoxSizer(orientation);
2087
 
 
2088
 
    // add each pane to the dock
2089
 
    int pane_i, pane_count = dock.panes.GetCount();
2090
 
 
2091
 
    if (dock.fixed)
2092
 
    {
2093
 
        wxArrayInt pane_positions, pane_sizes;
2094
 
 
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);
2098
 
 
2099
 
        int offset = 0;
2100
 
        for (pane_i = 0; pane_i < pane_count; ++pane_i)
2101
 
        {
2102
 
            wxPaneInfo& pane = *(dock.panes.Item(pane_i));
2103
 
            int pane_pos = pane_positions.Item(pane_i);
2104
 
 
2105
 
            int amount = pane_pos - offset;
2106
 
            if (amount > 0)
2107
 
            {
2108
 
                if (dock.IsVertical())
2109
 
                    sizer_item = dock_sizer->Add(1, amount, 0, wxEXPAND);
2110
 
                     else
2111
 
                    sizer_item = dock_sizer->Add(amount, 1, 0, wxEXPAND);
2112
 
 
2113
 
                part.type = wxDockUIPart::typeBackground;
2114
 
                part.dock = &dock;
2115
 
                part.pane = NULL;
2116
 
                part.button = NULL;
2117
 
                part.orientation = (orientation==wxHORIZONTAL) ? wxVERTICAL:wxHORIZONTAL;
2118
 
                part.cont_sizer = dock_sizer;
2119
 
                part.sizer_item = sizer_item;
2120
 
                uiparts.Add(part);
2121
 
 
2122
 
                offset += amount;
2123
 
            }
2124
 
 
2125
 
            LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only);
2126
 
 
2127
 
            offset += pane_sizes.Item(pane_i);
2128
 
        }
2129
 
 
2130
 
        // at the end add a very small stretchable background area
2131
 
        sizer_item = dock_sizer->Add(1,1, 1, wxEXPAND);
2132
 
 
2133
 
        part.type = wxDockUIPart::typeBackground;
2134
 
        part.dock = &dock;
2135
 
        part.pane = NULL;
2136
 
        part.button = NULL;
2137
 
        part.orientation = orientation;
2138
 
        part.cont_sizer = dock_sizer;
2139
 
        part.sizer_item = sizer_item;
2140
 
        uiparts.Add(part);
2141
 
    }
2142
 
     else
2143
 
    {
2144
 
        for (pane_i = 0; pane_i < pane_count; ++pane_i)
2145
 
        {
2146
 
            wxPaneInfo& pane = *(dock.panes.Item(pane_i));
2147
 
 
2148
 
            // if this is not the first pane being added,
2149
 
            // we need to add a pane sizer
2150
 
            if (pane_i > 0)
2151
 
            {
2152
 
                sizer_item = dock_sizer->Add(sash_size, sash_size, 0, wxEXPAND);
2153
 
 
2154
 
                part.type = wxDockUIPart::typePaneSizer;
2155
 
                part.dock = &dock;
2156
 
                part.pane = dock.panes.Item(pane_i-1);
2157
 
                part.button = NULL;
2158
 
                part.orientation = (orientation==wxHORIZONTAL) ? wxVERTICAL:wxHORIZONTAL;
2159
 
                part.cont_sizer = dock_sizer;
2160
 
                part.sizer_item = sizer_item;
2161
 
                uiparts.Add(part);
2162
 
            }
2163
 
 
2164
 
            LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only);
2165
 
        }
2166
 
    }
2167
 
 
2168
 
    if (dock.dock_direction == wxAUI_DOCK_CENTER)
2169
 
        sizer_item = cont->Add(dock_sizer, 1, wxEXPAND);
2170
 
         else
2171
 
        sizer_item = cont->Add(dock_sizer, 0, wxEXPAND);
2172
 
 
2173
 
    part.type = wxDockUIPart::typeDock;
2174
 
    part.dock = &dock;
2175
 
    part.pane = NULL;
2176
 
    part.button = NULL;
2177
 
    part.orientation = orientation;
2178
 
    part.cont_sizer = cont;
2179
 
    part.sizer_item = sizer_item;
2180
 
    uiparts.Add(part);
2181
 
 
2182
 
    if (dock.IsHorizontal())
2183
 
        cont->SetItemMinSize(dock_sizer, 0, dock.size);
2184
 
         else
2185
 
        cont->SetItemMinSize(dock_sizer, dock.size, 0);
2186
 
 
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))
2190
 
    {
2191
 
        sizer_item = cont->Add(sash_size, sash_size, 0, wxEXPAND);
2192
 
 
2193
 
        part.type = wxDockUIPart::typeDockSizer;
2194
 
        part.dock = &dock;
2195
 
        part.pane = NULL;
2196
 
        part.button = NULL;
2197
 
        part.orientation = orientation;
2198
 
        part.cont_sizer = cont;
2199
 
        part.sizer_item = sizer_item;
2200
 
        uiparts.Add(part);
2201
 
    }
2202
 
}
2203
 
 
2204
 
wxSizer* wxFrameManager::LayoutAll(wxPaneInfoArray& panes,
2205
 
                                   wxDockInfoArray& docks,
2206
 
                                   wxDockUIPartArray& uiparts,
2207
 
                                   bool spacer_only)
2208
 
{
2209
 
    wxBoxSizer* container = new wxBoxSizer(wxVERTICAL);
2210
 
 
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;
2215
 
 
2216
 
 
2217
 
    // empty all docks out
2218
 
    for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
2219
 
        docks.Item(i).panes.Empty();
2220
 
 
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)
2225
 
    {
2226
 
        wxPaneInfo& p = panes.Item(i);
2227
 
 
2228
 
        // find any docks in this layer
2229
 
        wxDockInfo* dock;
2230
 
        wxDockInfoPtrArray arr;
2231
 
        FindDocks(docks, p.dock_direction, p.dock_layer, p.dock_row, arr);
2232
 
 
2233
 
        if (arr.GetCount() > 0)
2234
 
        {
2235
 
            dock = arr.Item(0);
2236
 
        }
2237
 
         else
2238
 
        {
2239
 
            // dock was not found, so we need to create a new one
2240
 
            wxDockInfo d;
2241
 
            d.dock_direction = p.dock_direction;
2242
 
            d.dock_layer = p.dock_layer;
2243
 
            d.dock_row = p.dock_row;
2244
 
            docks.Add(d);
2245
 
            dock = &docks.Last();
2246
 
        }
2247
 
 
2248
 
 
2249
 
        if (p.IsDocked() && p.IsShown())
2250
 
        {
2251
 
            // remove the pane from any existing docks except this one
2252
 
            RemovePaneFromDocks(docks, p, dock);
2253
 
 
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);
2258
 
        }
2259
 
         else
2260
 
        {
2261
 
            // remove the pane from any existing docks
2262
 
            RemovePaneFromDocks(docks, p);
2263
 
        }
2264
 
 
2265
 
    }
2266
 
 
2267
 
    // remove any empty docks
2268
 
    for (i = docks.GetCount()-1; i >= 0; --i)
2269
 
    {
2270
 
        if (docks.Item(i).panes.GetCount() == 0)
2271
 
            docks.RemoveAt(i);
2272
 
    }
2273
 
 
2274
 
    // configure the docks further
2275
 
    for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
2276
 
    {
2277
 
        wxDockInfo& dock = docks.Item(i);
2278
 
        int j, dock_pane_count = dock.panes.GetCount();
2279
 
 
2280
 
        // sort the dock pane array by the pane's
2281
 
        // dock position (dock_pos), in ascending order
2282
 
        dock.panes.Sort(PaneSortFunc);
2283
 
 
2284
 
        // for newly created docks, set up their initial size
2285
 
        if (dock.size == 0)
2286
 
        {
2287
 
            int size = 0;
2288
 
 
2289
 
            for (j = 0; j < dock_pane_count; ++j)
2290
 
            {
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();
2297
 
 
2298
 
                if (dock.IsHorizontal())
2299
 
                    size = wxMax(pane_size.y, size);
2300
 
                     else
2301
 
                    size = wxMax(pane_size.x, size);
2302
 
            }
2303
 
 
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)
2307
 
            {
2308
 
                if (dock.panes.Item(j)->HasBorder())
2309
 
                {
2310
 
                    size += (pane_border_size*2);
2311
 
                    break;
2312
 
                }
2313
 
            }
2314
 
 
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())
2318
 
            {
2319
 
                for (j = 0; j < dock_pane_count; ++j)
2320
 
                {
2321
 
                    if (dock.panes.Item(j)->HasCaption())
2322
 
                    {
2323
 
                        size += caption_size;
2324
 
                        break;
2325
 
                    }
2326
 
                }
2327
 
            }
2328
 
 
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);
2332
 
                 else
2333
 
                size = wxMin(size, cli_size.x/3);
2334
 
 
2335
 
            if (size < 10)
2336
 
                size = 10;
2337
 
            dock.size = size;
2338
 
        }
2339
 
 
2340
 
 
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)
2346
 
        {
2347
 
            wxPaneInfo& pane = *dock.panes.Item(j);
2348
 
            if (pane.min_size != wxDefaultSize)
2349
 
            {
2350
 
                if (pane.HasBorder())
2351
 
                    plus_border = true;
2352
 
                if (pane.HasCaption())
2353
 
                    plus_caption = true;
2354
 
                if (dock.IsHorizontal())
2355
 
                {
2356
 
                    if (pane.min_size.y > dock_min_size)
2357
 
                        dock_min_size = pane.min_size.y;
2358
 
                }
2359
 
                 else
2360
 
                {
2361
 
                    if (pane.min_size.x > dock_min_size)
2362
 
                        dock_min_size = pane.min_size.x;
2363
 
                }
2364
 
            }
2365
 
        }
2366
 
 
2367
 
        if (plus_border)
2368
 
            dock_min_size += (pane_border_size*2);
2369
 
        if (plus_caption && dock.IsHorizontal())
2370
 
            dock_min_size += (caption_size);
2371
 
 
2372
 
        dock.min_size = dock_min_size;
2373
 
 
2374
 
 
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;
2379
 
 
2380
 
 
2381
 
        // determine the dock's mode (fixed or proportional);
2382
 
        // determine whether the dock has only toolbars
2383
 
        bool action_pane_marked = false;
2384
 
        dock.fixed = true;
2385
 
        dock.toolbar = true;
2386
 
        for (j = 0; j < dock_pane_count; ++j)
2387
 
        {
2388
 
            wxPaneInfo& pane = *dock.panes.Item(j);
2389
 
            if (!pane.IsFixed())
2390
 
                dock.fixed = false;
2391
 
            if (!pane.IsToolbar())
2392
 
                dock.toolbar = false;
2393
 
            if (pane.state & wxPaneInfo::actionPane)
2394
 
                action_pane_marked = true;
2395
 
        }
2396
 
 
2397
 
 
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
2401
 
        if (!dock.fixed)
2402
 
        {
2403
 
            for (j = 0; j < dock_pane_count; ++j)
2404
 
            {
2405
 
                wxPaneInfo& pane = *dock.panes.Item(j);
2406
 
                pane.dock_pos = j;
2407
 
            }
2408
 
        }
2409
 
 
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)
2415
 
        {
2416
 
            wxArrayInt pane_positions, pane_sizes;
2417
 
            GetPanePositionsAndSizes(dock, pane_positions, pane_sizes);
2418
 
 
2419
 
            int offset = 0;
2420
 
            for (j = 0; j < dock_pane_count; ++j)
2421
 
            {
2422
 
                wxPaneInfo& pane = *(dock.panes.Item(j));
2423
 
                pane.dock_pos = pane_positions[j];
2424
 
 
2425
 
                int amount = pane.dock_pos - offset;
2426
 
                if (amount >= 0)
2427
 
                    offset += amount;
2428
 
                     else
2429
 
                    pane.dock_pos += -amount;
2430
 
 
2431
 
                offset += pane_sizes[j];
2432
 
            }
2433
 
        }
2434
 
    }
2435
 
 
2436
 
    // discover the maximum dock layer
2437
 
    int max_layer = 0;
2438
 
    for (i = 0; i < dock_count; ++i)
2439
 
        max_layer = wxMax(max_layer, docks.Item(i).dock_layer);
2440
 
 
2441
 
 
2442
 
    // clear out uiparts
2443
 
    uiparts.Empty();
2444
 
 
2445
 
    // create a bunch of box sizers,
2446
 
    // from the innermost level outwards.
2447
 
    wxSizer* cont = NULL;
2448
 
    wxSizer* middle = NULL;
2449
 
    int layer = 0;
2450
 
    int row, row_count;
2451
 
 
2452
 
    for (layer = 0; layer <= max_layer; ++layer)
2453
 
    {
2454
 
        wxDockInfoPtrArray arr;
2455
 
 
2456
 
        // find any docks in this layer
2457
 
        FindDocks(docks, -1, layer, -1, arr);
2458
 
 
2459
 
        // if there aren't any, skip to the next layer
2460
 
        if (arr.IsEmpty())
2461
 
            continue;
2462
 
 
2463
 
        wxSizer* old_cont = cont;
2464
 
 
2465
 
        // create a container which will hold this layer's
2466
 
        // docks (top, bottom, left, right)
2467
 
        cont = new wxBoxSizer(wxVERTICAL);
2468
 
 
2469
 
 
2470
 
        // find any top docks in this layer
2471
 
        FindDocks(docks, wxAUI_DOCK_TOP, layer, -1, arr);
2472
 
        RenumberDockRows(arr);
2473
 
        if (!arr.IsEmpty())
2474
 
        {
2475
 
            for (row = 0, row_count = arr.GetCount(); row < row_count; ++row)
2476
 
                LayoutAddDock(cont, *arr.Item(row), uiparts, spacer_only);
2477
 
        }
2478
 
 
2479
 
 
2480
 
        // fill out the middle layer (which consists
2481
 
        // of left docks, content area and right docks)
2482
 
 
2483
 
        middle = new wxBoxSizer(wxHORIZONTAL);
2484
 
 
2485
 
        // find any left docks in this layer
2486
 
        FindDocks(docks, wxAUI_DOCK_LEFT, layer, -1, arr);
2487
 
        RenumberDockRows(arr);
2488
 
        if (!arr.IsEmpty())
2489
 
        {
2490
 
            for (row = 0, row_count = arr.GetCount(); row < row_count; ++row)
2491
 
                LayoutAddDock(middle, *arr.Item(row), uiparts, spacer_only);
2492
 
        }
2493
 
 
2494
 
        // add content dock (or previous layer's sizer
2495
 
        // to the middle
2496
 
        if (!old_cont)
2497
 
        {
2498
 
            // find any center docks
2499
 
            FindDocks(docks, wxAUI_DOCK_CENTER, -1, -1, arr);
2500
 
            if (!arr.IsEmpty())
2501
 
            {
2502
 
                for (row = 0,row_count = arr.GetCount(); row<row_count; ++row)
2503
 
                   LayoutAddDock(middle, *arr.Item(row), uiparts, spacer_only);
2504
 
            }
2505
 
             else
2506
 
            {
2507
 
                // there are no center docks, add a background area
2508
 
                wxSizerItem* sizer_item = middle->Add(1,1, 1, wxEXPAND);
2509
 
                wxDockUIPart part;
2510
 
                part.type = wxDockUIPart::typeBackground;
2511
 
                part.pane = NULL;
2512
 
                part.dock = NULL;
2513
 
                part.button = NULL;
2514
 
                part.cont_sizer = middle;
2515
 
                part.sizer_item = sizer_item;
2516
 
                uiparts.Add(part);
2517
 
            }
2518
 
        }
2519
 
         else
2520
 
        {
2521
 
            middle->Add(old_cont, 1, wxEXPAND);
2522
 
        }
2523
 
 
2524
 
        // find any right docks in this layer
2525
 
        FindDocks(docks, wxAUI_DOCK_RIGHT, layer, -1, arr);
2526
 
        RenumberDockRows(arr);
2527
 
        if (!arr.IsEmpty())
2528
 
        {
2529
 
            for (row = arr.GetCount()-1; row >= 0; --row)
2530
 
                LayoutAddDock(middle, *arr.Item(row), uiparts, spacer_only);
2531
 
        }
2532
 
 
2533
 
        cont->Add(middle, 1, wxEXPAND);
2534
 
 
2535
 
 
2536
 
 
2537
 
        // find any bottom docks in this layer
2538
 
        FindDocks(docks, wxAUI_DOCK_BOTTOM, layer, -1, arr);
2539
 
        RenumberDockRows(arr);
2540
 
        if (!arr.IsEmpty())
2541
 
        {
2542
 
            for (row = arr.GetCount()-1; row >= 0; --row)
2543
 
                LayoutAddDock(cont, *arr.Item(row), uiparts, spacer_only);
2544
 
        }
2545
 
 
2546
 
    }
2547
 
 
2548
 
    if (!cont)
2549
 
    {
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);
2554
 
        wxDockUIPart part;
2555
 
        part.type = wxDockUIPart::typeBackground;
2556
 
        part.pane = NULL;
2557
 
        part.dock = NULL;
2558
 
        part.button = NULL;
2559
 
        part.cont_sizer = middle;
2560
 
        part.sizer_item = sizer_item;
2561
 
        uiparts.Add(part);
2562
 
    }
2563
 
 
2564
 
    container->Add(cont, 1, wxEXPAND);
2565
 
    return container;
2566
 
}
2567
 
 
2568
 
 
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.
2572
 
 
2573
 
void wxFrameManager::Update()
2574
 
{
2575
 
    wxSizer* sizer;
2576
 
    int i, pane_count = m_panes.GetCount();
2577
 
 
2578
 
    // delete old sizer first
2579
 
    m_frame->SetSizer(NULL);
2580
 
 
2581
 
    // destroy floating panes which have been
2582
 
    // redocked or are becoming non-floating
2583
 
    for (i = 0; i < pane_count; ++i)
2584
 
    {
2585
 
        wxPaneInfo& p = m_panes.Item(i);
2586
 
 
2587
 
        if (!p.IsFloating() && p.frame)
2588
 
        {
2589
 
            // because the pane is no longer in a floating, we need to
2590
 
            // reparent it to m_frame and destroy the floating frame
2591
 
 
2592
 
            // reduce flicker
2593
 
            p.window->SetSize(1,1);
2594
 
            p.frame->Show(false);
2595
 
 
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;
2602
 
            p.frame->Destroy();
2603
 
            p.frame = NULL;
2604
 
        }
2605
 
    }
2606
 
 
2607
 
 
2608
 
    // create a layout for all of the panes
2609
 
    sizer = LayoutAll(m_panes, m_docks, m_uiparts, false);
2610
 
 
2611
 
    // hide or show panes as necessary,
2612
 
    // and float panes as necessary
2613
 
    for (i = 0; i < pane_count; ++i)
2614
 
    {
2615
 
        wxPaneInfo& p = m_panes.Item(i);
2616
 
 
2617
 
        if (p.IsFloating())
2618
 
        {
2619
 
            if (p.frame == NULL)
2620
 
            {
2621
 
                // we need to create a frame for this
2622
 
                // pane, which has recently been floated
2623
 
                wxFloatingPane* frame = new wxFloatingPane(m_frame,
2624
 
                                                  this, -1,
2625
 
                                                  p.floating_pos,
2626
 
                                                  p.floating_size);
2627
 
 
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
2631
 
                #ifdef __WXMSW__
2632
 
                if (m_action == actionDragFloatingPane &&
2633
 
                    (m_flags & wxAUI_MGR_TRANSPARENT_DRAG))
2634
 
                        MakeWindowTransparent(frame, 150);
2635
 
                #endif
2636
 
 
2637
 
                frame->SetPaneWindow(p);
2638
 
                p.frame = frame;
2639
 
 
2640
 
                if (p.IsShown())
2641
 
                {
2642
 
                    frame->Show();
2643
 
                }
2644
 
            }
2645
 
             else
2646
 
            {
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)
2650
 
                {
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);
2654
 
                }
2655
 
 
2656
 
                 p.frame->Show(p.IsShown());
2657
 
            }
2658
 
        }
2659
 
         else
2660
 
        {
2661
 
            p.window->Show(p.IsShown());
2662
 
        }
2663
 
 
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)
2667
 
        {
2668
 
            p.state &= ~wxPaneInfo::optionActive;
2669
 
        }
2670
 
    }
2671
 
 
2672
 
 
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)
2677
 
    {
2678
 
        wxRect r;
2679
 
        wxPaneInfo& p = m_panes.Item(i);
2680
 
 
2681
 
        if (p.window && p.IsShown() && p.IsDocked())
2682
 
            r = p.rect;
2683
 
 
2684
 
        old_pane_rects.Add(r);
2685
 
    }
2686
 
 
2687
 
 
2688
 
 
2689
 
 
2690
 
    // apply the new sizer
2691
 
    m_frame->SetSizer(sizer);
2692
 
    m_frame->SetAutoLayout(false);
2693
 
    DoFrameLayout();
2694
 
 
2695
 
 
2696
 
 
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)
2702
 
    {
2703
 
        wxPaneInfo& p = m_panes.Item(i);
2704
 
        if (p.window && p.window->IsShown() && p.IsDocked())
2705
 
        {
2706
 
            if (p.rect != old_pane_rects[i])
2707
 
            {
2708
 
                p.window->Refresh();
2709
 
                p.window->Update();
2710
 
            }
2711
 
        }
2712
 
    }
2713
 
 
2714
 
 
2715
 
    Repaint();
2716
 
 
2717
 
    // set frame's minimum size
2718
 
 
2719
 
/*
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();
2727
 
 
2728
 
    wxSize minframe_size(min_size.x+frame_size.x-client_size.x,
2729
 
                         min_size.y+frame_size.y-client_size.y );
2730
 
 
2731
 
    m_frame->SetMinSize(minframe_size);
2732
 
 
2733
 
    if (frame_size.x < minframe_size.x ||
2734
 
        frame_size.y < minframe_size.y)
2735
 
            sizer->Fit(m_frame);
2736
 
*/
2737
 
}
2738
 
 
2739
 
 
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
2744
 
 
2745
 
void wxFrameManager::DoFrameLayout()
2746
 
{
2747
 
    m_frame->Layout();
2748
 
 
2749
 
    int i, part_count;
2750
 
    for (i = 0, part_count = m_uiparts.GetCount(); i < part_count; ++i)
2751
 
    {
2752
 
        wxDockUIPart& part = m_uiparts.Item(i);
2753
 
 
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
2764
 
 
2765
 
 
2766
 
        part.rect = part.sizer_item->GetRect();
2767
 
        int flag = part.sizer_item->GetFlag();
2768
 
        int border = part.sizer_item->GetBorder();
2769
 
        if (flag & wxTOP)
2770
 
        {
2771
 
            part.rect.y -= border;
2772
 
            part.rect.height += border;
2773
 
        }
2774
 
        if (flag & wxLEFT)
2775
 
        {
2776
 
            part.rect.x -= border;
2777
 
            part.rect.width += border;
2778
 
        }
2779
 
        if (flag & wxBOTTOM)
2780
 
            part.rect.height += border;
2781
 
        if (flag & wxRIGHT)
2782
 
            part.rect.width += border;
2783
 
 
2784
 
 
2785
 
        if (part.type == wxDockUIPart::typeDock)
2786
 
            part.dock->rect = part.rect;
2787
 
        if (part.type == wxDockUIPart::typePane)
2788
 
            part.pane->rect = part.rect;
2789
 
    }
2790
 
}
2791
 
 
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).
2796
 
 
2797
 
wxDockUIPart* wxFrameManager::GetPanePart(wxWindow* wnd)
2798
 
{
2799
 
    int i, part_count;
2800
 
    for (i = 0, part_count = m_uiparts.GetCount(); i < part_count; ++i)
2801
 
    {
2802
 
        wxDockUIPart& part = m_uiparts.Item(i);
2803
 
        if (part.type == wxDockUIPart::typePaneBorder &&
2804
 
            part.pane && part.pane->window == wnd)
2805
 
                return &part;
2806
 
    }
2807
 
    for (i = 0, part_count = m_uiparts.GetCount(); i < part_count; ++i)
2808
 
    {
2809
 
        wxDockUIPart& part = m_uiparts.Item(i);
2810
 
        if (part.type == wxDockUIPart::typePane &&
2811
 
            part.pane && part.pane->window == wnd)
2812
 
                return &part;
2813
 
    }
2814
 
    return NULL;
2815
 
}
2816
 
 
2817
 
 
2818
 
 
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.
2824
 
 
2825
 
int wxFrameManager::GetDockPixelOffset(wxPaneInfo& test)
2826
 
{
2827
 
    // the only way to accurately calculate the dock's
2828
 
    // offset is to actually run a theoretical layout
2829
 
 
2830
 
    int i, part_count, dock_count;
2831
 
    wxDockInfoArray docks;
2832
 
    wxPaneInfoArray panes;
2833
 
    wxDockUIPartArray uiparts;
2834
 
    CopyDocksAndPanes(docks, panes, m_docks, m_panes);
2835
 
    panes.Add(test);
2836
 
 
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);
2840
 
    sizer->Layout();
2841
 
 
2842
 
    for (i = 0, part_count = uiparts.GetCount(); i < part_count; ++i)
2843
 
    {
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;
2849
 
    }
2850
 
 
2851
 
    delete sizer;
2852
 
 
2853
 
    for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
2854
 
    {
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)
2858
 
        {
2859
 
            if (dock.IsVertical())
2860
 
                return dock.rect.y;
2861
 
                 else
2862
 
                return dock.rect.x;
2863
 
        }
2864
 
    }
2865
 
 
2866
 
    return 0;
2867
 
}
2868
 
 
2869
 
 
2870
 
 
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.
2874
 
 
2875
 
static bool ProcessDockResult(wxPaneInfo& target,
2876
 
                              const wxPaneInfo& new_pos)
2877
 
{
2878
 
    bool allowed = false;
2879
 
    switch (new_pos.dock_direction)
2880
 
    {
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;
2885
 
    }
2886
 
 
2887
 
    if (allowed)
2888
 
        target = new_pos;
2889
 
 
2890
 
    return allowed;
2891
 
}
2892
 
 
2893
 
 
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
2901
 
 
2902
 
const int auiInsertRowPixels = 10;
2903
 
const int auiNewRowPixels = 40;
2904
 
const int auiLayerInsertPixels = 40;
2905
 
const int auiLayerInsertOffset = 5;
2906
 
 
2907
 
bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
2908
 
                            wxPaneInfoArray& panes,
2909
 
                            wxPaneInfo& target,
2910
 
                            const wxPoint& pt,
2911
 
                            const wxPoint& offset)
2912
 
{
2913
 
    wxSize cli_size = m_frame->GetClientSize();
2914
 
 
2915
 
    wxPaneInfo drop = target;
2916
 
 
2917
 
 
2918
 
    // The result should always be shown
2919
 
    drop.Show();
2920
 
 
2921
 
 
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
2924
 
 
2925
 
 
2926
 
    int layer_insert_offset = auiLayerInsertOffset;
2927
 
    if (target.IsToolbar())
2928
 
        layer_insert_offset = 0;
2929
 
 
2930
 
    if (pt.x < layer_insert_offset &&
2931
 
        pt.x > layer_insert_offset-auiLayerInsertPixels)
2932
 
    {
2933
 
        int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_LEFT),
2934
 
                                    GetMaxLayer(docks, wxAUI_DOCK_BOTTOM)),
2935
 
                                    GetMaxLayer(docks, wxAUI_DOCK_TOP)) + 1;
2936
 
        drop.Dock().Left().
2937
 
             Layer(new_layer).
2938
 
             Row(0).
2939
 
             Position(pt.y - GetDockPixelOffset(drop) - offset.y);
2940
 
        return ProcessDockResult(target, drop);
2941
 
    }
2942
 
     else if (pt.y < layer_insert_offset &&
2943
 
              pt.y > layer_insert_offset-auiLayerInsertPixels)
2944
 
    {
2945
 
        int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_TOP),
2946
 
                                    GetMaxLayer(docks, wxAUI_DOCK_LEFT)),
2947
 
                                    GetMaxLayer(docks, wxAUI_DOCK_RIGHT)) + 1;
2948
 
        drop.Dock().Top().
2949
 
             Layer(new_layer).
2950
 
             Row(0).
2951
 
             Position(pt.x - GetDockPixelOffset(drop) - offset.x);
2952
 
        return ProcessDockResult(target, drop);
2953
 
    }
2954
 
     else if (pt.x >= cli_size.x - layer_insert_offset &&
2955
 
              pt.x < cli_size.x - layer_insert_offset + auiLayerInsertPixels)
2956
 
    {
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().
2961
 
             Layer(new_layer).
2962
 
             Row(0).
2963
 
             Position(pt.y - GetDockPixelOffset(drop) - offset.y);
2964
 
        return ProcessDockResult(target, drop);
2965
 
    }
2966
 
     else if (pt.y >= cli_size.y - layer_insert_offset &&
2967
 
              pt.y < cli_size.y - layer_insert_offset + auiLayerInsertPixels)
2968
 
    {
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().
2973
 
             Layer(new_layer).
2974
 
             Row(0).
2975
 
             Position(pt.x - GetDockPixelOffset(drop) - offset.x);
2976
 
        return ProcessDockResult(target, drop);
2977
 
    }
2978
 
 
2979
 
 
2980
 
    wxDockUIPart* part = HitTest(pt.x, pt.y);
2981
 
 
2982
 
 
2983
 
    if (drop.IsToolbar())
2984
 
    {
2985
 
        if (!part || !part->dock)
2986
 
            return false;
2987
 
 
2988
 
 
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;
2994
 
             else
2995
 
            dock_drop_offset = pt.y - part->dock->rect.y - offset.y;
2996
 
 
2997
 
 
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)
3002
 
        {
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)))
3007
 
            {
3008
 
                drop.Float();
3009
 
            }
3010
 
 
3011
 
            return ProcessDockResult(target, drop);
3012
 
        }
3013
 
 
3014
 
        drop.Dock().
3015
 
             Direction(part->dock->dock_direction).
3016
 
             Layer(part->dock->dock_layer).
3017
 
             Row(part->dock->dock_row).
3018
 
             Position(dock_drop_offset);
3019
 
 
3020
 
        if ((
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)
3024
 
        {
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;
3030
 
        }
3031
 
 
3032
 
        if ((
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)
3036
 
        {
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;
3041
 
        }
3042
 
 
3043
 
        return ProcessDockResult(target, drop);
3044
 
    }
3045
 
 
3046
 
 
3047
 
 
3048
 
 
3049
 
    if (!part)
3050
 
        return false;
3051
 
 
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)
3060
 
    {
3061
 
        if (part->type == wxDockUIPart::typeDockSizer)
3062
 
        {
3063
 
            if (part->dock->panes.GetCount() != 1)
3064
 
                return false;
3065
 
            part = GetPanePart(part->dock->panes.Item(0)->window);
3066
 
            if (!part)
3067
 
                return false;
3068
 
        }
3069
 
 
3070
 
 
3071
 
 
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)
3077
 
        {
3078
 
            int layer = 0;
3079
 
 
3080
 
            switch (part->dock->dock_direction)
3081
 
            {
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));
3086
 
                    break;
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));
3091
 
                    break;
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));
3096
 
                    break;
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));
3101
 
                    break;
3102
 
            }
3103
 
 
3104
 
            DoInsertDockRow(panes, part->dock->dock_direction,
3105
 
                            layer, 0);
3106
 
            drop.Dock().
3107
 
                 Direction(part->dock->dock_direction).
3108
 
                 Layer(layer).Row(0).Position(0);
3109
 
            return ProcessDockResult(target, drop);
3110
 
        }
3111
 
 
3112
 
 
3113
 
        if (!part->pane)
3114
 
            return false;
3115
 
 
3116
 
        part = GetPanePart(part->pane->window);
3117
 
        if (!part)
3118
 
            return false;
3119
 
 
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;
3124
 
 
3125
 
        switch (part->pane->dock_direction)
3126
 
        {
3127
 
            case wxAUI_DOCK_TOP:
3128
 
                if (pt.y >= part->rect.y &&
3129
 
                    pt.y < part->rect.y+auiInsertRowPixels)
3130
 
                        insert_dock_row = true;
3131
 
                break;
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;
3136
 
                break;
3137
 
            case wxAUI_DOCK_LEFT:
3138
 
                if (pt.x >= part->rect.x &&
3139
 
                    pt.x < part->rect.x+auiInsertRowPixels)
3140
 
                        insert_dock_row = true;
3141
 
                break;
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;
3146
 
                break;
3147
 
            case wxAUI_DOCK_CENTER:
3148
 
            {
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;
3153
 
 
3154
 
                if (new_row_pixels_x > (part->rect.width*20)/100)
3155
 
                    new_row_pixels_x = (part->rect.width*20)/100;
3156
 
 
3157
 
                if (new_row_pixels_y > (part->rect.height*20)/100)
3158
 
                    new_row_pixels_y = (part->rect.height*20)/100;
3159
 
 
3160
 
 
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
3164
 
 
3165
 
                insert_layer = 0;
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;
3170
 
                 else
3171
 
                if (pt.y >= part->rect.y &&
3172
 
                    pt.y < part->rect.y+new_row_pixels_y)
3173
 
                        insert_dir = wxAUI_DOCK_TOP;
3174
 
                 else
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;
3178
 
                 else
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;
3182
 
                 else
3183
 
                return false;
3184
 
 
3185
 
                insert_row = GetMaxRow(panes, insert_dir, insert_layer) + 1;
3186
 
            }
3187
 
        }
3188
 
 
3189
 
        if (insert_dock_row)
3190
 
        {
3191
 
            DoInsertDockRow(panes, insert_dir, insert_layer, insert_row);
3192
 
            drop.Dock().Direction(insert_dir).
3193
 
                        Layer(insert_layer).
3194
 
                        Row(insert_row).
3195
 
                        Position(0);
3196
 
            return ProcessDockResult(target, drop);
3197
 
        }
3198
 
 
3199
 
        // determine the mouse offset and the pane size, both in the
3200
 
        // direction of the dock itself, and perpendicular to the dock
3201
 
 
3202
 
        int offset, size;
3203
 
 
3204
 
        if (part->orientation == wxVERTICAL)
3205
 
        {
3206
 
            offset = pt.y - part->rect.y;
3207
 
            size = part->rect.GetHeight();
3208
 
        }
3209
 
         else
3210
 
        {
3211
 
            offset = pt.x - part->rect.x;
3212
 
            size = part->rect.GetWidth();
3213
 
        }
3214
 
 
3215
 
        int drop_position = part->pane->dock_pos;
3216
 
 
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)
3220
 
        {
3221
 
            drop_position = part->pane->dock_pos;
3222
 
            DoInsertPane(panes,
3223
 
                         part->pane->dock_direction,
3224
 
                         part->pane->dock_layer,
3225
 
                         part->pane->dock_row,
3226
 
                         part->pane->dock_pos);
3227
 
        }
3228
 
 
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)
3232
 
        {
3233
 
            drop_position = part->pane->dock_pos+1;
3234
 
            DoInsertPane(panes,
3235
 
                         part->pane->dock_direction,
3236
 
                         part->pane->dock_layer,
3237
 
                         part->pane->dock_row,
3238
 
                         part->pane->dock_pos+1);
3239
 
        }
3240
 
 
3241
 
        drop.Dock().
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);
3247
 
    }
3248
 
 
3249
 
    return false;
3250
 
}
3251
 
 
3252
 
 
3253
 
void wxFrameManager::OnHintFadeTimer(wxTimerEvent& event)
3254
 
{
3255
 
    bool realtransparency = !(m_hint_wnd && m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame)));
3256
 
    if (!m_hint_wnd || m_hint_fadeamt >= (realtransparency?50:128))
3257
 
    {
3258
 
        m_hint_fadetimer.Stop();
3259
 
        return;
3260
 
    }
3261
 
 
3262
 
    m_hint_fadeamt += 5;
3263
 
    MakeWindowTransparent(m_hint_wnd, m_hint_fadeamt);
3264
 
}
3265
 
 
3266
 
void wxFrameManager::ShowHint(const wxRect& rect)
3267
 
{
3268
 
 
3269
 
    static bool realtransparency = false;
3270
 
#ifdef __WXMSW__
3271
 
    // First, determine if the operating system can handle transparency.
3272
 
    // Transparency is available on Win2000 and above
3273
 
 
3274
 
    static int os_type = -1;
3275
 
    static int ver_major = -1;
3276
 
 
3277
 
    if (os_type == -1)
3278
 
        os_type = ::wxGetOsVersion(&ver_major);
3279
 
 
3280
 
    realtransparency = (m_flags & wxAUI_MGR_TRANSPARENT_HINT) && os_type == wxWINDOWS_NT && ver_major >= 5;
3281
 
#endif
3282
 
 
3283
 
    // If the transparent flag is set, and the OS supports it,
3284
 
    // go ahead and use a transparent hint
3285
 
 
3286
 
    if (m_last_hint == rect)
3287
 
        return;
3288
 
    m_last_hint = rect;
3289
 
 
3290
 
    int initial_fade = realtransparency?50:128;
3291
 
    if (m_flags & wxAUI_MGR_TRANSPARENT_HINT_FADE)
3292
 
        initial_fade = 0;
3293
 
 
3294
 
    if (m_hint_wnd == NULL)
3295
 
    {
3296
 
        wxPoint pt = rect.GetPosition();
3297
 
        wxSize size = rect.GetSize();
3298
 
 
3299
 
        if (realtransparency)
3300
 
        {
3301
 
#ifdef __WXMSW__
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 |
3306
 
                                        wxNO_BORDER);
3307
 
            m_hint_wnd->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION));
3308
 
#endif
3309
 
        }
3310
 
        else
3311
 
        {
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 |
3316
 
                                        wxNO_BORDER);
3317
 
        }
3318
 
        MakeWindowTransparent(m_hint_wnd, initial_fade);
3319
 
        m_hint_wnd->Show();
3320
 
 
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();
3325
 
 
3326
 
    }
3327
 
    else
3328
 
    {
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);
3333
 
        m_hint_wnd->Show();
3334
 
        if (m_action == actionDragFloatingPane && m_action_window)
3335
 
            m_action_window->SetFocus();
3336
 
    }
3337
 
 
3338
 
    if (m_flags & wxAUI_MGR_TRANSPARENT_HINT_FADE)
3339
 
    {
3340
 
        // start fade in timer
3341
 
        m_hint_fadeamt = 0;
3342
 
        m_hint_fadetimer.SetOwner(this, 101);
3343
 
        m_hint_fadetimer.Start(5);
3344
 
    }
3345
 
 
3346
 
    return;
3347
 
}
3348
 
 
3349
 
void wxFrameManager::HideHint()
3350
 
{
3351
 
    // hides a transparent window hint (currently wxMSW only)
3352
 
    if (m_hint_wnd)
3353
 
    {
3354
 
        MakeWindowTransparent(m_hint_wnd, 0);
3355
 
        m_hint_fadetimer.Stop();
3356
 
        m_last_hint = wxRect();
3357
 
        m_hint_wnd->Hide();
3358
 
 
3359
 
        // We don't need to destroy the hint window here, as it gets reused, but let's try.
3360
 
        m_hint_wnd->Destroy();
3361
 
        m_hint_wnd=NULL;
3362
 
 
3363
 
        return;
3364
 
    }
3365
 
}
3366
 
 
3367
 
 
3368
 
 
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,
3376
 
                                  const wxPoint& pt,
3377
 
                                  const wxPoint& offset)
3378
 
{
3379
 
    wxRect rect;
3380
 
 
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
3385
 
 
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__");
3392
 
 
3393
 
    if (!hint.IsOk())
3394
 
        return;
3395
 
 
3396
 
    CopyDocksAndPanes(docks, panes, m_docks, m_panes);
3397
 
 
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)
3401
 
    {
3402
 
        if (panes.Item(i).window == pane_window)
3403
 
        {
3404
 
            RemovePaneFromDocks(docks, panes.Item(i));
3405
 
            panes.RemoveAt(i);
3406
 
            break;
3407
 
        }
3408
 
    }
3409
 
 
3410
 
    // find out where the new pane would be
3411
 
    if (!DoDrop(docks, panes, hint, pt, offset))
3412
 
    {
3413
 
        HideHint();
3414
 
        return;
3415
 
    }
3416
 
 
3417
 
    panes.Add(hint);
3418
 
 
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);
3422
 
    sizer->Layout();
3423
 
 
3424
 
    for (i = 0, part_count = uiparts.GetCount();
3425
 
         i < part_count; ++i)
3426
 
    {
3427
 
        wxDockUIPart& part = uiparts.Item(i);
3428
 
 
3429
 
        if (part.type == wxDockUIPart::typePaneBorder &&
3430
 
            part.pane && part.pane->name == wxT("__HINT__"))
3431
 
        {
3432
 
            rect = wxRect(part.sizer_item->GetPosition(),
3433
 
                          part.sizer_item->GetSize());
3434
 
            break;
3435
 
        }
3436
 
    }
3437
 
 
3438
 
    delete sizer;
3439
 
 
3440
 
    if (rect.IsEmpty())
3441
 
    {
3442
 
        HideHint();
3443
 
        return;
3444
 
    }
3445
 
 
3446
 
    // actually show the hint rectangle on the screen
3447
 
    m_frame->ClientToScreen(&rect.x, &rect.y);
3448
 
    ShowHint(rect);
3449
 
}
3450
 
 
3451
 
void wxFrameManager::OnFloatingPaneMoveStart(wxWindow* wnd)
3452
 
{
3453
 
    // try to find the pane
3454
 
    wxPaneInfo& pane = GetPane(wnd);
3455
 
    wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
3456
 
 
3457
 
    #ifdef __WXMSW__
3458
 
    if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG)
3459
 
        MakeWindowTransparent(pane.frame, 150);
3460
 
    #endif
3461
 
}
3462
 
 
3463
 
void wxFrameManager::OnFloatingPaneMoving(wxWindow* wnd)
3464
 
{
3465
 
    // try to find the pane
3466
 
    wxPaneInfo& pane = GetPane(wnd);
3467
 
    wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
3468
 
 
3469
 
    wxPoint pt = ::wxGetMousePosition();
3470
 
    wxPoint client_pt = m_frame->ScreenToClient(pt);
3471
 
 
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);
3476
 
 
3477
 
    // no hint for toolbar floating windows
3478
 
    if (pane.IsToolbar() && m_action == actionDragFloatingPane)
3479
 
    {
3480
 
        if (m_action == actionDragFloatingPane)
3481
 
        {
3482
 
            wxDockInfoArray docks;
3483
 
            wxPaneInfoArray panes;
3484
 
            wxDockUIPartArray uiparts;
3485
 
            wxPaneInfo hint = pane;
3486
 
 
3487
 
            CopyDocksAndPanes(docks, panes, m_docks, m_panes);
3488
 
 
3489
 
            // find out where the new pane would be
3490
 
            if (!DoDrop(docks, panes, hint, client_pt))
3491
 
                return;
3492
 
            if (hint.IsFloating())
3493
 
                return;
3494
 
 
3495
 
            pane = hint;
3496
 
            m_action = actionDragToolbarPane;
3497
 
            m_action_window = pane.window;
3498
 
 
3499
 
            Update();
3500
 
        }
3501
 
 
3502
 
        return;
3503
 
    }
3504
 
 
3505
 
 
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))
3509
 
    {
3510
 
        HideHint();
3511
 
        return;
3512
 
    }
3513
 
 
3514
 
 
3515
 
    DrawHintRect(wnd, client_pt, action_offset);
3516
 
 
3517
 
    #ifdef __WXGTK__
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
3520
 
    // in DrawHintRect)
3521
 
    //Refresh();
3522
 
    #endif
3523
 
 
3524
 
 
3525
 
    // reduces flicker
3526
 
    m_frame->Update();
3527
 
}
3528
 
 
3529
 
void wxFrameManager::OnFloatingPaneMoved(wxWindow* wnd)
3530
 
{
3531
 
    // try to find the pane
3532
 
    wxPaneInfo& pane = GetPane(wnd);
3533
 
    wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
3534
 
 
3535
 
    wxPoint pt = ::wxGetMousePosition();
3536
 
    wxPoint client_pt = m_frame->ScreenToClient(pt);
3537
 
 
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);
3542
 
 
3543
 
 
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))
3547
 
    {
3548
 
        HideHint();
3549
 
        return;
3550
 
    }
3551
 
 
3552
 
 
3553
 
    // do the drop calculation
3554
 
    DoDrop(m_docks, m_panes, pane, client_pt, action_offset);
3555
 
 
3556
 
    // if the pane is still floating, update it's floating
3557
 
    // position (that we store)
3558
 
    if (pane.IsFloating())
3559
 
    {
3560
 
        pane.floating_pos = pane.frame->GetPosition();
3561
 
 
3562
 
        #ifdef __WXMSW__
3563
 
        if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG)
3564
 
            MakeWindowTransparent(pane.frame, 255);
3565
 
        #endif
3566
 
    }
3567
 
 
3568
 
    Update();
3569
 
 
3570
 
    HideHint();
3571
 
}
3572
 
 
3573
 
void wxFrameManager::OnFloatingPaneResized(wxWindow* wnd, const wxSize& size)
3574
 
{
3575
 
    // try to find the pane
3576
 
    wxPaneInfo& pane = GetPane(wnd);
3577
 
    wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
3578
 
 
3579
 
    pane.floating_size = size;
3580
 
}
3581
 
 
3582
 
void wxFrameManager::OnFloatingPaneClosed(wxWindow* wnd)
3583
 
{
3584
 
    // try to find the pane
3585
 
    wxPaneInfo& pane = GetPane(wnd);
3586
 
    wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
3587
 
 
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);
3592
 
    pane.frame = NULL;
3593
 
    pane.Hide();
3594
 
}
3595
 
 
3596
 
void wxFrameManager::OnFloatingPaneActivated(wxWindow* wnd)
3597
 
{
3598
 
    if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE)
3599
 
    {
3600
 
        // try to find the pane
3601
 
        wxASSERT_MSG(GetPane(wnd).IsOk(), wxT("Pane window not found"));
3602
 
 
3603
 
        SetActivePane(m_panes, wnd);
3604
 
        Repaint();
3605
 
    }
3606
 
}
3607
 
 
3608
 
// Render() draws all of the pane captions, sashes,
3609
 
// backgrounds, captions, grippers, pane borders and buttons.
3610
 
// It renders the entire user interface.
3611
 
 
3612
 
void wxFrameManager::Render(wxDC* dc)
3613
 
{
3614
 
#ifdef __WXMAC__
3615
 
    dc->Clear() ;
3616
 
#endif
3617
 
    int i, part_count;
3618
 
    for (i = 0, part_count = m_uiparts.GetCount();
3619
 
         i < part_count; ++i)
3620
 
    {
3621
 
        wxDockUIPart& part = m_uiparts.Item(i);
3622
 
 
3623
 
        // don't draw hidden pane items
3624
 
        if (part.sizer_item && !part.sizer_item->IsShown())
3625
 
            continue;
3626
 
 
3627
 
        switch (part.type)
3628
 
        {
3629
 
            case wxDockUIPart::typeDockSizer:
3630
 
            case wxDockUIPart::typePaneSizer:
3631
 
                m_art->DrawSash(*dc, part.orientation, part.rect);
3632
 
                break;
3633
 
            case wxDockUIPart::typeBackground:
3634
 
                m_art->DrawBackground(*dc, part.orientation, part.rect);
3635
 
                break;
3636
 
            case wxDockUIPart::typeCaption:
3637
 
                m_art->DrawCaption(*dc, part.pane->caption, part.rect, *part.pane);
3638
 
                break;
3639
 
            case wxDockUIPart::typeGripper:
3640
 
                m_art->DrawGripper(*dc, part.rect, *part.pane);
3641
 
                break;
3642
 
            case wxDockUIPart::typePaneBorder:
3643
 
                m_art->DrawBorder(*dc, part.rect, *part.pane);
3644
 
                break;
3645
 
            case wxDockUIPart::typePaneButton:
3646
 
                m_art->DrawPaneButton(*dc, part.button->button_id,
3647
 
                        wxAUI_BUTTON_STATE_NORMAL, part.rect, *part.pane);
3648
 
                break;
3649
 
        }
3650
 
    }
3651
 
}
3652
 
 
3653
 
void wxFrameManager::Repaint(wxDC* dc)
3654
 
{
3655
 
#ifdef __WXMAC__
3656
 
    if ( dc == NULL )
3657
 
    {
3658
 
        m_frame->Refresh() ;
3659
 
        m_frame->Update() ;
3660
 
        return ;
3661
 
    }
3662
 
#endif
3663
 
    int w, h;
3664
 
    m_frame->GetClientSize(&w, &h);
3665
 
 
3666
 
    // figure out which dc to use; if one
3667
 
    // has been specified, use it, otherwise
3668
 
    // make a client dc
3669
 
    wxClientDC* client_dc = NULL;
3670
 
    if (!dc)
3671
 
    {
3672
 
        client_dc = new wxClientDC(m_frame);
3673
 
        dc = client_dc;
3674
 
    }
3675
 
 
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);
3681
 
 
3682
 
    // render all the items
3683
 
    Render(dc);
3684
 
 
3685
 
    // if we created a client_dc, delete it
3686
 
    if (client_dc)
3687
 
        delete client_dc;
3688
 
}
3689
 
 
3690
 
void wxFrameManager::OnPaint(wxPaintEvent& event)
3691
 
{
3692
 
    wxPaintDC dc(m_frame);
3693
 
    Repaint(&dc);
3694
 
}
3695
 
 
3696
 
void wxFrameManager::OnEraseBackground(wxEraseEvent& event)
3697
 
{
3698
 
#ifdef __WXMAC__
3699
 
    event.Skip() ;
3700
 
#endif
3701
 
}
3702
 
 
3703
 
void wxFrameManager::OnSize(wxSizeEvent& event)
3704
 
{
3705
 
    if (m_frame)
3706
 
    {
3707
 
        DoFrameLayout();
3708
 
        Repaint();
3709
 
    }
3710
 
    event.Skip();
3711
 
}
3712
 
 
3713
 
 
3714
 
void wxFrameManager::OnSetCursor(wxSetCursorEvent& event)
3715
 
{
3716
 
    // determine cursor
3717
 
    wxDockUIPart* part = HitTest(event.GetX(), event.GetY());
3718
 
    wxCursor cursor = wxNullCursor;
3719
 
 
3720
 
    if (part)
3721
 
    {
3722
 
        if (part->type == wxDockUIPart::typeDockSizer ||
3723
 
            part->type == wxDockUIPart::typePaneSizer)
3724
 
        {
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())
3730
 
                    return;
3731
 
 
3732
 
            // panes that may not be resized do not get a sizing cursor
3733
 
            if (part->pane && part->pane->IsFixed())
3734
 
                return;
3735
 
 
3736
 
            if (part->orientation == wxVERTICAL)
3737
 
                cursor = wxCursor(wxCURSOR_SIZEWE);
3738
 
                 else
3739
 
                cursor = wxCursor(wxCURSOR_SIZENS);
3740
 
        }
3741
 
         else if (part->type == wxDockUIPart::typeGripper)
3742
 
        {
3743
 
            cursor = wxCursor(wxCURSOR_SIZING);
3744
 
        }
3745
 
    }
3746
 
 
3747
 
    event.SetCursor(cursor);
3748
 
}
3749
 
 
3750
 
 
3751
 
 
3752
 
void wxFrameManager::UpdateButtonOnScreen(wxDockUIPart* button_ui_part,
3753
 
                                          const wxMouseEvent& event)
3754
 
{
3755
 
    wxDockUIPart* hit_test = HitTest(event.GetX(), event.GetY());
3756
 
 
3757
 
    int state = wxAUI_BUTTON_STATE_NORMAL;
3758
 
 
3759
 
    if (hit_test == button_ui_part)
3760
 
    {
3761
 
        if (event.LeftDown())
3762
 
            state = wxAUI_BUTTON_STATE_PRESSED;
3763
 
             else
3764
 
            state = wxAUI_BUTTON_STATE_HOVER;
3765
 
    }
3766
 
     else
3767
 
    {
3768
 
        if (event.LeftDown())
3769
 
            state = wxAUI_BUTTON_STATE_HOVER;
3770
 
    }
3771
 
 
3772
 
    // now repaint the button with hover state
3773
 
    wxClientDC cdc(m_frame);
3774
 
 
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);
3780
 
 
3781
 
    m_art->DrawPaneButton(cdc,
3782
 
              button_ui_part->button->button_id,
3783
 
              state,
3784
 
              button_ui_part->rect,
3785
 
              *hit_test->pane);
3786
 
}
3787
 
 
3788
 
void wxFrameManager::OnLeftDown(wxMouseEvent& event)
3789
 
{
3790
 
    wxDockUIPart* part = HitTest(event.GetX(), event.GetY());
3791
 
    if (part)
3792
 
    {
3793
 
        if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER)
3794
 
            return;
3795
 
 
3796
 
        if (part->type == wxDockUIPart::typeDockSizer ||
3797
 
            part->type == wxDockUIPart::typePaneSizer)
3798
 
        {
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())
3804
 
                    return;
3805
 
 
3806
 
            // panes that may not be resized should be ignored here
3807
 
            if (part->pane && part->pane->IsFixed())
3808
 
                return;
3809
 
 
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();
3817
 
        }
3818
 
         else if (part->type == wxDockUIPart::typePaneButton)
3819
 
        {
3820
 
            m_action = actionClickButton;
3821
 
            m_action_part = part;
3822
 
            m_action_start = wxPoint(event.m_x, event.m_y);
3823
 
            m_frame->CaptureMouse();
3824
 
 
3825
 
            UpdateButtonOnScreen(part, event);
3826
 
        }
3827
 
         else if (part->type == wxDockUIPart::typeCaption ||
3828
 
                  part->type == wxDockUIPart::typeGripper)
3829
 
        {
3830
 
            if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE)
3831
 
            {
3832
 
                // set the caption as active
3833
 
                SetActivePane(m_panes, part->pane->window);
3834
 
                Repaint();
3835
 
            }
3836
 
 
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();
3843
 
        }
3844
 
#ifdef __WXMAC__
3845
 
        else
3846
 
        {
3847
 
            event.Skip();
3848
 
        }
3849
 
#endif
3850
 
    }
3851
 
#ifdef __WXMAC__
3852
 
    else
3853
 
    {
3854
 
        event.Skip();
3855
 
    }
3856
 
#else
3857
 
    event.Skip();
3858
 
#endif
3859
 
}
3860
 
 
3861
 
 
3862
 
void wxFrameManager::OnLeftUp(wxMouseEvent& event)
3863
 
{
3864
 
    if (m_action == actionResize)
3865
 
    {
3866
 
        m_frame->ReleaseMouse();
3867
 
 
3868
 
        // get rid of the hint rectangle
3869
 
        wxScreenDC dc;
3870
 
        DrawResizeHint(dc, m_action_hintrect);
3871
 
 
3872
 
        // resize the dock or the pane
3873
 
        if (m_action_part && m_action_part->type==wxDockUIPart::typeDockSizer)
3874
 
        {
3875
 
            wxRect& rect = m_action_part->dock->rect;
3876
 
 
3877
 
            wxPoint new_pos(event.m_x - m_action_offset.x,
3878
 
                            event.m_y - m_action_offset.y);
3879
 
 
3880
 
            switch (m_action_part->dock->dock_direction)
3881
 
            {
3882
 
                case wxAUI_DOCK_LEFT:
3883
 
                    m_action_part->dock->size = new_pos.x - rect.x;
3884
 
                    break;
3885
 
                case wxAUI_DOCK_TOP:
3886
 
                    m_action_part->dock->size = new_pos.y - rect.y;
3887
 
                    break;
3888
 
                case wxAUI_DOCK_RIGHT:
3889
 
                    m_action_part->dock->size = rect.x + rect.width -
3890
 
                                  new_pos.x - m_action_part->rect.GetWidth();
3891
 
                    break;
3892
 
                case wxAUI_DOCK_BOTTOM:
3893
 
                    m_action_part->dock->size = rect.y + rect.height -
3894
 
                                  new_pos.y - m_action_part->rect.GetHeight();
3895
 
                    break;
3896
 
            }
3897
 
 
3898
 
            Update();
3899
 
            Repaint(NULL);
3900
 
        }
3901
 
         else if (m_action_part &&
3902
 
                  m_action_part->type == wxDockUIPart::typePaneSizer)
3903
 
        {
3904
 
            wxDockInfo& dock = *m_action_part->dock;
3905
 
            wxPaneInfo& pane = *m_action_part->pane;
3906
 
 
3907
 
            int total_proportion = 0;
3908
 
            int dock_pixels = 0;
3909
 
            int new_pixsize = 0;
3910
 
 
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);
3914
 
 
3915
 
            wxPoint new_pos(event.m_x - m_action_offset.x,
3916
 
                            event.m_y - m_action_offset.y);
3917
 
 
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"));
3922
 
 
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;
3927
 
                 else
3928
 
                new_pixsize = new_pos.y - pane_part->rect.y;
3929
 
 
3930
 
            // determine the size of the dock, based on orientation
3931
 
            if (dock.IsHorizontal())
3932
 
                dock_pixels = dock.rect.GetWidth();
3933
 
                 else
3934
 
                dock_pixels = dock.rect.GetHeight();
3935
 
 
3936
 
            // determine the total proportion of all resizable panes,
3937
 
            // and the total size of the dock minus the size of all
3938
 
            // the fixed panes
3939
 
            int i, dock_pane_count = dock.panes.GetCount();
3940
 
            int pane_position = -1;
3941
 
            for (i = 0; i < dock_pane_count; ++i)
3942
 
            {
3943
 
                wxPaneInfo& p = *dock.panes.Item(i);
3944
 
                if (p.window == pane.window)
3945
 
                    pane_position = i;
3946
 
 
3947
 
                // while we're at it, subtract the pane sash
3948
 
                // width from the dock width, because this would
3949
 
                // skew our proportion calculations
3950
 
                if (i > 0)
3951
 
                    dock_pixels -= sash_size;
3952
 
 
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
3956
 
                if (p.IsFixed())
3957
 
                {
3958
 
                    if (dock.IsHorizontal())
3959
 
                        dock_pixels -= p.best_size.x;
3960
 
                         else
3961
 
                        dock_pixels -= p.best_size.y;
3962
 
                }
3963
 
                 else
3964
 
                {
3965
 
                    total_proportion += p.dock_proportion;
3966
 
                }
3967
 
            }
3968
 
 
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)
3975
 
            {
3976
 
                wxPaneInfo& p = *dock.panes.Item(i);
3977
 
                if (!p.IsFixed())
3978
 
                {
3979
 
                    borrow_pane = i;
3980
 
                    break;
3981
 
                }
3982
 
            }
3983
 
 
3984
 
 
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"));
3988
 
 
3989
 
            // prevent division by zero
3990
 
            if (dock_pixels == 0 || total_proportion == 0 || borrow_pane == -1)
3991
 
            {
3992
 
                m_action = actionNone;
3993
 
                return;
3994
 
            }
3995
 
 
3996
 
            // calculate the new proportion of the pane
3997
 
            int new_proportion = (new_pixsize*total_proportion)/dock_pixels;
3998
 
 
3999
 
            // default minimum size
4000
 
            int min_size = 0;
4001
 
 
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())
4007
 
            {
4008
 
                min_size = 0;
4009
 
 
4010
 
                if (pane.HasBorder())
4011
 
                    min_size += (pane_border_size*2);
4012
 
 
4013
 
                // calculate minimum size with decorations (border,caption)
4014
 
                if (pane_part->orientation == wxVERTICAL)
4015
 
                {
4016
 
                    min_size += pane.min_size.y;
4017
 
                    if (pane.HasCaption())
4018
 
                        min_size += caption_size;
4019
 
                }
4020
 
                 else
4021
 
                {
4022
 
                    min_size += pane.min_size.x;
4023
 
                }
4024
 
            }
4025
 
 
4026
 
 
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.
4031
 
            min_size++;
4032
 
 
4033
 
            int min_proportion = (min_size*total_proportion)/dock_pixels;
4034
 
 
4035
 
            if (new_proportion < min_proportion)
4036
 
                new_proportion = min_proportion;
4037
 
 
4038
 
 
4039
 
 
4040
 
            int prop_diff = new_proportion - pane.dock_proportion;
4041
 
 
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;
4046
 
 
4047
 
            // repaint
4048
 
            Update();
4049
 
            Repaint(NULL);
4050
 
        }
4051
 
    }
4052
 
     else if (m_action == actionClickButton)
4053
 
    {
4054
 
        m_hover_button = NULL;
4055
 
        m_frame->ReleaseMouse();
4056
 
        UpdateButtonOnScreen(m_action_part, event);
4057
 
 
4058
 
        // make sure we're still over the item that was originally clicked
4059
 
        if (m_action_part == HitTest(event.GetX(), event.GetY()))
4060
 
        {
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);
4065
 
            ProcessMgrEvent(e);
4066
 
        }
4067
 
    }
4068
 
     else if (m_action == actionClickCaption)
4069
 
    {
4070
 
        m_frame->ReleaseMouse();
4071
 
    }
4072
 
     else if (m_action == actionDragFloatingPane)
4073
 
    {
4074
 
        m_frame->ReleaseMouse();
4075
 
    }
4076
 
     else if (m_action == actionDragToolbarPane)
4077
 
    {
4078
 
        m_frame->ReleaseMouse();
4079
 
 
4080
 
        wxPaneInfo& pane = GetPane(m_action_window);
4081
 
        wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
4082
 
 
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)
4088
 
        {
4089
 
            wxDockInfo& dock = *docks.Item(0);
4090
 
 
4091
 
            wxArrayInt pane_positions, pane_sizes;
4092
 
            GetPanePositionsAndSizes(dock, pane_positions, pane_sizes);
4093
 
 
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];
4097
 
        }
4098
 
 
4099
 
        pane.state &= ~wxPaneInfo::actionPane;
4100
 
        Update();
4101
 
    }
4102
 
     else
4103
 
    {
4104
 
        event.Skip();
4105
 
    }
4106
 
 
4107
 
    m_action = actionNone;
4108
 
    m_last_mouse_move = wxPoint(); // see comment in OnMotion()
4109
 
}
4110
 
 
4111
 
 
4112
 
void wxFrameManager::OnMotion(wxMouseEvent& event)
4113
 
{
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
4119
 
 
4120
 
    wxPoint mouse_pos = event.GetPosition();
4121
 
    if (m_last_mouse_move == mouse_pos)
4122
 
        return;
4123
 
    m_last_mouse_move = mouse_pos;
4124
 
 
4125
 
 
4126
 
    if (m_action == actionResize)
4127
 
    {
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);
4131
 
             else
4132
 
            pos.x = wxMax(0, event.m_x - m_action_offset.x);
4133
 
 
4134
 
        wxRect rect(m_frame->ClientToScreen(pos),
4135
 
                    m_action_part->rect.GetSize());
4136
 
 
4137
 
        wxScreenDC dc;
4138
 
        if (!m_action_hintrect.IsEmpty())
4139
 
            DrawResizeHint(dc, m_action_hintrect);
4140
 
        DrawResizeHint(dc, rect);
4141
 
        m_action_hintrect = rect;
4142
 
    }
4143
 
     else if (m_action == actionClickCaption)
4144
 
    {
4145
 
        int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
4146
 
        int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
4147
 
 
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)
4153
 
        {
4154
 
            wxPaneInfo* pane_info = m_action_part->pane;
4155
 
 
4156
 
            if (!pane_info->IsToolbar())
4157
 
            {
4158
 
                if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) &&
4159
 
                    pane_info->IsFloatable())
4160
 
                {
4161
 
                    m_action = actionDragFloatingPane;
4162
 
 
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);
4167
 
                    // float the window
4168
 
                    pane_info->Float();
4169
 
                    Update();
4170
 
 
4171
 
                    m_action_window = pane_info->frame;
4172
 
 
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;
4181
 
                }
4182
 
            }
4183
 
             else
4184
 
            {
4185
 
                m_action = actionDragToolbarPane;
4186
 
                m_action_window = pane_info->window;
4187
 
            }
4188
 
        }
4189
 
    }
4190
 
     else if (m_action == actionDragFloatingPane)
4191
 
    {
4192
 
        // m_action_window might have gone away already
4193
 
        if ( m_action_window )
4194
 
        {
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);
4198
 
        }
4199
 
    }
4200
 
     else if (m_action == actionDragToolbarPane)
4201
 
    {
4202
 
        wxPaneInfo& pane = GetPane(m_action_window);
4203
 
        wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
4204
 
 
4205
 
        pane.state |= wxPaneInfo::actionPane;
4206
 
 
4207
 
        wxPoint pt = event.GetPosition();
4208
 
        DoDrop(m_docks, m_panes, pane, pt, m_action_offset);
4209
 
 
4210
 
        // if DoDrop() decided to float the pane, set up
4211
 
        // the floating pane's initial position
4212
 
        if (pane.IsFloating())
4213
 
        {
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);
4217
 
        }
4218
 
 
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
4223
 
        Update();
4224
 
 
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())
4229
 
        {
4230
 
            pane.state &= ~wxPaneInfo::actionPane;
4231
 
            m_action = actionDragFloatingPane;
4232
 
            m_action_window = pane.frame;
4233
 
        }
4234
 
    }
4235
 
     else
4236
 
    {
4237
 
        wxDockUIPart* part = HitTest(event.GetX(), event.GetY());
4238
 
        if (part && part->type == wxDockUIPart::typePaneButton)
4239
 
        {
4240
 
            if (part != m_hover_button)
4241
 
            {
4242
 
                // make the old button normal
4243
 
                if (m_hover_button)
4244
 
                    UpdateButtonOnScreen(m_hover_button, event);
4245
 
 
4246
 
                // mouse is over a button, so repaint the
4247
 
                // button in hover mode
4248
 
                UpdateButtonOnScreen(part, event);
4249
 
                m_hover_button = part;
4250
 
            }
4251
 
        }
4252
 
         else
4253
 
        {
4254
 
            if (m_hover_button)
4255
 
            {
4256
 
                m_hover_button = NULL;
4257
 
                Repaint();
4258
 
            }
4259
 
             else
4260
 
            {
4261
 
                event.Skip();
4262
 
            }
4263
 
        }
4264
 
    }
4265
 
}
4266
 
 
4267
 
void wxFrameManager::OnLeaveWindow(wxMouseEvent& event)
4268
 
{
4269
 
    if (m_hover_button)
4270
 
    {
4271
 
        m_hover_button = NULL;
4272
 
        Repaint();
4273
 
    }
4274
 
}
4275
 
 
4276
 
void wxFrameManager::OnChildFocus(wxChildFocusEvent& event)
4277
 
{
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)
4282
 
    {
4283
 
        if (GetPane(event.GetWindow()).IsOk())
4284
 
        {
4285
 
            SetActivePane(m_panes, event.GetWindow());
4286
 
            m_frame->Refresh();
4287
 
        }
4288
 
    }
4289
 
}
4290
 
 
4291
 
 
4292
 
// OnPaneButton() is an event handler that is called
4293
 
// when a pane button has been pressed.
4294
 
void wxFrameManager::OnPaneButton(wxFrameManagerEvent& event)
4295
 
{
4296
 
    wxPaneInfo& pane = *(event.pane);
4297
 
 
4298
 
    if (event.button == wxPaneInfo::buttonClose)
4299
 
    {
4300
 
        pane.Hide();
4301
 
        Update();
4302
 
    }
4303
 
     else if (event.button == wxPaneInfo::buttonPin)
4304
 
    {
4305
 
        if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) &&
4306
 
            pane.IsFloatable())
4307
 
                pane.Float();
4308
 
        Update();
4309
 
    }
4310
 
}
4311
 
 
4312
 
#endif // wxCHECK_VERSION