]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/fl/controlbar.cpp
fixes for animated GIFs playing (patch 1097003)
[wxWidgets.git] / contrib / src / fl / controlbar.cpp
CommitLineData
8e08b761 1/////////////////////////////////////////////////////////////////////////////
4cbc57f0
JS
2// Name: controlbar.cpp
3// Purpose: Implementation for main controlbar classes.
8e08b761
JS
4// Author: Aleksandras Gluchovas
5// Modified by:
6// Created: 06/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Aleksandras Gluchovas
5515f252 9// Licence: wxWindows license
8e08b761
JS
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13 #pragma implementation "controlbar.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include "wx/wx.h"
25#endif
26
27#include <math.h>
28#include <stdlib.h>
29
30#include "wx/string.h"
31#include "wx/utils.h" // import wxMin,wxMax macros
32#include "wx/minifram.h"
33
34#include "wx/fl/controlbar.h"
35
36// import classes of default plugins
37
38#include "wx/fl/panedrawpl.h"
39#include "wx/fl/rowlayoutpl.h"
40#include "wx/fl/antiflickpl.h"
41#include "wx/fl/bardragpl.h"
42#include "wx/fl/cbcustom.h"
43
44#include "wx/fl/gcupdatesmgr.h" // import default updates manager class ("garbage-collecting" one)
45#include "wx/fl/updatesmgr.h"
46
47#include "wx/fl/toolwnd.h"
48
49// These are the event IDs being initialized to a value to
50// meet the new event paradigm as of wx2.3.0. Probably we
51// should find a way to make these be non-global, but this
52// works for right now.
5515f252
GT
53 wxEventType cbEVT_PL_LEFT_DOWN = wxNewEventType();
54 wxEventType cbEVT_PL_LEFT_UP = wxNewEventType();
55 wxEventType cbEVT_PL_RIGHT_DOWN = wxNewEventType();
56 wxEventType cbEVT_PL_RIGHT_UP = wxNewEventType();
57 wxEventType cbEVT_PL_MOTION = wxNewEventType();
58
59 wxEventType cbEVT_PL_LEFT_DCLICK = wxNewEventType();
60
61 wxEventType cbEVT_PL_LAYOUT_ROW = wxNewEventType();
62 wxEventType cbEVT_PL_RESIZE_ROW = wxNewEventType();
63 wxEventType cbEVT_PL_LAYOUT_ROWS = wxNewEventType();
64 wxEventType cbEVT_PL_INSERT_BAR = wxNewEventType();
65 wxEventType cbEVT_PL_RESIZE_BAR = wxNewEventType();
66 wxEventType cbEVT_PL_REMOVE_BAR = wxNewEventType();
67 wxEventType cbEVT_PL_SIZE_BAR_WND = wxNewEventType();
68
69 wxEventType cbEVT_PL_DRAW_BAR_DECOR = wxNewEventType();
70 wxEventType cbEVT_PL_DRAW_ROW_DECOR = wxNewEventType();
71 wxEventType cbEVT_PL_DRAW_PANE_DECOR = wxNewEventType();
72 wxEventType cbEVT_PL_DRAW_BAR_HANDLES = wxNewEventType();
73 wxEventType cbEVT_PL_DRAW_ROW_HANDLES = wxNewEventType();
74 wxEventType cbEVT_PL_DRAW_ROW_BKGROUND = wxNewEventType();
75 wxEventType cbEVT_PL_DRAW_PANE_BKGROUND = wxNewEventType();
76
77 wxEventType cbEVT_PL_START_BAR_DRAGGING = wxNewEventType();
78 wxEventType cbEVT_PL_DRAW_HINT_RECT = wxNewEventType();
79
80 wxEventType cbEVT_PL_START_DRAW_IN_AREA = wxNewEventType();
81 wxEventType cbEVT_PL_FINISH_DRAW_IN_AREA = wxNewEventType();
82
83 wxEventType cbEVT_PL_CUSTOMIZE_BAR = wxNewEventType();
84 wxEventType cbEVT_PL_CUSTOMIZE_LAYOUT = wxNewEventType();
85
86 wxEventType wxCUSTOM_CB_PLUGIN_EVENTS_START_AT = wxNewEventType();
8e08b761
JS
87
88// some ascii-art, still can't get these *nice* cursors working on wx... :-(
89
8552e6f0
MB
90/*
91// FIXME:: see places where _gHorizCursorImg is used
92
8e08b761
JS
93static const char* _gHorizCursorImg[] =
94{
5515f252
GT
95 "............XX....XX............",
96 "............XX....XX............",
97 "............XX....XX............",
98 "............XX....XX............",
99 "............XX....XX............",
100 "...X........XX....XX........X...",
101 "..XX........XX....XX........XX..",
102 ".XXX........XX....XX........XXX.",
103 "XXXXXXXXXXXXXX....XXXXXXXXXXXXXX",
104 ".XXX........XX....XX........XXX.",
105 "..XX........XX....XX........XX..",
106 "...X........XX....XX........X...",
107 "............XX....XX............",
108 "............XX....XX............",
109 "............XX....XX............",
110 "............XX....XX............"
8e08b761
JS
111};
112
113static const char* _gVertCursorImg[] =
114{
5515f252
GT
115 "................X...............",
116 "...............XXX..............",
117 "..............XXXXX.............",
118 ".............XXXXXXX............",
119 "................X...............",
120 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
121 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
122 "................................",
123 "................................",
124 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
125 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
126 "................X...............",
127 ".............XXXXXXX............",
128 "..............XXXXX.............",
129 "...............XXX..............",
130 "................X..............."
8e08b761 131};
8552e6f0 132*/
8e08b761
JS
133
134// helper inline functions
135
136static inline bool rect_contains_point( const wxRect& rect, int x, int y )
137{
5515f252
GT
138 return ( x >= rect.x &&
139 y >= rect.y &&
140 x < rect.x + rect.width &&
141 y < rect.y + rect.height );
8e08b761
JS
142}
143
144static inline bool rect_hits_rect( const wxRect& r1, const wxRect& r2 )
145{
5515f252
GT
146 if ( ( r2.x >= r1.x && r2.x <= r1.x + r1.width ) ||
147 ( r1.x >= r2.x && r1.x <= r2.x + r2.width ) )
8e08b761 148
5515f252
GT
149 if ( ( r2.y >= r1.y && r2.y <= r1.y + r1.height ) ||
150 ( r1.y >= r2.y && r1.y <= r2.y + r2.height ) )
151
152 return 1;
8e08b761 153
5515f252 154 return 0;
8e08b761
JS
155}
156
157static inline void hide_rect( wxRect& r )
158{
5515f252
GT
159 r.x = 32768;
160 r.y = 32768;
161 r.width = 1;
162 r.height = 1;
8e08b761
JS
163}
164
165static inline void clip_rect_against_rect( wxRect& r1, const wxRect& r2 )
166{
5515f252
GT
167 if ( r1.x < r2.x ||
168 r1.y < r2.y ||
169 r1.x >= r2.x + r2.width ||
170 r1.y >= r2.y + r2.height
171 )
172 {
173 hide_rect( r1 );
174 return;
175 }
176 else
177 {
178 if ( r1.x + r1.width > r2.x + r2.width )
8e08b761 179
5515f252 180 r1.width = r2.x + r2.width - r1.x;
8e08b761 181
5515f252 182 if ( r1.y + r1.height > r2.y + r2.height )
8e08b761 183
5515f252
GT
184 r1.height = r2.y + r2.height - r1.y;
185 }
8e08b761
JS
186}
187
188/***** Implementation for class cbBarSpy *****/
189
190IMPLEMENT_DYNAMIC_CLASS( cbBarSpy, wxEvtHandler )
191
192cbBarSpy::cbBarSpy(void)
5515f252
GT
193 : mpLayout(0),
194 mpBarWnd(0)
8e08b761
JS
195{}
196
197cbBarSpy::cbBarSpy( wxFrameLayout* pPanel )
198
5515f252
GT
199 : mpLayout(pPanel),
200 mpBarWnd(0)
8e08b761
JS
201{}
202
203void cbBarSpy::SetBarWindow( wxWindow* pWnd )
204{
5515f252 205 mpBarWnd = pWnd;
8e08b761
JS
206}
207
208bool cbBarSpy::ProcessEvent(wxEvent& event)
209{
5515f252 210 bool handled = wxEvtHandler::ProcessEvent( event );
8e08b761 211
5515f252 212 int type = event.GetEventType();
8e08b761 213
5515f252
GT
214 if ( !handled && ( type == wxEVT_LEFT_DOWN ||
215 type == wxEVT_LEFT_DCLICK ) )
216 {
217 wxMouseEvent& mevent = *((wxMouseEvent*)&event);
8e08b761 218
5515f252
GT
219 int x = mevent.m_x;
220 int y = mevent.m_y;
8e08b761 221
5515f252
GT
222 mpBarWnd->ClientToScreen( &x, &y );
223 mpLayout->GetParentFrame().ScreenToClient( &x, &y );
8e08b761 224
5515f252
GT
225 mevent.m_x = x;
226 mevent.m_y = y;
8e08b761 227
5515f252 228 // forwared not-handled event to frame-layout
8e08b761 229
5515f252
GT
230 if ( type == wxEVT_LEFT_DOWN )
231 {
232 //mpLayout->OnLButtonDown( mevent );
233 event.Skip();
234 }
235 else
236 mpLayout->OnLDblClick( mevent );
8e08b761 237
c82c42d4 238 //event.Skip(false);
5515f252 239 }
8e08b761 240
5515f252 241 return handled;
8e08b761
JS
242}
243
244/***** Implementation for class wxFrameLayout *****/
245
246IMPLEMENT_DYNAMIC_CLASS( wxFrameLayout, wxEvtHandler )
247
248BEGIN_EVENT_TABLE( wxFrameLayout, wxEvtHandler )
249
5515f252
GT
250 EVT_PAINT ( wxFrameLayout::OnPaint )
251 EVT_SIZE ( wxFrameLayout::OnSize )
252 EVT_LEFT_DOWN ( wxFrameLayout::OnLButtonDown )
253 EVT_LEFT_UP ( wxFrameLayout::OnLButtonUp )
254 EVT_RIGHT_DOWN ( wxFrameLayout::OnRButtonDown )
255 EVT_RIGHT_UP ( wxFrameLayout::OnRButtonUp )
256 EVT_MOTION ( wxFrameLayout::OnMouseMove )
8e08b761 257
5515f252 258 EVT_LEFT_DCLICK( wxFrameLayout::OnLDblClick )
8e08b761 259
5515f252 260 EVT_IDLE ( wxFrameLayout::OnIdle )
8e08b761 261
5515f252 262 EVT_ERASE_BACKGROUND( wxFrameLayout::OnEraseBackground )
8e08b761
JS
263
264END_EVENT_TABLE()
265
266// FIXME:: how to eliminate these cut&pasted constructors?
267
268wxFrameLayout::wxFrameLayout(void)
269
5515f252
GT
270 : mpFrame ( NULL ),
271 mpFrameClient( NULL ),
8e08b761 272
e1c6c6ae
VS
273 mDarkPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW), 1, wxSOLID ),
274 mLightPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT), 1, wxSOLID ),
275 mGrayPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE), 1, wxSOLID ),
5515f252 276 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID ),
e1c6c6ae 277 mBorderPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE), 1, wxSOLID ),
8e08b761 278
5515f252 279 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT ),
8e08b761 280
5515f252
GT
281 mpPaneInFocus( NULL ),
282 mpLRUPane ( NULL ),
8e08b761
JS
283
284
5515f252
GT
285 mpTopPlugin ( NULL ),
286 mpCaputesInput( NULL ),
8e08b761 287
c82c42d4
WS
288 mClientWndRefreshPending( false ),
289 mRecalcPending( true ),
290 mCheckFocusWhenIdle( false )
8e08b761 291{
5515f252 292 CreateCursors();
8e08b761 293
5515f252
GT
294 int i;
295 for ( i = 0; i != MAX_PANES; ++i )
296 mPanes[i] = NULL;
8e08b761 297
5515f252 298 mFloatingOn = CanReparent();
8e08b761
JS
299}
300
301wxFrameLayout::wxFrameLayout( wxWindow* pParentFrame, wxWindow* pFrameClient, bool activateNow )
302
5515f252
GT
303 : mpFrame( pParentFrame ),
304 mpFrameClient(pFrameClient),
8e08b761 305
e1c6c6ae
VS
306 mDarkPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW), 1, wxSOLID ),
307 mLightPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT), 1, wxSOLID ),
308 mGrayPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE), 1, wxSOLID ),
5515f252 309 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID ),
e1c6c6ae 310 mBorderPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE), 1, wxSOLID ),
8e08b761 311
5515f252 312 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT ),
8e08b761 313
5515f252
GT
314 mpPaneInFocus( NULL ),
315 mpLRUPane ( NULL ),
8e08b761 316
c82c42d4 317 mFloatingOn ( true ),
8e08b761 318
5515f252
GT
319 mpTopPlugin ( NULL ),
320 mpCaputesInput( NULL ),
321
c82c42d4
WS
322 mClientWndRefreshPending( false ),
323 mRecalcPending( true ),
324 mCheckFocusWhenIdle( false ),
5515f252 325
8e08b761
JS
326 mpUpdatesMgr( NULL )
327{
5515f252 328 CreateCursors();
8e08b761 329
5515f252
GT
330 int i;
331 for ( i = 0; i != MAX_PANES; ++i )
332 mPanes[i] = new cbDockPane( i, this );
8e08b761 333
5515f252
GT
334 if ( activateNow )
335 {
336 HookUpToFrame();
8e08b761 337
5515f252
GT
338 // FOR NOW::
339 // DBG:: set RED color of frame's background for the
340 // prurpose of tracking engine bugs "visually"
8e08b761 341
e1c6c6ae 342 GetParentFrame().SetBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE) );
5515f252 343 }
8e08b761 344
5515f252 345 mFloatingOn = CanReparent();
8e08b761
JS
346}
347
4cbc57f0 348// NOTE:: below are the only platform-check "ifdef"s in the docking system!
8e08b761
JS
349
350bool wxFrameLayout::CanReparent()
351{
352#ifdef __WXMSW__
c82c42d4 353 return true;
fdaebb05
VZ
354#elif defined(__WXGTK20__)
355 return TRUE;
8e08b761 356#elif defined (__WXGTK__)
c82c42d4
WS
357 //return true;
358 return false;
8e08b761
JS
359#else
360
c82c42d4 361 return false; // reparenting is not yet supported by Motif and others
8e08b761
JS
362#endif
363}
364
365/*
366#ifdef __WXMSW__
5515f252 367 #inlcude "windows.h"
8e08b761
JS
368#endif
369*/
370
371void wxFrameLayout::ReparentWindow( wxWindow* pChild, wxWindow* pNewParent )
372{
373#ifdef __WXMSW__
374#if 0
375
5515f252
GT
376 if ( pChild->GetParent() )
377 {
378 bool success = pChild->GetParent()->GetChildren().DeleteObject( pChild );
8e08b761 379
5515f252
GT
380 wxASSERT( success ); // DBG::
381 }
8e08b761 382
5515f252 383 ::SetParent( (HWND)pChild->m_hWnd, (HWND)pNewParent->m_hWnd );
8e08b761 384
5515f252 385 pNewParent->GetChildren().Append( pChild );
8e08b761 386
5515f252 387 pChild->SetParent( pNewParent );
8e08b761
JS
388#endif
389 pChild->Reparent(pNewParent);
390
fdaebb05
VZ
391 return;
392#elif defined(__WXGTK20__)
393 pChild->Reparent(pNewParent);
394
5515f252 395 return;
618f2efa 396#elif defined(__WXGTK__) || defined(__WXX11__)
5515f252 397 // FOR NOW:: floating with wxGtk still very buggy
8e08b761 398
5515f252 399 return;
8e08b761 400
5515f252 401 //pChild->ReParent( pNewParent );
8e08b761 402
5515f252 403 //return;
8e08b761 404#else
5515f252 405 wxMessageBox( "Sorry, docking is not supported for ports other than MSW and wxGTK" );
8e08b761
JS
406#endif
407}
408
409void wxFrameLayout::DestroyBarWindows()
410{
b02a6dc2 411 wxObjectList::compatibility_iterator pSpy = mBarSpyList.GetFirst();
8e08b761 412
5515f252
GT
413 while( pSpy )
414 {
8495ba53 415 cbBarSpy& spy = *((cbBarSpy*)pSpy->GetData());
8e08b761 416
5515f252 417 if ( spy.mpBarWnd->GetEventHandler() == &spy )
8e08b761 418
5515f252 419 spy.mpBarWnd->PopEventHandler();
8e08b761 420
5515f252 421 delete &spy;
8e08b761 422
8495ba53 423 pSpy = pSpy->GetNext();
5515f252 424 }
8e08b761 425
5515f252 426 mBarSpyList.Clear();
8e08b761 427
5515f252
GT
428 size_t i;
429 for ( i = 0; i != mAllBars.Count(); ++i )
430 {
431 if ( mAllBars[i]->mpBarWnd )
432 {
433 mAllBars[i]->mpBarWnd->Destroy();
434 mAllBars[i]->mpBarWnd = NULL;
435 }
436 }
8e08b761
JS
437}
438
439void wxFrameLayout::ShowFloatedWindows( bool show )
440{
b02a6dc2 441 wxObjectList::compatibility_iterator pNode = mFloatedFrames.GetFirst();
8e08b761 442
5515f252
GT
443 while( pNode )
444 {
8495ba53 445 cbFloatedBarWindow* pFFrm = ((cbFloatedBarWindow*)pNode->GetData());
8e08b761 446
5515f252 447 pFFrm->Show( show );
8e08b761 448
8495ba53 449 pNode = pNode->GetNext();
5515f252 450 }
8e08b761
JS
451}
452
453wxFrameLayout::~wxFrameLayout()
454{
8552e6f0
MB
455 size_t i;
456
5515f252 457 UnhookFromFrame();
8e08b761 458
5515f252 459 if ( mpUpdatesMgr )
8e08b761
JS
460 delete mpUpdatesMgr;
461
462 PopAllPlugins();
463
5515f252 464 // destoy the chain of plugins from left to right
8e08b761 465
5515f252 466 wxEvtHandler* pCur = mpTopPlugin;
8e08b761 467
5515f252 468 if ( pCur )
8e08b761 469
5515f252 470 while ( pCur->GetPreviousHandler() )
8e08b761 471
5515f252 472 pCur = pCur->GetPreviousHandler();
8e08b761 473
5515f252
GT
474 while ( pCur )
475 {
476 wxEvtHandler* pNext = pCur->GetNextHandler();
8e08b761 477
5515f252 478 delete pCur;
8e08b761 479
5515f252
GT
480 pCur = pNext;
481 }
8e08b761 482
5515f252 483 // destroy contents of arrays and lists
8e08b761 484
5515f252
GT
485 for ( i = 0; i != MAX_PANES; ++i )
486 {
487 if ( mPanes[i] )
8e08b761 488 delete mPanes[i];
5515f252
GT
489 }
490 if ( mpHorizCursor )
8e08b761 491 delete mpHorizCursor;
5515f252 492 if ( mpVertCursor )
8e08b761 493 delete mpVertCursor;
5515f252 494 if ( mpNormalCursor )
8e08b761 495 delete mpNormalCursor;
5515f252 496 if ( mpDragCursor )
8e08b761 497 delete mpDragCursor;
5515f252 498 if ( mpNECursor )
8e08b761
JS
499 delete mpNECursor;
500
b02a6dc2 501 wxObjectList::compatibility_iterator pSpy = mBarSpyList.GetFirst();
8e08b761 502
5515f252
GT
503 while( pSpy )
504 {
8495ba53 505 cbBarSpy& spy = *((cbBarSpy*)pSpy->GetData());
8e08b761 506
5515f252 507 if ( spy.mpBarWnd->GetEventHandler() == &spy )
8e08b761 508
5515f252 509 spy.mpBarWnd->PopEventHandler();
8e08b761 510
5515f252 511 delete &spy;
8e08b761 512
8495ba53 513 pSpy = pSpy->GetNext();
5515f252 514 }
8e08b761 515
5515f252
GT
516 for ( i = 0; i != mAllBars.Count(); ++i )
517 delete mAllBars[i];
8e08b761
JS
518}
519
520void wxFrameLayout::EnableFloating( bool enable )
521{
5515f252 522 mFloatingOn = enable && CanReparent();
8e08b761
JS
523}
524
525void wxFrameLayout::Activate()
526{
5515f252 527 HookUpToFrame();
8e08b761 528
c82c42d4 529 RefreshNow( true );
8e08b761 530
c82c42d4 531 ShowFloatedWindows( true );
8e08b761
JS
532}
533
534void wxFrameLayout::Deactivate()
535{
c82c42d4 536 ShowFloatedWindows( false );
8e08b761 537
5515f252 538 UnhookFromFrame();
8e08b761 539
5515f252 540 HideBarWindows();
8e08b761
JS
541}
542
543void wxFrameLayout::SetFrameClient( wxWindow* pFrameClient )
544{
5515f252 545 mpFrameClient = pFrameClient;
8e08b761
JS
546}
547
548wxWindow* wxFrameLayout::GetFrameClient()
549{
5515f252 550 return mpFrameClient;
8e08b761
JS
551}
552
553cbUpdatesManagerBase& wxFrameLayout::GetUpdatesManager()
554{
5515f252 555 if ( !mpUpdatesMgr )
8e08b761
JS
556 mpUpdatesMgr = CreateUpdatesManager();
557
5515f252 558 return *mpUpdatesMgr;
8e08b761
JS
559}
560
561void wxFrameLayout::SetUpdatesManager( cbUpdatesManagerBase* pUMgr )
562{
5515f252 563 if ( mpUpdatesMgr )
8e08b761
JS
564 delete mpUpdatesMgr;
565
5515f252 566 mpUpdatesMgr = pUMgr;
8e08b761 567
5515f252 568 mpUpdatesMgr->SetLayout( this );
8e08b761
JS
569}
570
571cbUpdatesManagerBase* wxFrameLayout::CreateUpdatesManager()
572{
5515f252
GT
573 return new cbGCUpdatesMgr( this );
574 //return new cbSimpleUpdatesMgr( this );
8e08b761
JS
575}
576
577void wxFrameLayout::AddBar( wxWindow* pBarWnd,
578 const cbDimInfo& dimInfo,
579 int alignment,
580 int rowNo,
581 int columnPos,
582 const wxString& name,
583 bool spyEvents,
584 int state
5515f252 585 )
8e08b761 586{
5515f252
GT
587 if ( pBarWnd && spyEvents )
588 {
589 // hook up spy to bar window
590 cbBarSpy* pSpy = new cbBarSpy( this );
8e08b761 591
5515f252
GT
592 pSpy->SetBarWindow( pBarWnd );
593 pBarWnd->PushEventHandler( pSpy );
8e08b761 594
5515f252
GT
595 mBarSpyList.Append( pSpy );
596 }
8e08b761 597
5515f252 598 cbBarInfo* pInfo = new cbBarInfo();
8e08b761 599
5515f252
GT
600 pInfo->mName = name;
601 pInfo->mpBarWnd = pBarWnd;
602 pInfo->mDimInfo = dimInfo;
fdaebb05 603 pInfo->mDimInfo.mLRUPane = alignment;
5515f252
GT
604 pInfo->mState = state;
605 pInfo->mAlignment = alignment;
606 pInfo->mRowNo = rowNo;
607 pInfo->mBounds.x = columnPos;
8e08b761 608
5515f252 609 mAllBars.Add( pInfo );
8e08b761 610
5515f252 611 DoSetBarState( pInfo );
8e08b761
JS
612}
613
614bool wxFrameLayout::RedockBar( cbBarInfo* pBar,
5515f252
GT
615 const wxRect& shapeInParent,
616 cbDockPane* pToPane,
617 bool updateNow )
8e08b761 618{
5515f252
GT
619 if ( !pToPane )
620
621 pToPane = HitTestPanes( shapeInParent, NULL );
8e08b761 622
5515f252
GT
623 if ( !pToPane )
624
c82c42d4 625 return false; // bar's shape does not hit any pane
5515f252 626 // - redocking is NOT possible
8e08b761 627
5515f252 628 cbDockPane* pBarPane = GetBarPane( pBar );
8e08b761 629
5515f252 630 if ( updateNow )
8e08b761 631
5515f252 632 GetUpdatesManager().OnStartChanges();
8e08b761 633
5515f252 634 pBarPane->RemoveBar( pBar );
8e08b761 635
4cbc57f0 636 // FIXME FIXME:: the recalculation below may be a *huge* performance
5515f252
GT
637 // hit, it could be eliminated though...
638 // but first the "pane-postion-changed" problem
4cbc57f0 639 // has to be fixed
8e08b761 640
c82c42d4 641 RecalcLayout( false );
8e08b761 642
5515f252 643 pToPane->InsertBar( pBar, shapeInParent );
8e08b761 644
c82c42d4 645 RecalcLayout( false );
8e08b761 646
5515f252 647 // finish update "transaction"
8e08b761 648
5515f252
GT
649 if ( updateNow )
650 {
651 GetUpdatesManager().OnFinishChanges();
652 GetUpdatesManager().UpdateNow();
653 }
8e08b761 654
c82c42d4 655 return true;
8e08b761
JS
656}
657
658cbBarInfo* wxFrameLayout::FindBarByName( const wxString& name )
659{
5515f252
GT
660 size_t i;
661 for ( i = 0; i != mAllBars.Count(); ++i )
662 if ( mAllBars[i]->mName == name )
663 return mAllBars[i];
8e08b761 664
5515f252 665 return NULL;
8e08b761
JS
666}
667
668cbBarInfo* wxFrameLayout::FindBarByWindow( const wxWindow* pWnd )
669{
5515f252
GT
670 size_t i;
671 for ( i = 0; i != mAllBars.Count(); ++i )
672 if ( mAllBars[i]->mpBarWnd == pWnd )
673 return mAllBars[i];
8e08b761 674
5515f252 675 return NULL;
8e08b761
JS
676}
677
678BarArrayT& wxFrameLayout::GetBars()
679{
5515f252 680 return mAllBars;
8e08b761
JS
681}
682
683void wxFrameLayout::SetBarState( cbBarInfo* pBar, int newState, bool updateNow )
684{
fc7c8ae9 685 if ( newState == wxCBAR_FLOATING && !(mFloatingOn && pBar->mFloatingOn))
8e08b761 686
5515f252 687 return;
8e08b761 688
5515f252 689 if ( updateNow )
8e08b761 690
5515f252 691 GetUpdatesManager().OnStartChanges();
8e08b761 692
c82c42d4 693 pBar->mUMgrData.SetDirty(true);
8e08b761 694
5515f252 695 // check bar's previous state
8e08b761 696
5515f252
GT
697 if ( pBar->mState != wxCBAR_HIDDEN && pBar->mState != wxCBAR_FLOATING )
698 {
699 cbDockPane* pPane;
700 cbRowInfo* pRow;
8e08b761 701
8552e6f0
MB
702 #ifdef __WXDEBUG__
703 bool success =
704 #endif
705 LocateBar( pBar, &pRow, &pPane );
8e08b761 706
5515f252 707 wxASSERT( success ); // DBG::
8e08b761 708
5515f252 709 // save LRU-dim info before removing bar
8e08b761 710
5515f252
GT
711 pBar->mDimInfo.mLRUPane = pPane->GetAlignment();
712 pBar->mDimInfo.mBounds[ pPane->GetAlignment() ] = pBar->mBounds;
8e08b761 713
5515f252 714 // remove it from the pane it was docked on
8e08b761 715
5515f252 716 pPane->RemoveBar( pBar );
8e08b761 717
5515f252 718 }
8e08b761 719
5515f252
GT
720 if ( pBar->mState == wxCBAR_FLOATING && newState != wxCBAR_FLOATING )
721 {
4cbc57f0
JS
722 // remove bar's window from the containing mini-frame
723 // and set its parent to be layout's parent frame
8e08b761 724
5515f252
GT
725 if ( pBar->mpBarWnd )
726 {
c82c42d4 727 pBar->mpBarWnd->Show(false); // to avoid flicker upon reparenting
8e08b761 728
b02a6dc2 729 wxObjectList::compatibility_iterator pNode = mFloatedFrames.GetFirst();
8e08b761 730
5515f252
GT
731 while( pNode )
732 {
8495ba53 733 cbFloatedBarWindow* pFFrm = ((cbFloatedBarWindow*)pNode->GetData());
8e08b761 734
5515f252
GT
735 if ( pFFrm->GetBar() == pBar )
736 {
c82c42d4 737 pFFrm->Show( false ); // reduces flicker sligthly
8e08b761 738
5515f252 739 ReparentWindow( pBar->mpBarWnd, &GetParentFrame() );
8e08b761 740
5515f252 741 pBar->mBounds = pBar->mDimInfo.mBounds[ pBar->mDimInfo.mLRUPane ];
8e08b761 742
5515f252 743 if ( newState != wxCBAR_HIDDEN )
8e08b761 744
5515f252 745 pBar->mAlignment = pBar->mDimInfo.mLRUPane;
8e08b761 746
b02a6dc2 747 mFloatedFrames.Erase( pNode );
8e08b761 748
c82c42d4 749 pFFrm->Show( false );
5515f252
GT
750 pFFrm->Destroy(); break;
751 }
8e08b761 752
8495ba53 753 pNode = pNode->GetNext();
5515f252 754 }
8e08b761 755
5515f252
GT
756 // FOR NOW:: excessive!
757 //if ( mpFrameClient ) mpFrameClient->Refresh();
758 if ( mpFrameClient )
c82c42d4 759 mClientWndRefreshPending = true;
5515f252
GT
760 }
761 }
8e08b761 762
aef58440
GT
763 if ( pBar->mDimInfo.GetDimHandler() )
764 {
765 pBar->mDimInfo.GetDimHandler()->OnChangeBarState( pBar, newState );
766 }
767
5515f252 768 pBar->mState = newState;
8e08b761 769
5515f252 770 DoSetBarState( pBar );
8e08b761 771
5515f252
GT
772 if ( updateNow )
773 {
c82c42d4 774 RecalcLayout(false);
8e08b761 775
5515f252
GT
776 GetUpdatesManager().OnFinishChanges();
777 GetUpdatesManager().UpdateNow();
778 }
8e08b761
JS
779}
780
781void wxFrameLayout::InverseVisibility( cbBarInfo* pBar )
782{
5515f252 783 wxASSERT( pBar ); // DBG::
8e08b761 784
5515f252 785 // "inverse" bar-visibility of the selected bar
8e08b761 786
8552e6f0 787 int newState;
8e08b761 788
5515f252
GT
789 if ( pBar->mState == wxCBAR_HIDDEN )
790 {
791 if ( pBar->mAlignment == -1 )
792 {
793 pBar->mAlignment = 0; // just remove "-1" marking
794 newState = wxCBAR_FLOATING;
795 }
796 else
797 if ( pBar->mAlignment == FL_ALIGN_TOP ||
798 pBar->mAlignment == FL_ALIGN_BOTTOM )
8e08b761 799
5515f252
GT
800 newState = wxCBAR_DOCKED_HORIZONTALLY;
801 else
802 newState = wxCBAR_DOCKED_VERTICALLY;
803 }
804 else
805 {
806 newState = wxCBAR_HIDDEN;
8e08b761 807
5515f252 808 if ( pBar->mState == wxCBAR_FLOATING )
8e08b761 809
5515f252
GT
810 pBar->mAlignment = -1;
811 }
8e08b761 812
c82c42d4 813 this->SetBarState( pBar, newState, true );
8e08b761 814
5515f252 815 if ( newState == wxCBAR_FLOATING )
8e08b761 816
5515f252 817 this->RepositionFloatedBar( pBar );
8e08b761
JS
818}
819
820void wxFrameLayout::ApplyBarProperties( cbBarInfo* pBar )
821{
5515f252
GT
822 if ( pBar->mState == wxCBAR_FLOATING )
823 {
824 RepositionFloatedBar( pBar );
825 }
826 else
827 if ( pBar->mState == wxCBAR_DOCKED_HORIZONTALLY ||
828 pBar->mState == wxCBAR_DOCKED_VERTICALLY
829 )
830 {
831 // FOR NOW:: nothing
832 }
8e08b761
JS
833
834}
835
836void wxFrameLayout::RepositionFloatedBar( cbBarInfo* pBar )
837{
fc7c8ae9 838 if ( !(mFloatingOn && pBar->mFloatingOn)) return;
8e08b761 839
b02a6dc2 840 wxObjectList::compatibility_iterator pNode = mFloatedFrames.GetFirst();
8e08b761 841
5515f252
GT
842 while( pNode )
843 {
8495ba53 844 cbFloatedBarWindow* pFFrm = ((cbFloatedBarWindow*)pNode->GetData());
8e08b761 845
5515f252
GT
846 if ( pFFrm->GetBar() == pBar )
847 {
848 wxRect& bounds = pBar->mDimInfo.mBounds[wxCBAR_FLOATING];
8e08b761 849
5515f252
GT
850 int x = bounds.x,
851 y = bounds.y;
8e08b761 852
5515f252 853 GetParentFrame().ClientToScreen( &x, &y );
8e08b761 854
5515f252
GT
855 pFFrm->PositionFloatedWnd( x,y,
856 bounds.width,
857 bounds.height );
8e08b761 858
5515f252
GT
859 break;
860 }
8e08b761 861
8495ba53 862 pNode = pNode->GetNext();
5515f252 863 }
8e08b761
JS
864}
865
866void wxFrameLayout::DoSetBarState( cbBarInfo* pBar )
867{
5515f252
GT
868 if ( pBar->mState != wxCBAR_FLOATING &&
869 pBar->mState != wxCBAR_HIDDEN )
870
871 // dock it
8e08b761 872
5515f252
GT
873 mPanes[pBar->mAlignment]->InsertBar( pBar );
874 else
875 if ( pBar->mState == wxCBAR_HIDDEN )
876 {
877 // hide it
8e08b761 878
5515f252 879 if ( pBar->mpBarWnd )
8e08b761 880
c82c42d4 881 pBar->mpBarWnd->Show( false );
5515f252
GT
882 }
883 else
884 {
fc7c8ae9
JS
885 if ( !(mFloatingOn && pBar->mFloatingOn) )
886 return;
8e08b761 887
5515f252 888 // float it
8e08b761 889
5515f252
GT
890 if ( pBar->mpBarWnd == NULL || !CanReparent() )
891 {
892 // FOR NOW:: just hide it
8e08b761 893
5515f252 894 if ( pBar->mpBarWnd )
8e08b761 895
c82c42d4 896 pBar->mpBarWnd->Show( false );
8e08b761 897
5515f252 898 pBar->mState = wxCBAR_HIDDEN;
8e08b761 899
5515f252
GT
900 return;
901 }
8e08b761 902
5515f252 903 cbFloatedBarWindow* pMiniFrm = new cbFloatedBarWindow();
8e08b761 904
5515f252
GT
905 pMiniFrm->SetBar( pBar );
906 pMiniFrm->SetLayout( this );
8e08b761 907
c82c42d4 908 pMiniFrm->Create( &GetParentFrame(), wxID_ANY, pBar->mName,
5515f252
GT
909 wxPoint( 50,50 ),
910 wxSize ( 0, 0 ),
6b2878de 911 wxFRAME_FLOAT_ON_PARENT |
c25b742a 912 wxNO_BORDER |
6b2878de 913 wxFRAME_NO_TASKBAR
5515f252 914 );
8e08b761 915
5515f252 916 pMiniFrm->SetClient( pBar->mpBarWnd );
8e08b761 917
5515f252 918 ReparentWindow( pBar->mpBarWnd, pMiniFrm );
8e08b761 919
5515f252 920 mFloatedFrames.Append( pMiniFrm );
8e08b761 921
5515f252 922 wxRect& bounds = pBar->mDimInfo.mBounds[wxCBAR_FLOATING];
8e08b761 923
5515f252 924 // check if it wasn't floated anytime before
8e08b761 925
5515f252
GT
926 if ( bounds.width == -1 )
927 {
928 wxRect& clntRect = GetClientRect();
8e08b761 929
5515f252 930 // adjust position into which the next floated bar will be placed
8e08b761 931
5515f252 932 if ( mNextFloatedWndPos.x + bounds.width > clntRect.width )
8e08b761 933
5515f252 934 mNextFloatedWndPos.x = mFloatingPosStep.x;
8e08b761 935
5515f252 936 if ( mNextFloatedWndPos.y + bounds.height > clntRect.height )
8e08b761 937
5515f252 938 mNextFloatedWndPos.y = mFloatingPosStep.y;
8e08b761 939
5515f252
GT
940 bounds.x = mNextFloatedWndPos.x + clntRect.x;
941 bounds.y = mNextFloatedWndPos.y + clntRect.y;
8e08b761 942
5515f252
GT
943 bounds.width = pBar->mDimInfo.mSizes[wxCBAR_FLOATING].x;
944 bounds.height = pBar->mDimInfo.mSizes[wxCBAR_FLOATING].y;
8e08b761 945
5515f252
GT
946 mNextFloatedWndPos.x += mFloatingPosStep.x;
947 mNextFloatedWndPos.y += mFloatingPosStep.y;
948 }
8e08b761 949
c82c42d4 950 pMiniFrm->Show( true );
fdaebb05 951 RepositionFloatedBar(pMiniFrm->GetBar());
8e08b761 952
5515f252 953 // FIXME:: this is excessive
c82c42d4 954 pBar->mpBarWnd->Show(true);
5515f252 955 }
8e08b761
JS
956}
957
958void wxFrameLayout::RemoveBar( cbBarInfo* pBarInfo )
959{
5515f252 960 // first, try to "guess" what was the perviouse state of the bar
8e08b761 961
5515f252
GT
962 cbDockPane* pPane;
963 cbRowInfo* pRow;
8e08b761 964
5515f252
GT
965 if ( LocateBar( pBarInfo, &pRow, &pPane ) )
966 {
967 // ...aha, bar was docked into one of the panes,
968 // remove it from there
8e08b761 969
5515f252
GT
970 pPane->RemoveBar( pBarInfo );
971 }
8e08b761 972
5515f252
GT
973 size_t i;
974 for ( i = 0; i != mAllBars.Count(); ++i )
975 {
976 if ( mAllBars[i] == pBarInfo )
977 {
8e08b761 978#if wxCHECK_VERSION(2,3,2)
5515f252 979 mAllBars.RemoveAt(i);
8e08b761 980#else
5515f252 981 mAllBars.Remove(i);
8e08b761 982#endif
5515f252 983 if ( pBarInfo->mpBarWnd ) // hides it's window
8e08b761 984
c82c42d4 985 pBarInfo->mpBarWnd->Show( false );
8e08b761 986
5515f252 987 delete pBarInfo;
8e08b761 988
5515f252
GT
989 return;
990 }
991 }
873a543b 992 wxFAIL_MSG(wxT("bar info should be present in the list of all bars of all panes"));
8e08b761
JS
993}
994
995bool wxFrameLayout::LocateBar( cbBarInfo* pBarInfo,
5515f252
GT
996 cbRowInfo** ppRow,
997 cbDockPane** ppPane )
8e08b761 998{
5515f252
GT
999 (*ppRow) = NULL;
1000 (*ppPane) = NULL;
8e08b761 1001
5515f252
GT
1002 int n;
1003 for ( n = 0; n != MAX_PANES; ++n )
1004 {
1005 wxBarIterator i( mPanes[n]->GetRowList() );
8e08b761 1006
5515f252
GT
1007 while ( i.Next() )
1008
1009 if ( &i.BarInfo() == pBarInfo )
1010 {
1011 (*ppPane) = mPanes[n];
1012 (*ppRow ) = &i.RowInfo();
8e08b761 1013
c82c42d4 1014 return true;
5515f252
GT
1015 }
1016 }
8e08b761 1017
c82c42d4 1018 return false;
8e08b761
JS
1019}
1020
1021void wxFrameLayout::RecalcLayout( bool repositionBarsNow )
1022{
c82c42d4 1023 mRecalcPending = false;
8e08b761 1024
5515f252
GT
1025 int frmWidth, frmHeight;
1026 mpFrame->GetClientSize( &frmWidth, &frmHeight );
8e08b761 1027
5515f252
GT
1028 int curY = 0;
1029 int curX = 0;
1030 wxRect rect;
8e08b761 1031
5515f252
GT
1032 // pane positioning priorities in decreasing order:
1033 // top, bottom, left, right
8e08b761 1034
5515f252 1035 // setup TOP pane
8e08b761 1036
5515f252 1037 cbDockPane* pPane = mPanes[ FL_ALIGN_TOP ];
8e08b761 1038
5515f252
GT
1039 pPane->SetPaneWidth( frmWidth );
1040 pPane->RecalcLayout();
8e08b761 1041
8552e6f0 1042 int paneHeight = pPane->GetPaneHeight();
8e08b761 1043
5515f252
GT
1044 rect.x = curX;
1045 rect.y = curY;
1046 rect.width = frmWidth;
1047 rect.height = wxMin( paneHeight, frmHeight - curY );
8e08b761 1048
5515f252 1049 pPane->SetBoundsInParent( rect );
8e08b761 1050
5515f252 1051 curY += paneHeight;
8e08b761 1052
5515f252 1053 // setup BOTTOM pane
8e08b761 1054
5515f252 1055 pPane = mPanes[ FL_ALIGN_BOTTOM ];
8e08b761 1056
5515f252
GT
1057 pPane->SetPaneWidth( frmWidth );
1058 pPane->RecalcLayout();
8e08b761 1059
5515f252 1060 paneHeight = pPane->GetPaneHeight();
8e08b761 1061
5515f252
GT
1062 rect.x = curX;
1063 rect.y = wxMax( frmHeight - paneHeight, curY );
1064 rect.width = frmWidth;
1065 rect.height = frmHeight - rect.y;
8e08b761 1066
5515f252 1067 pPane->SetBoundsInParent( rect );
8e08b761 1068
5515f252 1069 // setup LEFT pane
8e08b761 1070
5515f252 1071 pPane = mPanes[ FL_ALIGN_LEFT ];
8e08b761 1072
5515f252
GT
1073 // bottom pane's y
1074 pPane->SetPaneWidth( rect.y - curY );
8e08b761 1075
5515f252
GT
1076 pPane->RecalcLayout();
1077 paneHeight = pPane->GetPaneHeight();
8e08b761 1078
5515f252
GT
1079 // bottom rect's y
1080 rect.height = rect.y - curY;
1081 rect.x = curX;
1082 rect.y = curY;
1083 rect.width = wxMin( paneHeight, frmWidth );
8e08b761 1084
5515f252 1085 pPane->SetBoundsInParent( rect );
8e08b761 1086
5515f252 1087 curX += rect.width;
8e08b761 1088
5515f252 1089 // setup RIGHT pane
8e08b761 1090
5515f252 1091 pPane = mPanes[ FL_ALIGN_RIGHT ];
8e08b761 1092
5515f252
GT
1093 // left pane's height
1094 pPane->SetPaneWidth( rect.height );
8e08b761 1095
5515f252
GT
1096 pPane->RecalcLayout();
1097 paneHeight = pPane->GetPaneHeight();
8e08b761 1098
5515f252
GT
1099 // left pane's height
1100 rect.height = rect.height;
1101 rect.x = wxMax( frmWidth - paneHeight, curX );
1102 rect.y = curY;
1103 rect.width = frmWidth - rect.x;
8e08b761 1104
5515f252 1105 pPane->SetBoundsInParent( rect );
8e08b761 1106
5515f252 1107 // recalc bounds of the client-window
8e08b761 1108
5515f252
GT
1109 mClntWndBounds.x = mPanes[FL_ALIGN_LEFT]->mBoundsInParent.x +
1110 mPanes[FL_ALIGN_LEFT]->mBoundsInParent.width;
1111 mClntWndBounds.y = mPanes[FL_ALIGN_TOP ]->mBoundsInParent.y +
1112 mPanes[FL_ALIGN_TOP ]->mBoundsInParent.height;
8e08b761 1113
5515f252
GT
1114 mClntWndBounds.width = mPanes[FL_ALIGN_RIGHT]->mBoundsInParent.x -
1115 mClntWndBounds.x;
1116 mClntWndBounds.height = mPanes[FL_ALIGN_BOTTOM]->mBoundsInParent.y -
1117 mClntWndBounds.y;
8e08b761 1118
5515f252 1119 if ( repositionBarsNow )
8e08b761 1120
5515f252 1121 PositionPanes();
8e08b761
JS
1122}
1123
1124int wxFrameLayout::GetClientHeight()
1125{
5515f252 1126 // for better portablility wxWindow::GetSzie() is not used here
8e08b761 1127
5515f252 1128 return mClntWndBounds.height;
8e08b761
JS
1129}
1130
1131int wxFrameLayout::GetClientWidth()
1132{
5515f252 1133 // for better portablility wxWindow::GetSzie() is not used here
8e08b761 1134
5515f252 1135 return mClntWndBounds.width;
8e08b761
JS
1136}
1137
1138void wxFrameLayout::PositionClientWindow()
1139{
5515f252
GT
1140 if ( mpFrameClient )
1141 {
1142 if ( mClntWndBounds.width >= 1 && mClntWndBounds.height >= 1 )
1143 {
1144 mpFrameClient->SetSize( mClntWndBounds.x, mClntWndBounds.y,
1145 mClntWndBounds.width, mClntWndBounds.height, 0 );
8e08b761 1146
5515f252 1147 if ( !mpFrameClient->IsShown() )
8e08b761 1148
c82c42d4 1149 mpFrameClient->Show( true );
5515f252
GT
1150 }
1151 else
c82c42d4 1152 mpFrameClient->Show( false );
5515f252 1153 }
8e08b761
JS
1154}
1155
1156void wxFrameLayout::PositionPanes()
1157{
5515f252 1158 PositionClientWindow();
8e08b761 1159
5515f252
GT
1160 // FOR NOW:: excessive updates!
1161 // reposition bars within all panes
8e08b761 1162
5515f252
GT
1163 int i;
1164 for ( i = 0; i != MAX_PANES; ++i )
1165 mPanes[i]->SizePaneObjects();
8e08b761
JS
1166}
1167
1168void wxFrameLayout::OnSize( wxSizeEvent& event )
1169{
a55e5190 1170 mpFrame->ProcessEvent( event );
c82c42d4 1171 event.Skip( false ); // stop its progpagation
a55e5190 1172
5515f252 1173 if ( event.GetEventObject() == (wxObject*) mpFrame )
4cf0b34c
GT
1174 {
1175 GetUpdatesManager().OnStartChanges();
c82c42d4 1176 RecalcLayout(true);
4cf0b34c
GT
1177 GetUpdatesManager().OnFinishChanges();
1178 GetUpdatesManager().UpdateNow();
1179 }
1180
8e08b761
JS
1181}
1182
1183/*** protected members ***/
1184
1185void wxFrameLayout::HideBarWindows()
1186{
5515f252
GT
1187 size_t i;
1188 for ( i = 0; i != mAllBars.Count(); ++i )
1189 if ( mAllBars[i]->mpBarWnd && mAllBars[i]->mState != wxCBAR_FLOATING )
c82c42d4 1190 mAllBars[i]->mpBarWnd->Show( false );
8e08b761 1191
5515f252 1192 // then floated frames
8e08b761 1193
c82c42d4 1194 ShowFloatedWindows( false );
8e08b761 1195
5515f252 1196 if ( mpFrameClient )
8e08b761 1197
c82c42d4 1198 mpFrameClient->Show( false );
8e08b761
JS
1199}
1200
1201void wxFrameLayout::UnhookFromFrame()
1202{
5515f252 1203 // NOTE:: the SetEvtHandlerEnabled() method is not used
4cbc57f0 1204 // here, since it is assumed that unhooking layout
5515f252
GT
1205 // from window may result destroying of the layout itself
1206 //
1207 // BUG BUG BUG (wx):: this would not be a problem if
4cbc57f0 1208 // wxEvtHandler's destructor checked if
5515f252
GT
1209 // this handler is currently the top-most
1210 // handler of some window, and additionally
4cbc57f0
JS
1211 // to the reconnecting itself from the chain.
1212 // It would also re-setup current event handler
5515f252
GT
1213 // of the window using wxWindow::SetEventHandler()
1214
1215 // FOR NOW::
1216
1217 if ( mpFrame->GetEventHandler() == this )
5921a14e 1218 {
5515f252
GT
1219 mpFrame->PopEventHandler();
1220 return;
5921a14e 1221 }
8e08b761 1222
5515f252
GT
1223 if ( mpFrame )
1224 {
1225 if ( this == mpFrame->GetEventHandler() )
5921a14e 1226 {
5515f252 1227 mpFrame->SetEventHandler( this->GetNextHandler() );
5921a14e 1228 }
5515f252
GT
1229 else
1230 {
1231 wxEvtHandler* pCur = mpFrame->GetEventHandler();
8e08b761 1232
5515f252
GT
1233 while ( pCur )
1234 {
1235 if ( pCur == this )
5921a14e 1236 break;
8e08b761 1237
5515f252
GT
1238 pCur = pCur->GetNextHandler();
1239 }
8e08b761 1240
5515f252
GT
1241 // do not try to unhook ourselves if we're not hooked yet
1242 if ( !pCur )
5921a14e 1243 return;
5515f252 1244 }
8e08b761 1245
5515f252
GT
1246 if ( GetPreviousHandler() )
1247 GetPreviousHandler()->SetNextHandler( GetNextHandler() );
1248 else
1249 {
1250 mpFrame->PopEventHandler();
1251 return;
1252 }
8e08b761 1253
5515f252
GT
1254 if ( GetNextHandler() )
1255 GetNextHandler()->SetPreviousHandler( GetPreviousHandler() );
8e08b761 1256
5515f252
GT
1257 SetNextHandler( NULL );
1258 SetPreviousHandler( NULL );
1259 }
8e08b761
JS
1260}
1261
1262void wxFrameLayout::HookUpToFrame()
1263{
5515f252 1264 // unhook us first, we're already hooked up
8e08b761 1265
5515f252 1266 UnhookFromFrame();
8e08b761 1267
5515f252 1268 // put ourselves on top
8e08b761 1269
5515f252 1270 mpFrame->PushEventHandler( this );
8e08b761
JS
1271}
1272
1273cbDockPane* wxFrameLayout::GetBarPane( cbBarInfo* pBar )
1274{
5515f252
GT
1275 int i;
1276 for ( i = 0; i != MAX_PANES; ++i )
1277 if ( mPanes[i]->BarPresent( pBar ) )
1278 return mPanes[i];
8e08b761 1279
5515f252 1280 return NULL;
8e08b761
JS
1281}
1282
1283void wxFrameLayout::CreateCursors()
1284{
5515f252
GT
1285 /*
1286 // FIXME:: The below code somehow doesn't work - cursors remain unchanged
1287 char bits[64];
1288
1289 set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
8e08b761 1290
5515f252 1291 mpHorizCursor = new wxCursor( bits, 32, 16 );
8e08b761 1292
5515f252 1293 set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
8e08b761 1294
5515f252
GT
1295 mpVertCursor = new wxCursor( bits, 32, 16 );
1296 */
8e08b761 1297
5515f252 1298 // FOR NOW:: use standard ones
8e08b761
JS
1299
1300 mpHorizCursor = new wxCursor(wxCURSOR_SIZEWE);
1301 mpVertCursor = new wxCursor(wxCURSOR_SIZENS);
5515f252
GT
1302 mpNormalCursor = new wxCursor(wxCURSOR_ARROW );
1303 mpDragCursor = new wxCursor(wxCURSOR_CROSS );
1304 mpNECursor = new wxCursor(wxCURSOR_NO_ENTRY);
8e08b761 1305
5515f252
GT
1306 mFloatingPosStep.x = 25;
1307 mFloatingPosStep.y = 25;
8e08b761 1308
5515f252
GT
1309 mNextFloatedWndPos.x = mFloatingPosStep.x;
1310 mNextFloatedWndPos.y = mFloatingPosStep.y;
8e08b761
JS
1311}
1312
1313bool wxFrameLayout::HitTestPane( cbDockPane* pPane, int x, int y )
1314{
5515f252 1315 return rect_contains_point( pPane->GetRealRect(), x, y );
8e08b761
JS
1316}
1317
1318cbDockPane* wxFrameLayout::HitTestPanes( const wxRect& rect,
5515f252 1319 cbDockPane* pCurPane )
8e08b761 1320{
5515f252 1321 // first, give the privilege to the current pane
8e08b761 1322
5515f252
GT
1323 if ( pCurPane && rect_hits_rect( pCurPane->GetRealRect(), rect ) )
1324
1325 return pCurPane;
8e08b761 1326
5515f252
GT
1327 int i;
1328 for ( i = 0; i != MAX_PANES; ++i )
1329 {
1330 if ( pCurPane != mPanes[i] &&
1331 rect_hits_rect( mPanes[i]->GetRealRect(), rect ) )
1332 {
1333 return mPanes[i];
1334 }
1335 }
1336 return 0;
8e08b761
JS
1337}
1338
1339void wxFrameLayout::ForwardMouseEvent( wxMouseEvent& event,
5515f252
GT
1340 cbDockPane* pToPane,
1341 int eventType )
8e08b761 1342{
5515f252
GT
1343 wxPoint pos( event.m_x, event.m_y );
1344 pToPane->FrameToPane( &pos.x, &pos.y );
8e08b761 1345
5515f252
GT
1346 if ( eventType == cbEVT_PL_LEFT_DOWN )
1347 {
1348 cbLeftDownEvent evt( pos, pToPane );
1349 FirePluginEvent( evt );
1350 }
1351 else if ( eventType == cbEVT_PL_LEFT_DCLICK )
1352 {
1353 cbLeftDClickEvent evt( pos, pToPane );
1354 FirePluginEvent( evt );
1355 }
1356 else if ( eventType == cbEVT_PL_LEFT_UP )
1357 {
1358 cbLeftUpEvent evt( pos, pToPane );
1359 FirePluginEvent( evt );
1360 }
1361 else if ( eventType == cbEVT_PL_RIGHT_DOWN )
1362 {
1363 cbRightDownEvent evt( pos, pToPane );
1364 FirePluginEvent( evt );
1365 }
1366 else if ( eventType == cbEVT_PL_RIGHT_UP )
1367 {
1368 cbRightUpEvent evt( pos, pToPane );
1369 FirePluginEvent( evt );
1370 }
1371 else if ( eventType == cbEVT_PL_MOTION )
1372 {
1373 cbMotionEvent evt( pos, pToPane );
1374 FirePluginEvent( evt );
1375 }
8e08b761
JS
1376} // wxFrameLayout::ForwardMouseEvent()
1377
1378
1379void wxFrameLayout::RouteMouseEvent( wxMouseEvent& event, int pluginEvtType )
1380{
5515f252 1381 if ( mpPaneInFocus )
8e08b761 1382
5515f252
GT
1383 ForwardMouseEvent( event, mpPaneInFocus, pluginEvtType );
1384 else
1385 {
1386 int i;
1387 for ( i = 0; i != MAX_PANES; ++i )
1388 {
1389 if ( HitTestPane( mPanes[i], event.m_x, event.m_y ) )
1390 {
1391 ForwardMouseEvent( event, mPanes[i], pluginEvtType );
1392 return;
1393 }
1394 }
1395 }
8e08b761
JS
1396}
1397
1398/*** event handlers ***/
1399
1400void wxFrameLayout::OnRButtonDown( wxMouseEvent& event )
1401{
5515f252 1402 RouteMouseEvent( event, cbEVT_PL_RIGHT_DOWN );
8e08b761
JS
1403}
1404
1405void wxFrameLayout::OnRButtonUp( wxMouseEvent& event )
1406{
5515f252 1407 RouteMouseEvent( event, cbEVT_PL_RIGHT_UP );
8e08b761
JS
1408}
1409
1410void wxFrameLayout::OnLButtonDown( wxMouseEvent& event )
1411{
5515f252 1412 RouteMouseEvent( event, cbEVT_PL_LEFT_DOWN );
8e08b761
JS
1413}
1414
1415void wxFrameLayout::OnLDblClick( wxMouseEvent& event )
1416{
5515f252 1417 RouteMouseEvent( event, cbEVT_PL_LEFT_DCLICK );
8e08b761
JS
1418}
1419
1420void wxFrameLayout::OnLButtonUp( wxMouseEvent& event )
1421{
5515f252 1422 RouteMouseEvent( event, cbEVT_PL_LEFT_UP );
8e08b761
JS
1423}
1424
1425void wxFrameLayout::OnMouseMove( wxMouseEvent& event )
1426{
5515f252
GT
1427 if ( mpPaneInFocus )
1428
1429 ForwardMouseEvent( event, mpPaneInFocus, cbEVT_PL_MOTION );
1430 else
1431 {
1432 int i;
1433 for ( i = 0; i != MAX_PANES; ++i )
1434 {
1435 if ( HitTestPane( mPanes[i], event.m_x, event.m_y ) )
1436 {
1437 if ( mpLRUPane && mpLRUPane != mPanes[i] )
1438 {
1439 // simulate "mouse-leave" event
1440 ForwardMouseEvent( event, mpLRUPane, cbEVT_PL_MOTION );
1441 }
8e08b761 1442
5515f252 1443 ForwardMouseEvent( event, mPanes[i], cbEVT_PL_MOTION );
8e08b761 1444
5515f252 1445 mpLRUPane = mPanes[i];
8e08b761 1446
5515f252
GT
1447 return;
1448 }
1449 }
1450 }
8e08b761 1451
5515f252
GT
1452 if ( mpLRUPane )
1453 {
1454 // simulate "mouse-leave" event
1455 ForwardMouseEvent( event, mpLRUPane, cbEVT_PL_MOTION );
1456 mpLRUPane = 0;
1457 }
8e08b761
JS
1458}
1459
1460void wxFrameLayout::OnPaint( wxPaintEvent& event )
1461{
5515f252 1462 if ( mRecalcPending )
c82c42d4 1463 RecalcLayout( true );
8e08b761 1464
5515f252 1465 wxPaintDC dc(mpFrame);
8e08b761 1466
5515f252
GT
1467 int i;
1468 for ( i = 0; i != MAX_PANES; ++i )
1469 {
1470 wxRect& rect = mPanes[i]->mBoundsInParent;
8e08b761 1471
5515f252 1472 dc.SetClippingRegion( rect.x, rect.y, rect.width, rect.height );
8e08b761 1473
5515f252 1474 mPanes[i]->PaintPane(dc);
8e08b761 1475
5515f252
GT
1476 dc.DestroyClippingRegion();
1477 }
8e08b761 1478
5515f252 1479 event.Skip();
8e08b761
JS
1480}
1481
196be0f1 1482void wxFrameLayout::OnEraseBackground( wxEraseEvent& WXUNUSED(event) )
8e08b761 1483{
5515f252 1484 // do nothing
8e08b761
JS
1485}
1486
1487void wxFrameLayout::OnIdle( wxIdleEvent& event )
1488{
5515f252 1489 wxWindow* focus = wxWindow::FindFocus();
8e08b761 1490
5515f252
GT
1491 if ( !focus && mCheckFocusWhenIdle )
1492 {
873a543b 1493 wxMessageBox(wxT("Hi, no more focus in this app!"));
8e08b761 1494
c82c42d4
WS
1495 mCheckFocusWhenIdle = false;
1496 //ShowFloatedWindows( false );
5515f252 1497 }
8e08b761 1498
c82c42d4 1499 mCheckFocusWhenIdle = false;
8e08b761 1500
5515f252 1501 event.Skip();
8e08b761
JS
1502}
1503
8e08b761
JS
1504void wxFrameLayout::GetPaneProperties( cbCommonPaneProperties& props, int alignment )
1505{
5515f252 1506 props = mPanes[alignment]->mProps;
8e08b761
JS
1507}
1508
1509void wxFrameLayout::SetPaneProperties( const cbCommonPaneProperties& props, int paneMask )
1510{
5515f252
GT
1511 int i;
1512 for ( i = 0; i != MAX_PANES; ++i )
1513 {
1514 if ( mPanes[i]->MatchesMask( paneMask ) )
1515 mPanes[i]->mProps = props;
1516 }
8e08b761
JS
1517}
1518
1519void wxFrameLayout::SetMargins( int top, int bottom, int left, int right,
5515f252 1520 int paneMask )
8e08b761 1521{
5515f252
GT
1522 int i;
1523 for ( i = 0; i != MAX_PANES; ++i )
1524 {
1525 cbDockPane& pane = *mPanes[i];
8e08b761 1526
5515f252
GT
1527 if ( pane.MatchesMask( paneMask ) )
1528 {
1529 pane.mTopMargin = top;
1530 pane.mBottomMargin = bottom;
1531 pane.mLeftMargin = left;
1532 pane.mRightMargin = right;
1533 }
1534 }
8e08b761
JS
1535}
1536
1537void wxFrameLayout::SetPaneBackground( const wxColour& colour )
1538{
5515f252 1539 mBorderPen.SetColour( colour );
8e08b761
JS
1540}
1541
1542void wxFrameLayout::RefreshNow( bool recalcLayout )
1543{
4cf0b34c 1544 if ( recalcLayout )
c82c42d4 1545 RecalcLayout( true );
8e08b761 1546
4cf0b34c
GT
1547 if ( mpFrame )
1548 mpFrame->Refresh();
8e08b761
JS
1549}
1550
1551/*** plugin-related methods ***/
1552
1553void wxFrameLayout::FirePluginEvent( cbPluginEvent& event )
1554{
5515f252 1555 // check state of input capture, before processing the event
8e08b761 1556
5515f252
GT
1557 if ( mpCaputesInput )
1558 {
c82c42d4 1559 bool isInputEvt = true;
8e08b761 1560#if wxCHECK_VERSION(2,3,0)
687706f5
KH
1561 if ( event.GetEventType() != cbEVT_PL_LEFT_DOWN &&
1562 event.GetEventType() != cbEVT_PL_LEFT_UP &&
1563 event.GetEventType() != cbEVT_PL_RIGHT_DOWN &&
1564 event.GetEventType() != cbEVT_PL_RIGHT_UP &&
1565 event.GetEventType() != cbEVT_PL_MOTION )
c82c42d4 1566 isInputEvt = false;
8e08b761 1567#else
5515f252
GT
1568 switch ( event.m_eventType )
1569 {
1570 case cbEVT_PL_LEFT_DOWN : break;
1571 case cbEVT_PL_LEFT_UP : break;
1572 case cbEVT_PL_RIGHT_DOWN : break;
1573 case cbEVT_PL_RIGHT_UP : break;
1574 case cbEVT_PL_MOTION : break;
1575
c82c42d4 1576 default : isInputEvt = false; break;
5515f252 1577 }
8e08b761
JS
1578#endif // #if wxCHECK_VERSION(2,3,0)
1579
5515f252
GT
1580 if ( isInputEvt )
1581 {
1582 mpCaputesInput->ProcessEvent( event );
1583 return;
1584 }
1585 }
8e08b761 1586
5515f252 1587 GetTopPlugin().ProcessEvent( event );
8e08b761
JS
1588}
1589
1590void wxFrameLayout::CaptureEventsForPlugin ( cbPluginBase* pPlugin )
1591{
5515f252
GT
1592 // cannot capture events for more than one plugin at a time
1593 wxASSERT( mpCaputesInput == NULL );
8e08b761 1594
5515f252 1595 mpCaputesInput = pPlugin;
8e08b761
JS
1596
1597}
1598
196be0f1 1599void wxFrameLayout::ReleaseEventsFromPlugin( cbPluginBase* WXUNUSED(pPlugin) )
8e08b761 1600{
5515f252
GT
1601 // events should be captured first
1602 wxASSERT( mpCaputesInput != NULL );
8e08b761 1603
5515f252 1604 mpCaputesInput = NULL;
8e08b761
JS
1605}
1606
1607void wxFrameLayout::CaptureEventsForPane( cbDockPane* toPane )
1608{
5515f252
GT
1609 // cannot capture events twice (without releasing)
1610 wxASSERT( mpPaneInFocus == NULL );
8e08b761 1611
5515f252 1612 mpFrame->CaptureMouse();
8e08b761 1613
5515f252 1614 mpPaneInFocus = toPane;
8e08b761
JS
1615}
1616
196be0f1 1617void wxFrameLayout::ReleaseEventsFromPane( cbDockPane* WXUNUSED(fromPane) )
8e08b761 1618{
5515f252
GT
1619 // cannot release events without capturing them
1620 wxASSERT( mpPaneInFocus != NULL );
8e08b761 1621
5515f252 1622 mpFrame->ReleaseMouse();
8e08b761 1623
5515f252 1624 mpPaneInFocus = NULL;
8e08b761
JS
1625}
1626
1627cbPluginBase& wxFrameLayout::GetTopPlugin()
1628{
5515f252
GT
1629 if ( !mpTopPlugin )
1630
1631 PushDefaultPlugins(); // automatic configuration
8e08b761 1632
5515f252 1633 return *mpTopPlugin;
8e08b761
JS
1634}
1635
1636void wxFrameLayout::SetTopPlugin( cbPluginBase* pPlugin )
1637{
5515f252 1638 mpTopPlugin = pPlugin;
8e08b761
JS
1639}
1640
1641bool wxFrameLayout::HasTopPlugin()
1642{
5515f252 1643 return ( mpTopPlugin != NULL );
8e08b761
JS
1644}
1645
1646void wxFrameLayout::PushPlugin( cbPluginBase* pPlugin )
1647{
5515f252
GT
1648 if ( !mpTopPlugin )
1649
1650 mpTopPlugin = pPlugin;
1651 else
1652 {
1653 pPlugin->SetNextHandler( mpTopPlugin );
8e08b761 1654
5515f252 1655 mpTopPlugin->SetPreviousHandler( pPlugin );
8e08b761 1656
5515f252
GT
1657 mpTopPlugin = pPlugin;
1658 }
8e08b761 1659
5515f252 1660 mpTopPlugin->OnInitPlugin(); // notification
8e08b761
JS
1661}
1662
1663void wxFrameLayout::PopPlugin()
1664{
5515f252 1665 wxASSERT( mpTopPlugin ); // DBG:: at least one plugin should be present
8e08b761 1666
5515f252 1667 cbPluginBase* pPopped = mpTopPlugin;
8e08b761 1668
5515f252 1669 mpTopPlugin = (cbPluginBase*)mpTopPlugin->GetNextHandler();
8e08b761 1670
5515f252 1671 delete pPopped;
8e08b761
JS
1672}
1673
1674void wxFrameLayout::PopAllPlugins()
1675{
5515f252 1676 while( mpTopPlugin ) PopPlugin();
8e08b761
JS
1677}
1678
1679void wxFrameLayout::PushDefaultPlugins()
1680{
5515f252 1681 // FIXME:: to much of the stuff for the default...
8e08b761 1682
5515f252
GT
1683 AddPlugin( CLASSINFO( cbRowLayoutPlugin ) );
1684 AddPlugin( CLASSINFO( cbBarDragPlugin ) );
1685 AddPlugin( CLASSINFO( cbPaneDrawPlugin ) );
8e08b761
JS
1686}
1687
1688void wxFrameLayout::AddPlugin( wxClassInfo* pPlInfo, int paneMask )
1689{
5515f252 1690 if ( FindPlugin ( pPlInfo ) ) return; // same type of plugin cannot be added twice
8e08b761 1691
5515f252 1692 cbPluginBase* pObj = (cbPluginBase*)pPlInfo->CreateObject();
8e08b761 1693
5515f252 1694 wxASSERT(pObj); // DBG:: plugin's class should be dynamic
8e08b761 1695
5515f252
GT
1696 pObj->mPaneMask = paneMask;
1697 pObj->mpLayout = this;
8e08b761 1698
5515f252 1699 PushPlugin( pObj );
8e08b761
JS
1700}
1701
1702void wxFrameLayout::AddPluginBefore( wxClassInfo* pNextPlInfo, wxClassInfo* pPlInfo,
5515f252 1703 int paneMask )
8e08b761 1704{
5515f252 1705 wxASSERT( pNextPlInfo != pPlInfo ); // DBG:: no sense
8e08b761 1706
5515f252 1707 cbPluginBase* pNextPl = FindPlugin( pNextPlInfo );
8e08b761 1708
5515f252
GT
1709 if ( !pNextPl )
1710 {
1711 AddPlugin( pPlInfo, paneMask );
8e08b761 1712
5515f252
GT
1713 return;
1714 }
8e08b761 1715
5515f252 1716 // remove existing one if present
8e08b761 1717
5515f252
GT
1718 cbPluginBase* pExistingPl = FindPlugin( pPlInfo );
1719
1720 if ( pExistingPl ) RemovePlugin( pPlInfo );
8e08b761 1721
5515f252 1722 // create an instance
8e08b761 1723
5515f252 1724 cbPluginBase* pNewPl = (cbPluginBase*)pPlInfo->CreateObject();
8e08b761 1725
5515f252 1726 wxASSERT(pNewPl); // DBG:: plugin's class should be dynamic
8e08b761 1727
5515f252 1728 // insert it to the chain
8e08b761 1729
5515f252
GT
1730 if ( pNextPl->GetPreviousHandler() )
1731
1732 pNextPl->GetPreviousHandler()->SetNextHandler( pNewPl );
1733 else
1734 mpTopPlugin = pNewPl;
8e08b761 1735
5515f252 1736 pNewPl->SetNextHandler( pNextPl );
8e08b761 1737
5515f252 1738 pNewPl->SetPreviousHandler( pNextPl->GetPreviousHandler() );
8e08b761 1739
5515f252 1740 pNextPl->SetPreviousHandler( pNewPl );
8e08b761 1741
5515f252 1742 // set it up
8e08b761 1743
5515f252
GT
1744 pNewPl->mPaneMask = paneMask;
1745 pNewPl->mpLayout = this;
8e08b761 1746
5515f252 1747 pNewPl->OnInitPlugin();
8e08b761
JS
1748}
1749
1750void wxFrameLayout::RemovePlugin( wxClassInfo* pPlInfo )
1751{
5515f252 1752 cbPluginBase* pPlugin = FindPlugin( pPlInfo );
8e08b761 1753
5515f252 1754 if ( !pPlugin ) return; // it's OK to remove not-existing plugin ;-)
8e08b761 1755
5515f252 1756 if ( pPlugin->GetPreviousHandler() == NULL )
8e08b761 1757
5515f252 1758 mpTopPlugin = (cbPluginBase*)pPlugin->GetNextHandler();
8e08b761 1759
5515f252 1760 delete pPlugin;
8e08b761
JS
1761}
1762
1763cbPluginBase* wxFrameLayout::FindPlugin( wxClassInfo* pPlInfo )
1764{
5515f252 1765 cbPluginBase *pCur = mpTopPlugin;
8e08b761 1766
5515f252
GT
1767 while( pCur )
1768 {
1769 // NOTE:: it might appear useful matching plugin
1770 // classes "polymorphically":
8e08b761 1771
5515f252 1772 if ( pCur->GetClassInfo()->IsKindOf( pPlInfo ) )
8e08b761 1773
5515f252 1774 return pCur;
8e08b761 1775
5515f252
GT
1776 pCur = (cbPluginBase*)pCur->GetNextHandler();
1777 }
8e08b761 1778
5515f252 1779 return NULL;
8e08b761
JS
1780}
1781
1782/***** Implementation for class cbUpdateMgrData *****/
1783
1784IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData, wxObject )
1785
1786cbUpdateMgrData::cbUpdateMgrData()
1787
5515f252 1788 : mPrevBounds( -1,-1,0,0 ),
fdaebb05
VZ
1789 mIsDirty( true ), // inidicate initial change
1790 mpCustomData(0)
8e08b761
JS
1791{}
1792
1793void cbUpdateMgrData::StoreItemState( const wxRect& boundsInParent )
1794{
5515f252 1795 mPrevBounds = boundsInParent;
8e08b761
JS
1796}
1797
1798void cbUpdateMgrData::SetDirty( bool isDirty )
1799{
5515f252 1800 mIsDirty = isDirty;
8e08b761
JS
1801}
1802
1803void cbUpdateMgrData::SetCustomData( wxObject* pCustomData )
1804{
5515f252 1805 mpCustomData = pCustomData;
8e08b761
JS
1806}
1807
1808/***** Implementation for class cbDockPane *****/
1809
1810void wxBarIterator::Reset()
1811{
5515f252
GT
1812 mpRow = ( mpRows->Count() ) ? (*mpRows)[0] : NULL;
1813 mpBar = NULL;
8e08b761
JS
1814}
1815
1816wxBarIterator::wxBarIterator( RowArrayT& rows )
1817
5515f252
GT
1818 : mpRows( &rows ),
1819 mpRow ( NULL ),
1820 mpBar ( NULL )
8e08b761 1821{
5515f252 1822 Reset();
8e08b761
JS
1823}
1824
1825bool wxBarIterator::Next()
5515f252
GT
1826{
1827 if ( mpRow )
1828 {
1829 if ( mpBar )
1830 mpBar = mpBar->mpNext;
1831 else
1832 {
1833 if ( mpRow->mBars.GetCount() == 0 )
1834 {
c82c42d4 1835 return false;
5515f252
GT
1836 }
1837
1838 mpBar = mpRow->mBars[0];
1839 }
1840
1841 if ( !mpBar )
1842 {
1843 // skip to the next row
1844
1845 mpRow = mpRow->mpNext;
1846
1847 if ( mpRow )
1848
1849 mpBar = mpRow->mBars[0];
1850 else
c82c42d4 1851 return false;
5515f252
GT
1852 }
1853
c82c42d4 1854 return true;
5515f252
GT
1855 }
1856 else
c82c42d4 1857 return false;
8e08b761
JS
1858}
1859
1860cbBarInfo& wxBarIterator::BarInfo()
1861{
5515f252 1862 return *mpBar;
8e08b761
JS
1863}
1864
1865cbRowInfo& wxBarIterator::RowInfo()
1866{
5515f252 1867 return *mpRow;
8e08b761
JS
1868}
1869
1870/***** Implementation for class cbBarDimHandlerBase *****/
1871
1872IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase, wxObject )
1873
1874cbBarDimHandlerBase::cbBarDimHandlerBase()
5515f252 1875 : mRefCount(0)
8e08b761
JS
1876{}
1877
1878void cbBarDimHandlerBase::AddRef()
1879{
5515f252 1880 ++mRefCount;
8e08b761
JS
1881}
1882
1883void cbBarDimHandlerBase::RemoveRef()
1884{
5515f252 1885 if ( --mRefCount <= 0 ) delete this;
8e08b761
JS
1886}
1887
1888/***** Implementation for class cbDimInfo *****/
1889
1890IMPLEMENT_DYNAMIC_CLASS( cbDimInfo, wxObject )
1891
1892cbDimInfo::cbDimInfo()
1893
5515f252
GT
1894 : mVertGap ( 0 ),
1895 mHorizGap( 0 ),
8e08b761 1896
c82c42d4 1897 mIsFixed(true),
5515f252 1898 mpHandler( NULL )
8e08b761 1899{
5515f252
GT
1900 size_t i;
1901 for ( i = 0; i != MAX_BAR_STATES; ++i )
1902 {
1903 mSizes[i].x = 20;
1904 mSizes[i].y = 20;
8e08b761 1905
5515f252
GT
1906 mBounds[i] = wxRect( -1,-1,-1,-1 );
1907 }
8e08b761
JS
1908}
1909
1910cbDimInfo::cbDimInfo( cbBarDimHandlerBase* pDimHandler,
5515f252 1911 bool isFixed )
8e08b761 1912
5515f252
GT
1913 : mVertGap ( 0 ),
1914 mHorizGap( 0 ),
1915 mIsFixed ( isFixed ),
8e08b761 1916
5515f252 1917 mpHandler( pDimHandler )
8e08b761 1918{
5515f252
GT
1919 if ( mpHandler )
1920 {
1921 // int vtad = *((int*)mpHandler);
1922 mpHandler->AddRef();
1923 }
1924
1925 size_t i;
1926 for ( i = 0; i != MAX_BAR_STATES; ++i )
1927 {
1928 mSizes[i].x = -1;
1929 mSizes[i].y = -1;
8e08b761 1930
5515f252
GT
1931 mBounds[i] = wxRect( -1,-1,-1,-1 );
1932 }
8e08b761
JS
1933}
1934
1935cbDimInfo::cbDimInfo( int dh_x, int dh_y,
5515f252
GT
1936 int dv_x, int dv_y,
1937 int f_x, int f_y,
1938
1939 bool isFixed,
1940 int horizGap,
1941 int vertGap,
1942
1943 cbBarDimHandlerBase* pDimHandler
1944 )
1945 : mVertGap ( vertGap ),
1946 mHorizGap ( horizGap ),
1947 mIsFixed ( isFixed ),
1948 mpHandler( pDimHandler )
1949{
1950 if ( mpHandler )
1951 {
1952 // int vtad = *((int*)mpHandler);
1953 mpHandler->AddRef();
1954 }
1955
1956 mSizes[wxCBAR_DOCKED_HORIZONTALLY].x = dh_x;
1957 mSizes[wxCBAR_DOCKED_HORIZONTALLY].y = dh_y;
1958 mSizes[wxCBAR_DOCKED_VERTICALLY ].x = dv_x;
1959 mSizes[wxCBAR_DOCKED_VERTICALLY ].y = dv_y;
1960 mSizes[wxCBAR_FLOATING ].x = f_x;
1961 mSizes[wxCBAR_FLOATING ].y = f_y;
1962
1963 size_t i;
1964 for ( i = 0; i != MAX_BAR_STATES; ++i )
1965 mBounds[i] = wxRect( -1,-1,-1,-1 );
1966}
8e08b761
JS
1967
1968cbDimInfo::cbDimInfo( int x, int y,
1969 bool isFixed, int gap,
1970 cbBarDimHandlerBase* pDimHandler)
1971 : mVertGap ( gap ),
1972 mHorizGap ( gap ),
1973 mIsFixed ( isFixed ),
1974 mpHandler( pDimHandler )
1975{
1976 if ( mpHandler )
1977 {
1978 // int vtad = *((int*)mpHandler);
1979 mpHandler->AddRef();
1980 }
1981
1982 mSizes[wxCBAR_DOCKED_HORIZONTALLY].x = x;
1983 mSizes[wxCBAR_DOCKED_HORIZONTALLY].y = y;
1984 mSizes[wxCBAR_DOCKED_VERTICALLY ].x = x;
1985 mSizes[wxCBAR_DOCKED_VERTICALLY ].y = y;
1986 mSizes[wxCBAR_FLOATING ].x = x;
1987 mSizes[wxCBAR_FLOATING ].y = y;
5515f252
GT
1988
1989 size_t i;
1990 for ( i = 0; i != MAX_BAR_STATES; ++i )
8e08b761
JS
1991 mBounds[i] = wxRect( -1,-1,-1,-1 );
1992}
1993
1994cbDimInfo::~cbDimInfo()
1995{
5515f252
GT
1996 if ( mpHandler )
1997
1998 mpHandler->RemoveRef();
8e08b761
JS
1999}
2000
2001const cbDimInfo& cbDimInfo::operator=( const cbDimInfo& other )
2002{
5515f252
GT
2003 if ( this == &other )
2004 return *this;
8e08b761 2005
5515f252
GT
2006 int i;
2007 for ( i = 0; i != MAX_BAR_STATES; ++i )
2008 mSizes[i] = other.mSizes[i];
8e08b761 2009
5515f252
GT
2010 mIsFixed = other.mIsFixed;
2011 mpHandler = other.mpHandler;
8e08b761 2012
5515f252
GT
2013 mVertGap = other.mVertGap;
2014 mHorizGap = other.mHorizGap;
8e08b761 2015
5515f252 2016 if ( mpHandler )
8e08b761 2017
5515f252 2018 mpHandler->AddRef();
8e08b761 2019
5515f252 2020 return *this;
8e08b761
JS
2021}
2022
2023/***** Implementation for structure cbCommonPaneProperties *****/
2024
2025IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties, wxObject )
2026
2027cbCommonPaneProperties::cbCommonPaneProperties(void)
2028
c82c42d4
WS
2029 : mRealTimeUpdatesOn ( true ),
2030 mOutOfPaneDragOn ( true ),
2031 mExactDockPredictionOn( false ),
2032 mNonDestructFrictionOn( false ),
2033 mShow3DPaneBorderOn ( true ),
2034 mBarFloatingOn ( false ),
2035 mRowProportionsOn ( false ),
2036 mColProportionsOn ( true ),
2037 mBarCollapseIconsOn ( false ),
2038 mBarDragHintsOn ( false ),
5515f252
GT
2039
2040 mMinCBarDim( 16, 16 ),
2041 mResizeHandleSize( 4 )
8e08b761
JS
2042{}
2043
69b8ed1b
GD
2044cbCommonPaneProperties::cbCommonPaneProperties(const cbCommonPaneProperties& props)
2045
2046 : wxObject(),
2047 mRealTimeUpdatesOn (props.mRealTimeUpdatesOn),
2048 mOutOfPaneDragOn (props.mOutOfPaneDragOn),
2049 mExactDockPredictionOn(props.mExactDockPredictionOn),
2050 mNonDestructFrictionOn(props.mNonDestructFrictionOn),
2051 mShow3DPaneBorderOn (props.mShow3DPaneBorderOn),
2052 mBarFloatingOn (props.mBarFloatingOn),
2053 mRowProportionsOn (props.mRowProportionsOn),
2054 mColProportionsOn (props.mColProportionsOn),
2055 mBarCollapseIconsOn (props.mBarCollapseIconsOn),
2056 mBarDragHintsOn (props.mBarDragHintsOn),
2057
2058 mMinCBarDim(props.mMinCBarDim),
2059 mResizeHandleSize(props.mResizeHandleSize)
2060{}
2061
2062cbCommonPaneProperties& cbCommonPaneProperties::operator=(const cbCommonPaneProperties& props)
2063{
2708457a
GD
2064 mRealTimeUpdatesOn = props.mRealTimeUpdatesOn;
2065 mOutOfPaneDragOn = props.mOutOfPaneDragOn;
2066 mExactDockPredictionOn = props.mExactDockPredictionOn;
2067 mNonDestructFrictionOn = props.mNonDestructFrictionOn;
2068 mShow3DPaneBorderOn = props.mShow3DPaneBorderOn;
2069 mBarFloatingOn = props.mBarFloatingOn;
2070 mRowProportionsOn = props.mRowProportionsOn;
2071 mColProportionsOn = props.mColProportionsOn;
2072 mBarCollapseIconsOn = props.mBarCollapseIconsOn;
2073 mBarDragHintsOn = props.mBarDragHintsOn;
2074
2075 mMinCBarDim = props.mMinCBarDim;
2076 mResizeHandleSize = props.mResizeHandleSize;
2077
69b8ed1b
GD
2078 return *this;
2079}
2080
8e08b761
JS
2081/***** Implementation for class cbRowInfo *****/
2082
2083IMPLEMENT_DYNAMIC_CLASS( cbRowInfo, wxObject )
2084
2085cbRowInfo::cbRowInfo(void)
2086
c82c42d4 2087 : mNotFixedBarsCnt( false ),
5515f252
GT
2088 mpNext ( NULL ),
2089 mpPrev ( NULL ),
2090 mpExpandedBar ( NULL )
8e08b761
JS
2091{}
2092
2093cbRowInfo::~cbRowInfo()
2094{
5515f252
GT
2095 // nothing! all bars are removed using global bar
2096 // list in wxFrameLayout class
8e08b761
JS
2097}
2098
2099/***** Implementation for class cbBarInfo *****/
2100
2101IMPLEMENT_DYNAMIC_CLASS( cbBarInfo, wxObject )
2102
2103cbBarInfo::cbBarInfo(void)
2104
5515f252 2105 : mpRow( NULL ),
c82c42d4 2106 mFloatingOn( true ),
5515f252 2107 mpNext( NULL ),
8495ba53 2108 mpPrev( NULL )
8e08b761
JS
2109{}
2110
2111cbBarInfo::~cbBarInfo()
2112{
5515f252 2113 // nothing
8e08b761
JS
2114}
2115
2116/***** Implementation for class cbDockPane *****/
2117
2118IMPLEMENT_DYNAMIC_CLASS( cbDockPane, wxObject )
2119
2120// FIXME:: how to eliminate these cut&pasted constructors?
2121
5515f252
GT
2122cbDockPane::cbDockPane(void)
2123 : mLeftMargin ( 1 ),
2124 mRightMargin ( 1 ),
2125 mTopMargin ( 1 ),
2126 mBottomMargin( 1 ),
2127 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2128 // since the real dimensions of the pane may not
2129 // be known, while inserting bars initially
2130 mPaneHeight( 32768 ),
2131 mAlignment ( -1 ),
2132 mpLayout ( 0 ),
2133 mpStoredRow( NULL )
8e08b761
JS
2134{}
2135
2136cbDockPane::cbDockPane( int alignment, wxFrameLayout* pPanel )
5515f252
GT
2137
2138 : mLeftMargin ( 1 ),
2139 mRightMargin ( 1 ),
2140 mTopMargin ( 1 ),
2141 mBottomMargin( 1 ),
2142 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2143 // since the real dimensions of the pane may not
2144 // be known, while inserting bars initially
2145 mPaneHeight( 32768 ),
2146 mAlignment ( alignment ),
2147 mpLayout ( pPanel ),
2148 mpStoredRow( NULL )
8e08b761
JS
2149{}
2150
2151cbDockPane::~cbDockPane()
2152{
5515f252
GT
2153 size_t i;
2154 for ( i = 0; i != mRows.Count(); ++i )
2155 delete mRows[i];
8e08b761 2156
b02a6dc2 2157 WX_CLEAR_LIST(wxList,mRowShapeData)
5515f252
GT
2158
2159 // NOTE:: control bar infromation structures are cleaned-up
2160 // in wxFrameLayout's destructor, using global control-bar list
8e08b761
JS
2161}
2162
2163void cbDockPane::SetMargins( int top, int bottom, int left, int right )
2164{
5515f252
GT
2165 mTopMargin = top;
2166 mBottomMargin = bottom;
2167 mLeftMargin = left;
2168 mRightMargin = right;
8e08b761
JS
2169}
2170
2171/*** helpers of cbDockPane ***/
2172
2173void cbDockPane::PaintBarDecorations( cbBarInfo* pBar, wxDC& dc )
2174{
5515f252 2175 cbDrawBarDecorEvent evt( pBar, dc, this );
8e08b761 2176
5515f252 2177 mpLayout->FirePluginEvent( evt );
8e08b761
JS
2178}
2179
2180void cbDockPane::PaintBarHandles( cbBarInfo* pBar, wxDC& dc )
2181{
5515f252 2182 cbDrawBarHandlesEvent evt( pBar, dc, this );
8e08b761 2183
5515f252 2184 mpLayout->FirePluginEvent( evt );
8e08b761
JS
2185}
2186
2187void cbDockPane::PaintBar( cbBarInfo* pBar, wxDC& dc )
2188{
5515f252
GT
2189 PaintBarDecorations( pBar, dc );
2190 PaintBarHandles( pBar, dc );
8e08b761
JS
2191}
2192
2193void cbDockPane::PaintRowHandles( cbRowInfo* pRow, wxDC& dc )
2194{
5515f252 2195 cbDrawRowHandlesEvent evt( pRow, dc, this );
8e08b761 2196
5515f252 2197 mpLayout->FirePluginEvent( evt );
8e08b761 2198
5515f252 2199 cbDrawRowDecorEvent evt1( pRow, dc, this );
8e08b761 2200
5515f252 2201 mpLayout->FirePluginEvent( evt1 );
8e08b761
JS
2202}
2203
2204void cbDockPane::PaintRowBackground ( cbRowInfo* pRow, wxDC& dc )
2205{
5515f252 2206 cbDrawRowBkGroundEvent evt( pRow, dc, this );
8e08b761 2207
5515f252 2208 mpLayout->FirePluginEvent( evt );
8e08b761
JS
2209}
2210
2211void cbDockPane::PaintRowDecorations( cbRowInfo* pRow, wxDC& dc )
2212{
8552e6f0 2213 size_t i;
8e08b761 2214
5515f252
GT
2215 // decorations first
2216 for ( i = 0; i != pRow->mBars.Count(); ++i )
2217
2218 PaintBarDecorations( pRow->mBars[i], dc );
8e08b761 2219
5515f252
GT
2220 // then handles if present
2221 for ( i = 0; i != pRow->mBars.Count(); ++i )
8e08b761 2222
5515f252 2223 PaintBarHandles( pRow->mBars[i], dc );
8e08b761
JS
2224}
2225
2226void cbDockPane::PaintRow( cbRowInfo* pRow, wxDC& dc )
2227{
5515f252
GT
2228 PaintRowBackground ( pRow, dc );
2229 PaintRowDecorations( pRow, dc );
2230 PaintRowHandles ( pRow, dc );
8e08b761
JS
2231}
2232
2233void cbDockPane::PaintPaneBackground( wxDC& dc )
2234{
5515f252 2235 cbDrawPaneBkGroundEvent evt( dc, this );
8e08b761 2236
5515f252 2237 mpLayout->FirePluginEvent( evt );
8e08b761
JS
2238}
2239
2240void cbDockPane::PaintPaneDecorations( wxDC& dc )
2241{
5515f252 2242 cbDrawPaneDecorEvent evt( dc, this );
8e08b761 2243
5515f252 2244 mpLayout->FirePluginEvent( evt );
8e08b761
JS
2245}
2246
2247void cbDockPane::PaintPane( wxDC& dc )
2248{
8552e6f0 2249 size_t i;
8e08b761 2250
8552e6f0 2251 PaintPaneBackground( dc );
8e08b761 2252
5515f252
GT
2253 // first decorations
2254 for ( i = 0; i != mRows.Count(); ++i )
2255 {
2256 PaintRowBackground( mRows[i], dc );
2257 PaintRowDecorations( mRows[i], dc );
2258 }
8e08b761 2259
5515f252
GT
2260 // than handles
2261 for ( i = 0; i != mRows.Count(); ++i )
2262 PaintRowHandles( mRows[i], dc );
8e08b761 2263
5515f252
GT
2264 // and finally
2265 PaintPaneDecorations( dc );
8e08b761
JS
2266}
2267
2268void cbDockPane::SizeBar( cbBarInfo* pBar )
2269{
5515f252 2270 cbSizeBarWndEvent evt( pBar, this );
8e08b761 2271
5515f252
GT
2272 mpLayout->FirePluginEvent( evt );
2273 return;
8e08b761
JS
2274}
2275
2276void cbDockPane::SizeRowObjects( cbRowInfo* pRow )
2277{
5515f252
GT
2278 size_t i;
2279 for ( i = 0; i != pRow->mBars.Count(); ++i )
2280 SizeBar( pRow->mBars[i] );
8e08b761
JS
2281}
2282
2283void cbDockPane::SizePaneObjects()
2284{
5515f252
GT
2285 size_t i;
2286 for ( i = 0; i != mRows.Count(); ++i )
2287 SizeRowObjects( mRows[i] );
8e08b761
JS
2288}
2289
2290wxDC* cbDockPane::StartDrawInArea( const wxRect& area )
2291{
5515f252 2292 wxDC* pDc = 0;
8e08b761 2293
5515f252 2294 cbStartDrawInAreaEvent evt( area, &pDc, this );
8e08b761 2295
5515f252 2296 mpLayout->FirePluginEvent( evt );
8e08b761 2297
5515f252 2298 return pDc;
8e08b761
JS
2299}
2300
2301void cbDockPane::FinishDrawInArea( const wxRect& area )
2302{
5515f252 2303 cbFinishDrawInAreaEvent evt( area, this );
8e08b761 2304
5515f252 2305 mpLayout->FirePluginEvent( evt );
8e08b761
JS
2306}
2307
2308bool cbDockPane::IsFixedSize( cbBarInfo* pInfo )
2309{
5515f252 2310 return ( pInfo->mDimInfo.mIsFixed );
8e08b761
JS
2311}
2312
2313int cbDockPane::GetNotFixedBarsCount( cbRowInfo* pRow )
2314{
5515f252 2315 int cnt = 0;
8e08b761 2316
5515f252
GT
2317 size_t i;
2318 for ( i = 0; i != pRow->mBars.Count(); ++i )
2319 {
2320 if ( !pRow->mBars[i]->IsFixed() )
2321 ++cnt;
2322 }
8e08b761 2323
5515f252 2324 return cnt;
8e08b761
JS
2325}
2326
2327void cbDockPane::RemoveBar( cbBarInfo* pBar )
2328{
6e8515a3 2329 bool needsRestoring = mProps.mNonDestructFrictionOn &&
5515f252 2330 mpStoredRow == pBar->mpRow;
8e08b761 2331
5515f252 2332 cbRemoveBarEvent evt( pBar, this );
8e08b761 2333
5515f252 2334 mpLayout->FirePluginEvent( evt );
8e08b761 2335
5515f252
GT
2336 if ( needsRestoring )
2337 {
2338 SetRowShapeData( mpStoredRow, &mRowShapeData );
8e08b761 2339
5515f252
GT
2340 mpStoredRow = NULL;
2341 }
8e08b761
JS
2342}
2343
2344void cbDockPane::SyncRowFlags( cbRowInfo* pRow )
2345{
5515f252 2346 // setup mHasOnlyFixedBars flag for the row information
c82c42d4 2347 pRow->mHasOnlyFixedBars = true;
8e08b761 2348
5515f252 2349 pRow->mNotFixedBarsCnt = 0;
8e08b761 2350
5515f252
GT
2351 size_t i;
2352 for ( i = 0; i != pRow->mBars.Count(); ++i )
2353 {
2354 cbBarInfo& bar = *pRow->mBars[i];
8e08b761 2355
5515f252 2356 bar.mpRow = pRow;
8e08b761 2357
5515f252
GT
2358 if ( !bar.IsFixed() )
2359 {
c82c42d4 2360 pRow->mHasOnlyFixedBars = false;
5515f252
GT
2361 ++pRow->mNotFixedBarsCnt;
2362 }
2363 }
8e08b761
JS
2364}
2365
2366void cbDockPane::FrameToPane( int* x, int* y )
2367{
5515f252
GT
2368 *x -= mLeftMargin;
2369 *y -= mTopMargin;
8e08b761 2370
5515f252
GT
2371 if ( mAlignment == FL_ALIGN_TOP ||
2372 mAlignment == FL_ALIGN_BOTTOM
2373 )
2374 {
2375 *x -= mBoundsInParent.x;
2376 *y -= mBoundsInParent.y;
2377 }
2378 else
2379 {
2380 int rx = *x, ry = *y;
8e08b761 2381
5515f252 2382 *x = ry - mBoundsInParent.y;
8e08b761 2383
5515f252
GT
2384 *y = rx - mBoundsInParent.x;
2385 }
8e08b761
JS
2386}
2387
2388void cbDockPane::PaneToFrame( int* x, int* y )
2389{
5515f252
GT
2390 if ( mAlignment == FL_ALIGN_TOP ||
2391 mAlignment == FL_ALIGN_BOTTOM
2392 )
2393 {
2394 *x += mBoundsInParent.x;
2395 *y += mBoundsInParent.y;
2396 }
2397 else
2398 {
2399 int rx = *x, ry = *y;
8e08b761 2400
5515f252 2401 *x = ry + mBoundsInParent.x;
8e08b761 2402
5515f252
GT
2403 *y = mBoundsInParent.y + rx;
2404 }
8e08b761 2405
5515f252
GT
2406 *x += mLeftMargin;
2407 *y += mTopMargin;
8e08b761
JS
2408}
2409
2410void cbDockPane::FrameToPane( wxRect* pRect )
2411{
5515f252
GT
2412 wxPoint upperLeft ( pRect->x, pRect->y );
2413 wxPoint lowerRight( pRect->x + pRect->width,
2414 pRect->y + pRect->height );
8e08b761 2415
5515f252
GT
2416 FrameToPane( &upperLeft.x, &upperLeft.y );
2417 FrameToPane( &lowerRight.x, &lowerRight.y );
8e08b761 2418
5515f252
GT
2419 pRect->x = wxMin(upperLeft.x,lowerRight.x);
2420 pRect->y = wxMin(upperLeft.y,lowerRight.y);
8e08b761 2421
5515f252
GT
2422 pRect->width = abs( lowerRight.x - upperLeft.x );
2423 pRect->height = abs( lowerRight.y - upperLeft.y );
8e08b761
JS
2424}
2425
2426void cbDockPane::PaneToFrame( wxRect* pRect )
2427{
5515f252
GT
2428 wxPoint upperLeft ( pRect->x, pRect->y );
2429 wxPoint lowerRight( pRect->x + pRect->width,
2430 pRect->y + pRect->height );
8e08b761 2431
5515f252
GT
2432 PaneToFrame( &upperLeft.x, &upperLeft.y );
2433 PaneToFrame( &lowerRight.x, &lowerRight.y );
8e08b761 2434
5515f252 2435 //wxRect newRect = wxRect( upperLeft, lowerRight );
8e08b761 2436
5515f252
GT
2437 pRect->x = wxMin(upperLeft.x,lowerRight.x);
2438 pRect->y = wxMin(upperLeft.y,lowerRight.y);
8e08b761 2439
5515f252
GT
2440 pRect->width = abs( lowerRight.x - upperLeft.x );
2441 pRect->height = abs( lowerRight.y - upperLeft.y );
8e08b761
JS
2442}
2443
2444int cbDockPane::GetRowAt( int paneY )
2445{
5515f252
GT
2446 if ( paneY < 0 )
2447 return -1;
8e08b761 2448
5515f252 2449 int curY = 0;
8e08b761 2450
5515f252 2451 size_t i = 0;
8e08b761 2452
5515f252
GT
2453 for ( ; i != mRows.Count(); ++i )
2454 {
2455 int rowHeight = mRows[i]->mRowHeight;
8e08b761 2456
5515f252
GT
2457 int third = rowHeight/3;
2458
2459 if ( paneY >= curY && paneY < curY + third )
2460 return i-1;
8e08b761 2461
5515f252
GT
2462 if ( paneY >= curY + third && paneY < curY + rowHeight - third )
2463 return i;
8e08b761 2464
5515f252
GT
2465 curY += rowHeight;
2466 }
8e08b761 2467
5515f252 2468 return i;
8e08b761
JS
2469}
2470
2471int cbDockPane::GetRowAt( int upperY, int lowerY )
2472{
5515f252
GT
2473 /*
2474 // OLD STUFF::
2475 int range = lowerY - upperY;
2476 int oneThird = range / 3;
8e08b761 2477
8495ba53 2478 wxNode* pRow = mRows.GetFirst();
5515f252
GT
2479 int row = 0;
2480 int curY = 0;
8e08b761 2481
5515f252 2482 if ( lowerY <= 0 ) return -1;
8e08b761 2483
5515f252
GT
2484 while( pRow )
2485 {
8495ba53 2486 int rowHeight = GetRowHeight( (wxList*)pRow->GetData() );
8e08b761 2487
5515f252
GT
2488 if ( upperY >= curY &&
2489 lowerY < curY ) return row;
8e08b761 2490
5515f252
GT
2491 if ( upperY <= curY &&
2492 lowerY >= curY &&
2493 curY - upperY >= oneThird ) return row-1;
8e08b761 2494
5515f252
GT
2495 if ( ( upperY < curY + rowHeight &&
2496 lowerY >= curY + rowHeight &&
2497 curY + rowHeight - lowerY >= oneThird )
2498 )
2499 return row+1;
8e08b761 2500
5515f252 2501 if ( lowerY <= curY + rowHeight ) return row;
8e08b761 2502
5515f252
GT
2503 ++row;
2504 curY += rowHeight;
8495ba53 2505 pRow = pRow->GetNext();
5515f252
GT
2506 }
2507 */
8e08b761 2508
5515f252 2509 int mid = upperY + (lowerY - upperY)/2;
8e08b761 2510
5515f252
GT
2511 if ( mid < 0 )
2512 return -1;
8e08b761 2513
5515f252
GT
2514 int curY = 0;
2515 size_t i = 0;
8e08b761 2516
5515f252
GT
2517 for ( ; i != mRows.Count(); ++i )
2518 {
2519 int rowHeight = mRows[i]->mRowHeight;
8e08b761 2520
5515f252 2521 if ( mid >= curY && mid < curY + rowHeight ) return i;
8e08b761 2522
5515f252
GT
2523 curY += rowHeight;
2524 }
8e08b761 2525
5515f252 2526 return i;
8e08b761
JS
2527}
2528
2529int cbDockPane::GetRowY( cbRowInfo* pRow )
2530{
5515f252 2531 int curY = 0;
8e08b761 2532
5515f252
GT
2533 size_t i;
2534 for ( i = 0; i != mRows.Count(); ++i )
2535 {
2536 if ( mRows[i] == pRow )
2537 break;
8e08b761 2538
5515f252
GT
2539 curY += mRows[i]->mRowHeight;
2540 }
8e08b761 2541
5515f252 2542 return curY;
8e08b761
JS
2543}
2544
2545bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo* pRow )
2546{
5515f252
GT
2547 while ( pRow->mpPrev )
2548 {
2549 pRow = pRow->mpPrev;
8e08b761 2550
5515f252 2551 if ( pRow->mHasOnlyFixedBars )
8e08b761 2552
c82c42d4 2553 return true;
5515f252 2554 }
8e08b761 2555
c82c42d4 2556 return false;
8e08b761
JS
2557}
2558
2559bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo* pRow )
2560{
5515f252
GT
2561 while( pRow->mpNext )
2562 {
2563 pRow = pRow->mpNext;
8e08b761 2564
5515f252 2565 if ( pRow->mHasOnlyFixedBars )
8e08b761 2566
c82c42d4 2567 return true;
5515f252 2568 }
8e08b761 2569
c82c42d4 2570 return false;
8e08b761
JS
2571}
2572
2573bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo* pBar )
2574{
5515f252
GT
2575 while( pBar->mpPrev )
2576 {
2577 pBar = pBar->mpPrev;
8e08b761 2578
5515f252 2579 if ( pBar->IsFixed() )
8e08b761 2580
c82c42d4 2581 return true;
5515f252
GT
2582 }
2583
c82c42d4 2584 return false;
8e08b761
JS
2585}
2586
2587bool cbDockPane::HasNotFixedBarsRight( cbBarInfo* pBar )
2588{
5515f252
GT
2589 while( pBar->mpNext )
2590 {
2591 pBar = pBar->mpNext;
8e08b761 2592
5515f252 2593 if ( pBar->IsFixed() )
8e08b761 2594
c82c42d4 2595 return true;
5515f252
GT
2596 }
2597
c82c42d4 2598 return false;
8e08b761
JS
2599}
2600
2601void cbDockPane::CalcLengthRatios( cbRowInfo* pInRow )
2602{
8552e6f0 2603 size_t i;
8e08b761 2604
8552e6f0 2605 int totalWidth = 0;
8e08b761 2606
4cbc57f0 2607 // calc current-maximal-total-length of all maximized bars
8e08b761 2608
5515f252
GT
2609 for ( i = 0; i != pInRow->mBars.GetCount(); ++i )
2610 {
2611 cbBarInfo& bar = *pInRow->mBars[i];
8e08b761 2612
5515f252
GT
2613 if ( !bar.IsFixed() )
2614 totalWidth += bar.mBounds.width;
2615 }
8e08b761 2616
4cbc57f0 2617 // set up percentages of occupied space for each maximized bar
8e08b761 2618
5515f252
GT
2619 for ( i = 0; i != pInRow->mBars.Count(); ++i )
2620 {
2621 cbBarInfo& bar = *pInRow->mBars[i];
8e08b761 2622
5515f252
GT
2623 if ( !bar.IsFixed() )
2624 bar.mLenRatio = double(bar.mBounds.width)/double(totalWidth);
2625 }
8e08b761
JS
2626}
2627
2628void cbDockPane::RecalcRowLayout( cbRowInfo* pRow )
2629{
5515f252
GT
2630 cbLayoutRowEvent evt( pRow, this );
2631
2632 mpLayout->FirePluginEvent( evt );
8e08b761
JS
2633}
2634
2635void cbDockPane::ExpandBar( cbBarInfo* pBar )
2636{
5515f252 2637 mpLayout->GetUpdatesManager().OnStartChanges();
8e08b761 2638
5515f252
GT
2639 if ( !pBar->mpRow->mpExpandedBar )
2640 {
2641 // save ratios only when there arent any bars expanded yet
8e08b761 2642
5515f252 2643 cbArrayFloat& ratios = pBar->mpRow->mSavedRatios;
8e08b761 2644
5515f252
GT
2645 ratios.Clear();
2646 ratios.Alloc( pBar->mpRow->mNotFixedBarsCnt );
8e08b761 2647
5515f252 2648 cbBarInfo* pCur = pBar->mpRow->mBars[0];
8e08b761 2649
5515f252
GT
2650 while( pCur )
2651 {
2652 if ( !pCur->IsFixed() )
2653 {
2654 ratios.Add( 0.0 );
2655 ratios[ ratios.GetCount() - 1 ] = pCur->mLenRatio;
2656 }
8e08b761 2657
5515f252
GT
2658 pCur = pCur->mpNext;
2659 }
2660 }
8e08b761 2661
5515f252 2662 cbBarInfo* pCur = pBar->mpRow->mBars[0];
8e08b761 2663
5515f252
GT
2664 while( pCur )
2665 {
2666 pCur->mLenRatio = 0.0; // minimize the rest
8e08b761 2667
5515f252
GT
2668 pCur = pCur->mpNext;
2669 }
8e08b761 2670
5515f252
GT
2671 pBar->mLenRatio = 1.0; // 100%
2672 pBar->mBounds.width = 0;
8e08b761 2673
5515f252 2674 pBar->mpRow->mpExpandedBar = pBar;
8e08b761 2675
c82c42d4 2676 mpLayout->RecalcLayout( false );
8e08b761 2677
5515f252
GT
2678 mpLayout->GetUpdatesManager().OnFinishChanges();
2679 mpLayout->GetUpdatesManager().UpdateNow();
8e08b761
JS
2680}
2681
2682void cbDockPane::ContractBar( cbBarInfo* pBar )
2683{
5515f252 2684 mpLayout->GetUpdatesManager().OnStartChanges();
8e08b761
JS
2685
2686 // FIXME: What's the purpose of this???
2687 // double ratio = 1.0/ double( pBar->mpRow->mNotFixedBarsCnt );
2688
5515f252 2689 // restore ratios which were present before expansion
8e08b761 2690
5515f252 2691 cbBarInfo* pCur = pBar->mpRow->mBars[0];
8e08b761 2692
5515f252 2693 cbArrayFloat& ratios = pBar->mpRow->mSavedRatios;
8e08b761 2694
5515f252 2695 size_t i = 0;
8e08b761 2696
5515f252
GT
2697 while( pCur )
2698 {
2699 if ( !pCur->IsFixed() )
2700 {
2701 pCur->mLenRatio = ratios[i];
2702 ++i;
2703 }
8e08b761 2704
5515f252
GT
2705 pCur = pCur->mpNext;
2706 }
8e08b761 2707
5515f252
GT
2708 ratios.Clear();
2709 ratios.Shrink();
8e08b761 2710
5515f252 2711 pBar->mpRow->mpExpandedBar = NULL;
8e08b761 2712
c82c42d4 2713 mpLayout->RecalcLayout( false );
8e08b761 2714
5515f252
GT
2715 mpLayout->GetUpdatesManager().OnFinishChanges();
2716 mpLayout->GetUpdatesManager().UpdateNow();
8e08b761
JS
2717}
2718
2719void cbDockPane::InitLinksForRow( cbRowInfo* pRow )
2720{
5515f252
GT
2721 size_t i;
2722 for ( i = 0; i != pRow->mBars.Count(); ++i )
2723 {
2724 cbBarInfo& bar = *pRow->mBars[i];
8e08b761 2725
5515f252
GT
2726 if ( i == 0 )
2727 bar.mpPrev = NULL;
2728 else
2729 bar.mpPrev = pRow->mBars[i-1];
8e08b761 2730
5515f252
GT
2731 if ( i == pRow->mBars.Count() - 1 )
2732 bar.mpNext = NULL;
2733 else
2734 bar.mpNext = pRow->mBars[i+1];
2735 }
8e08b761
JS
2736}
2737
2738void cbDockPane::InitLinksForRows()
2739{
5515f252
GT
2740 size_t i;
2741 for ( i = 0; i != mRows.Count(); ++i )
2742 {
2743 cbRowInfo& row = *mRows[i];
8e08b761 2744
5515f252
GT
2745 if ( i == 0 )
2746 row.mpPrev = NULL;
2747 else
2748 row.mpPrev = mRows[i-1];
8e08b761 2749
5515f252
GT
2750 if ( i == mRows.Count() - 1 )
2751 row.mpNext = NULL;
2752 else
2753 row.mpNext = mRows[i+1];
2754 }
8e08b761
JS
2755}
2756
2757void cbDockPane::DoInsertBar( cbBarInfo* pBar, int rowNo )
2758{
8552e6f0 2759 cbRowInfo* pRow;
8e08b761 2760
5515f252
GT
2761 if ( rowNo == -1 || rowNo >= (int)mRows.Count() )
2762 {
2763 pRow = new cbRowInfo();
8e08b761 2764
5515f252
GT
2765 if ( rowNo == -1 && mRows.Count() )
2766
2767 mRows.Insert( pRow, 0 );
2768 else
2769 mRows.Add( pRow );
8e08b761 2770
5515f252
GT
2771 InitLinksForRows();
2772 }
2773 else
2774 {
2775 pRow = mRows[rowNo];
8e08b761 2776
c82c42d4 2777 if ( mProps.mNonDestructFrictionOn == true )
5515f252
GT
2778 {
2779 // store original shape of the row (before the bar is inserted)
8e08b761 2780
5515f252
GT
2781 mpStoredRow = pRow;
2782
2783 GetRowShapeData( mpStoredRow, &mRowShapeData );
2784 }
2785 }
8e08b761 2786
5515f252 2787 if ( pRow->mBars.Count() )
8e08b761 2788
5515f252 2789 pRow->mpExpandedBar = NULL;
8e08b761 2790
5515f252 2791 cbInsertBarEvent insEvt( pBar, pRow, this );
8e08b761 2792
5515f252 2793 mpLayout->FirePluginEvent( insEvt );
8e08b761 2794
5515f252 2795 mpLayout->GetUpdatesManager().OnRowWillChange( pRow, this );
8e08b761
JS
2796}
2797
2798void cbDockPane::InsertBar( cbBarInfo* pBarInfo, const wxRect& atRect )
2799{
5515f252
GT
2800 wxRect rect = atRect;
2801 FrameToPane( &rect );
8e08b761 2802
5515f252
GT
2803 pBarInfo->mBounds.x = rect.x;
2804 pBarInfo->mBounds.width = rect.width;
2805 pBarInfo->mBounds.height = rect.height;
8e08b761 2806
5515f252 2807 int row = GetRowAt( rect.y, rect.y + rect.height );
8e08b761 2808
5515f252 2809 DoInsertBar( pBarInfo, row );
8e08b761
JS
2810}
2811
2812void cbDockPane::InsertBar( cbBarInfo* pBar, cbRowInfo* pIntoRow )
2813{
5515f252 2814 cbInsertBarEvent insEvt( pBar, pIntoRow, this );
8e08b761 2815
5515f252 2816 mpLayout->FirePluginEvent( insEvt );
8e08b761 2817
5515f252 2818 mpLayout->GetUpdatesManager().OnRowWillChange( pIntoRow, this );
8e08b761
JS
2819}
2820
2821void cbDockPane::InsertBar( cbBarInfo* pBarInfo )
2822{
5515f252 2823 // set transient properties
8e08b761 2824
5515f252 2825 pBarInfo->mpRow = NULL;
c82c42d4
WS
2826 pBarInfo->mHasLeftHandle = false;
2827 pBarInfo->mHasRightHandle = false;
5515f252 2828 pBarInfo->mLenRatio = 0.0;
8e08b761 2829
5515f252
GT
2830 // set preferred bar dimensions, according to the state in which
2831 // the bar is being inserted
8e08b761 2832
5515f252
GT
2833 pBarInfo->mBounds.width = pBarInfo->mDimInfo.mSizes[ pBarInfo->mState ].x;
2834 pBarInfo->mBounds.height = pBarInfo->mDimInfo.mSizes[ pBarInfo->mState ].y;
8e08b761 2835
5515f252 2836 DoInsertBar( pBarInfo, pBarInfo->mRowNo );
8e08b761
JS
2837}
2838
2839void cbDockPane::RemoveRow( cbRowInfo* pRow )
2840{
5515f252
GT
2841 size_t i;
2842 // first, hide all bar-windows in the removed row
2843 for ( i = 0; i != pRow->mBars.Count(); ++i )
2844 {
2845 if ( pRow->mBars[i]->mpBarWnd )
c82c42d4 2846 pRow->mBars[i]->mpBarWnd->Show( false );
5515f252 2847 }
8e08b761 2848
5515f252 2849 mRows.Remove( pRow );
8e08b761 2850
c82c42d4 2851 pRow->mUMgrData.SetDirty(true);
8e08b761
JS
2852}
2853
2854void cbDockPane::InsertRow( cbRowInfo* pRow, cbRowInfo* pBeforeRow )
2855{
5515f252 2856 if ( !pBeforeRow )
8e08b761 2857
5515f252
GT
2858 mRows.Add( pRow );
2859 else
2860 mRows.Insert( pRow, mRows.Index( pBeforeRow ) );
8e08b761 2861
5515f252 2862 InitLinksForRows();
8e08b761 2863
c82c42d4 2864 pRow->mUMgrData.SetDirty(true);
8e08b761 2865
5515f252
GT
2866 size_t i;
2867 for ( i = 0; i != pRow->mBars.Count(); ++i )
c82c42d4 2868 pRow->mBars[i]->mUMgrData.SetDirty( true );
8e08b761 2869
5515f252 2870 SyncRowFlags( pRow );
8e08b761
JS
2871}
2872
2873void cbDockPane::SetPaneWidth(int width)
2874{
5515f252
GT
2875 if ( IsHorizontal() )
2876 mPaneWidth = width - mLeftMargin - mRightMargin;
2877 else
2878 mPaneWidth = width - mTopMargin - mBottomMargin;
8e08b761
JS
2879}
2880
2881
2882void cbDockPane::SetBoundsInParent( const wxRect& rect )
2883{
5515f252 2884 mBoundsInParent = rect;
8e08b761 2885
5515f252 2886 // set pane dimensions in local coordinates
8e08b761 2887
5515f252
GT
2888 if ( IsHorizontal() )
2889 {
2890 mPaneWidth = mBoundsInParent.width - ( mRightMargin + mLeftMargin );
2891 mPaneHeight = mBoundsInParent.height - ( mTopMargin + mBottomMargin );
2892 }
2893 else
2894 {
2895 mPaneWidth = mBoundsInParent.height - ( mTopMargin + mBottomMargin );
2896 mPaneHeight = mBoundsInParent.width - ( mRightMargin + mLeftMargin );
2897 }
8e08b761 2898
5515f252 2899 // convert bounding rectangles of all pane items into parent frame's coordinates
8e08b761 2900
5515f252 2901 wxBarIterator i( mRows );
8e08b761 2902
5515f252 2903 wxRect noMarginsRect = mBoundsInParent;
8e08b761 2904
5515f252
GT
2905 noMarginsRect.x += mLeftMargin;
2906 noMarginsRect.y += mTopMargin;
2907 noMarginsRect.width -= ( mLeftMargin + mRightMargin );
2908 noMarginsRect.height -= ( mTopMargin + mBottomMargin );
8e08b761 2909
5515f252 2910 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
8e08b761 2911
5515f252
GT
2912 if ( mBoundsInParent.width < 0 ||
2913 mBoundsInParent.height < 0 )
8e08b761 2914
5515f252 2915 hide_rect( mBoundsInParent );
8e08b761 2916
5515f252
GT
2917 if ( noMarginsRect.width < 0 ||
2918 noMarginsRect.height < 0 )
2919
2920 hide_rect( noMarginsRect );
8e08b761 2921
5515f252 2922 // calculate mBoundsInParent for each item in the pane
8e08b761 2923
5515f252
GT
2924 while( i.Next() )
2925 {
2926 cbBarInfo& bar = i.BarInfo();
8e08b761 2927
5515f252 2928 cbRowInfo* pRowInfo = bar.mpRow;
8e08b761 2929
5515f252 2930 // set up row info, if this is first bar in the row
8e08b761 2931
5515f252
GT
2932 if ( pRowInfo && bar.mpPrev == NULL )
2933 {
2934 pRowInfo->mBoundsInParent.y = pRowInfo->mRowY;
2935 pRowInfo->mBoundsInParent.x = 0;
2936 pRowInfo->mBoundsInParent.width = mPaneWidth;
2937 pRowInfo->mBoundsInParent.height = pRowInfo->mRowHeight;
8e08b761 2938
5515f252 2939 PaneToFrame( &pRowInfo->mBoundsInParent );
8e08b761 2940
5515f252
GT
2941 clip_rect_against_rect( pRowInfo->mBoundsInParent, noMarginsRect );
2942 }
8e08b761 2943
5515f252 2944 wxRect bounds = bar.mBounds;
8e08b761 2945
5515f252
GT
2946 // exclude dimensions of handles, when calculating
2947 // bar's bounds in parent (i.e. "visual bounds")
8e08b761 2948
5515f252
GT
2949 if ( bar.mHasLeftHandle )
2950 {
2951 bounds.x += mProps.mResizeHandleSize;
2952 bounds.width -= mProps.mResizeHandleSize;
2953 }
8e08b761 2954
5515f252
GT
2955 if ( bar.mHasRightHandle )
2956
2957 bounds.width -= mProps.mResizeHandleSize;
8e08b761 2958
5515f252 2959 PaneToFrame( &bounds );
8e08b761 2960
5515f252 2961 clip_rect_against_rect( bounds, noMarginsRect );
8e08b761 2962
5515f252
GT
2963 bar.mBoundsInParent = bounds;
2964 }
8e08b761
JS
2965}
2966
2967bool cbDockPane::BarPresent( cbBarInfo* pBar )
2968{
5515f252 2969 wxBarIterator iter( mRows );
8e08b761 2970
5515f252
GT
2971 while( iter.Next() )
2972
c82c42d4 2973 if ( &iter.BarInfo() == pBar ) return true;
8e08b761 2974
c82c42d4 2975 return false;
8e08b761
JS
2976}
2977
2978cbRowInfo* cbDockPane::GetRow( int row )
2979{
5515f252 2980 if ( row >= (int)mRows.Count() ) return NULL;
8e08b761 2981
5515f252 2982 return mRows[ row ];
8e08b761
JS
2983}
2984
2985int cbDockPane::GetRowIndex( cbRowInfo* pRow )
2986{
5515f252
GT
2987 size_t i;
2988 for ( i = 0; i != mRows.Count(); ++i )
2989 {
2990 if ( mRows[i] == pRow )
2991 return i;
2992 }
8e08b761 2993
873a543b 2994 wxFAIL_MSG(wxT("Row must be present to call cbDockPane::GetRowIndex()"));
8e08b761 2995
5515f252 2996 return 0;
8e08b761
JS
2997}
2998
2999int cbDockPane::GetPaneHeight()
3000{
5515f252 3001 // first, recalculate row heights and the Y-positions
8e08b761 3002
5515f252
GT
3003 cbLayoutRowsEvent evt( this );
3004 mpLayout->FirePluginEvent( evt );
8e08b761 3005
5515f252 3006 int height = 0;
8e08b761 3007
5515f252
GT
3008 if ( IsHorizontal() )
3009
3010 height += mTopMargin + mBottomMargin;
3011 else
3012 height += mLeftMargin + mRightMargin;
8e08b761 3013
5515f252 3014 int count = mRows.Count();
8e08b761 3015
5515f252
GT
3016 if ( count )
3017
3018 height += mRows[count-1]->mRowY + mRows[count-1]->mRowHeight;
8e08b761 3019
5515f252 3020 return height;
8e08b761
JS
3021}
3022
3023int cbDockPane::GetAlignment()
3024{
5515f252 3025 return mAlignment;
8e08b761
JS
3026}
3027
3028bool cbDockPane::MatchesMask( int paneMask )
3029{
5515f252 3030 int thisMask = 0;
8e08b761 3031
5515f252 3032 // FIXME:: use array instead of switch()
8e08b761 3033
5515f252
GT
3034 switch (mAlignment)
3035 {
3036 case FL_ALIGN_TOP : thisMask = FL_ALIGN_TOP_PANE; break;
3037 case FL_ALIGN_BOTTOM : thisMask = FL_ALIGN_BOTTOM_PANE;break;
3038 case FL_ALIGN_LEFT : thisMask = FL_ALIGN_LEFT_PANE; break;
3039 case FL_ALIGN_RIGHT : thisMask = FL_ALIGN_RIGHT_PANE; break;
8e08b761 3040
5515f252 3041 default:
873a543b 3042 wxFAIL_MSG(wxT("Bad FL alignment type detected in cbDockPane::MatchesMask()"));
5515f252 3043 }
8e08b761 3044
5515f252 3045 return ( thisMask & paneMask ) != 0;
8e08b761
JS
3046}
3047
3048void cbDockPane::RecalcLayout()
3049{
5515f252 3050 // first, reposition rows and items vertically
8e08b761 3051
5515f252
GT
3052 cbLayoutRowsEvent evt( this );
3053 mpLayout->FirePluginEvent( evt );
8e08b761 3054
5515f252 3055 // then horizontally in each row
8e08b761 3056
5515f252
GT
3057 size_t i;
3058 for ( i = 0; i != mRows.Count(); ++i )
3059 RecalcRowLayout( mRows[i] );
8e08b761
JS
3060}
3061
3062int cbDockPane::GetDockingState()
3063{
5515f252
GT
3064 if ( mAlignment == FL_ALIGN_TOP ||
3065 mAlignment == FL_ALIGN_BOTTOM )
3066 {
3067 return wxCBAR_DOCKED_HORIZONTALLY;
3068 }
3069 else
3070 return wxCBAR_DOCKED_VERTICALLY;
8e08b761
JS
3071}
3072
3073inline bool cbDockPane::HasPoint( const wxPoint& pos, int x, int y,
5515f252 3074 int width, int height )
8e08b761 3075{
5515f252
GT
3076 return ( pos.x >= x &&
3077 pos.y >= y &&
3078 pos.x < x + width &&
3079 pos.y < y + height );
8e08b761
JS
3080}
3081
3082int cbDockPane::HitTestPaneItems( const wxPoint& pos,
5515f252
GT
3083 cbRowInfo** ppRow,
3084 cbBarInfo** ppBar
3085 )
8e08b761 3086{
5515f252
GT
3087 (*ppRow) = NULL;
3088 (*ppBar) = NULL;
8e08b761 3089
5515f252
GT
3090 size_t i;
3091 for ( i = 0; i != mRows.Count(); ++i )
3092 {
3093 cbRowInfo& row = *mRows[i];
8e08b761 3094
5515f252 3095 *ppRow = &row;
8e08b761 3096
5515f252 3097 // hit-test handles of the row, if present
8e08b761 3098
5515f252
GT
3099 if ( row.mHasUpperHandle )
3100 {
3101 if ( HasPoint( pos, 0, row.mRowY,
3102 row.mRowWidth, mProps.mResizeHandleSize ) )
8e08b761 3103
5515f252
GT
3104 return CB_UPPER_ROW_HANDLE_HITTED;
3105 }
3106 else
3107 if ( row.mHasLowerHandle )
3108 {
3109 if ( HasPoint( pos, 0, row.mRowY + row.mRowHeight - mProps.mResizeHandleSize,
3110 row.mRowWidth, mProps.mResizeHandleSize ) )
8e08b761 3111
5515f252
GT
3112 return CB_LOWER_ROW_HANDLE_HITTED;
3113 }
8e08b761 3114
5515f252 3115 // hit-test bar handles and bar content
8e08b761 3116
5515f252
GT
3117 size_t k;
3118 for ( k = 0; k != row.mBars.Count(); ++k )
3119 {
3120 cbBarInfo& bar = *row.mBars[k];
3121 wxRect& bounds = bar.mBounds;
8e08b761 3122
5515f252 3123 *ppBar = &bar;
8e08b761 3124
5515f252
GT
3125 if ( bar.mHasLeftHandle )
3126 {
3127 if ( HasPoint( pos, bounds.x, bounds.y,
3128 mProps.mResizeHandleSize, bounds.height ) )
8e08b761 3129
5515f252
GT
3130 return CB_LEFT_BAR_HANDLE_HITTED;
3131 }
3132 else
3133 if ( bar.mHasRightHandle )
3134 {
3135 if ( HasPoint( pos, bounds.x + bounds.width - mProps.mResizeHandleSize, bounds.y,
3136 mProps.mResizeHandleSize, bounds.height ) )
3137
3138 return CB_RIGHT_BAR_HANDLE_HITTED;
3139 }
8e08b761 3140
5515f252
GT
3141 if ( HasPoint( pos, bounds.x, bounds.y, bounds.width, bounds.height ) )
3142 return CB_BAR_CONTENT_HITTED;
8e08b761 3143
5515f252 3144 } // hit-test next bar
8e08b761 3145
5515f252 3146 } // next row
8e08b761 3147
5515f252 3148 return CB_NO_ITEMS_HITTED;
8e08b761
JS
3149}
3150
3151void cbDockPane::GetBarResizeRange( cbBarInfo* pBar, int* from, int *till,
5515f252 3152 bool forLeftHandle )
8e08b761 3153{
5515f252 3154 cbBarInfo* pGivenBar = pBar;
8e08b761 3155
5515f252 3156 int notFree = 0;
8e08b761 3157
5515f252 3158 // calc unavailable space from the left
8e08b761 3159
5515f252
GT
3160 while( pBar->mpPrev )
3161 {
3162 pBar = pBar->mpPrev;
8e08b761 3163
5515f252
GT
3164 if ( !pBar->IsFixed() ) notFree += mProps.mMinCBarDim.x;
3165 else notFree += pBar->mBounds.width;
3166 }
8e08b761 3167
5515f252 3168 *from = notFree;
8e08b761 3169
5515f252 3170 pBar = pGivenBar;
8e08b761 3171
5515f252 3172 notFree = 0;
8e08b761 3173
5515f252 3174 // calc unavailable space from the right
8e08b761 3175
5515f252
GT
3176 while( pBar->mpNext )
3177 {
3178 pBar = pBar->mpNext;
8e08b761 3179
5515f252 3180 if ( pBar->mBounds.x >= mPaneWidth ) break;
8e08b761 3181
5515f252 3182 // treat not-fixed bars as minimized
8e08b761 3183
5515f252
GT
3184 if ( !pBar->IsFixed() )
3185
3186 notFree += mProps.mMinCBarDim.x;
3187 else
3188 {
3189 if ( pBar->mBounds.x + pBar->mBounds.width >= mPaneWidth )
3190 {
3191 notFree += mPaneWidth - pBar->mBounds.x;
3192 break;
3193 }
3194 else
3195 notFree += pBar->mBounds.width;
3196 }
8e08b761 3197
5515f252 3198 }
8e08b761 3199
5515f252 3200 *till = mPaneWidth - notFree;
8e08b761 3201
5515f252 3202 // do not let resizing totally deform the bar itself
8e08b761 3203
5515f252
GT
3204 if ( forLeftHandle )
3205
3206 (*till) -= mProps.mMinCBarDim.x;
3207 else
3208
3209 (*from) += mProps.mMinCBarDim.x;
8e08b761
JS
3210}
3211
3212int cbDockPane::GetMinimalRowHeight( cbRowInfo* pRow )
3213{
5515f252 3214 int height = mProps.mMinCBarDim.y;
8e08b761 3215
5515f252
GT
3216 size_t i;
3217 for ( i = 0; i != pRow->mBars.Count(); ++i )
3218 {
3219 if ( pRow->mBars[i]->IsFixed() )
3220 height = wxMax( height, pRow->mBars[i]->mBounds.height );
3221 }
8e08b761 3222
5515f252
GT
3223 if ( pRow->mHasUpperHandle )
3224 height += mProps.mResizeHandleSize;
8e08b761 3225
5515f252
GT
3226 if ( pRow->mHasLowerHandle )
3227 height += mProps.mResizeHandleSize;
3228
3229 return height;
8e08b761
JS
3230}
3231
3232void cbDockPane::SetRowHeight( cbRowInfo* pRow, int newHeight )
3233{
5515f252 3234 if ( pRow->mHasUpperHandle )
8e08b761 3235
5515f252 3236 newHeight -= mProps.mResizeHandleSize;
8e08b761 3237
5515f252 3238 if ( pRow->mHasLowerHandle )
8e08b761 3239
5515f252 3240 newHeight -= mProps.mResizeHandleSize;
8e08b761 3241
5515f252
GT
3242 size_t i;
3243 for ( i = 0; i != pRow->mBars.Count(); ++i )
3244 {
3245 if ( !pRow->mBars[i]->IsFixed() )
3246 pRow->mBars[i]->mBounds.height = newHeight;
3247 }
8e08b761
JS
3248}
3249
3250void cbDockPane::GetRowResizeRange( cbRowInfo* pRow, int* from, int* till,
5515f252 3251 bool forUpperHandle )
8e08b761 3252{
5515f252 3253 cbRowInfo* pGivenRow = pRow;
8e08b761 3254
5515f252 3255 // calc unavailable space from above
8e08b761 3256
5515f252 3257 int notFree = 0;
8e08b761 3258
5515f252
GT
3259 while( pRow->mpPrev )
3260 {
3261 pRow = pRow->mpPrev;
8e08b761 3262
5515f252 3263 notFree += GetMinimalRowHeight( pRow );
8e08b761 3264
5515f252 3265 };
8e08b761 3266
5515f252 3267 *from = notFree;
8e08b761 3268
5515f252
GT
3269 // allow accupy the client window space by resizing pane rows
3270 if ( mAlignment == FL_ALIGN_BOTTOM )
8e08b761 3271
5515f252
GT
3272 *from -= mpLayout->GetClientHeight();
3273 else
3274 if ( mAlignment == FL_ALIGN_RIGHT )
8e08b761 3275
5515f252 3276 *from -= mpLayout->GetClientWidth();
8e08b761 3277
5515f252 3278 // calc unavailable space from below
8e08b761 3279
5515f252 3280 pRow = pGivenRow;
8e08b761 3281
5515f252 3282 notFree = 0;
8e08b761 3283
5515f252
GT
3284 while( pRow->mpNext )
3285 {
3286 pRow = pRow->mpNext;
8e08b761 3287
5515f252 3288 notFree += GetMinimalRowHeight( pRow );
8e08b761 3289
5515f252 3290 }
8e08b761 3291
5515f252 3292 *till = mPaneHeight - notFree;
8e08b761 3293
5515f252 3294 // allow adjustinig pane space vs. client window space by resizing pane row heights
8e08b761 3295
5515f252 3296 if ( mAlignment == FL_ALIGN_TOP )
8e08b761 3297
5515f252
GT
3298 *till += mpLayout->GetClientHeight();
3299 else
3300 if ( mAlignment == FL_ALIGN_LEFT )
8e08b761 3301
5515f252 3302 *till += mpLayout->GetClientWidth();
8e08b761 3303
5515f252 3304 // do not let the resizing of the row totally squeeze the row itself
8e08b761 3305
5515f252 3306 cbRowInfo& row = *pGivenRow;
8e08b761 3307
5515f252
GT
3308 if ( forUpperHandle )
3309 {
3310 *till = row.mRowY + row.mRowHeight - GetMinimalRowHeight( pGivenRow );
8e08b761 3311
5515f252 3312 if ( row.mHasUpperHandle )
8e08b761 3313
5515f252
GT
3314 *till -= mProps.mResizeHandleSize;
3315 }
3316 else
3317 {
3318 *from += GetMinimalRowHeight( pGivenRow );
8e08b761 3319
5515f252 3320 if ( row.mHasLowerHandle )
8e08b761 3321
5515f252
GT
3322 *from -= mProps.mResizeHandleSize;
3323 }
8e08b761
JS
3324}
3325
3326void cbDockPane::ResizeRow( cbRowInfo* pRow, int ofs,
5515f252 3327 bool forUpperHandle )
8e08b761 3328{
5515f252 3329 cbResizeRowEvent evt( pRow, ofs, forUpperHandle, this );
8e08b761 3330
5515f252 3331 mpLayout->FirePluginEvent( evt );
8e08b761
JS
3332}
3333
3334void cbDockPane::ResizeBar( cbBarInfo* pBar, int ofs,
5515f252 3335 bool forLeftHandle )
8e08b761 3336{
5515f252 3337 pBar->mpRow->mpExpandedBar = NULL;
8e08b761 3338
5515f252 3339 mpLayout->GetUpdatesManager().OnStartChanges();
8e08b761 3340
5515f252 3341 wxRect& bounds = pBar->mBounds;
8e08b761 3342
5515f252
GT
3343 if ( forLeftHandle )
3344 {
3345 // do not allow bar width become less then minimal
3346 if ( bounds.x + ofs > bounds.x + bounds.width - mProps.mMinCBarDim.x )
3347 {
3348 bounds.width = mProps.mMinCBarDim.x;
3349 bounds.x += ofs;
3350 }
3351 else
3352 {
3353 bounds.x += ofs;
3354 bounds.width -= ofs;
3355 }
3356 }
3357 else
3358 {
3359 // move bar left if necessary
3360 if ( bounds.width + ofs < mProps.mMinCBarDim.x )
3361 {
3362 bounds.x = bounds.x + bounds.width + ofs - mProps.mMinCBarDim.x;
3363 bounds.width = mProps.mMinCBarDim.x;
3364 }
3365 else
3366 // resize right border only
3367 bounds.width += ofs;
3368 }
8e08b761
JS
3369
3370
5515f252 3371 cbRowInfo* pToRow = pBar->mpRow;
8e08b761 3372
5515f252 3373 this->RemoveBar( pBar );
8e08b761 3374
5515f252 3375 InsertBar( pBar, pToRow );
8e08b761 3376
c82c42d4 3377 mpLayout->RecalcLayout(false);
8e08b761 3378
5515f252
GT
3379 mpLayout->GetUpdatesManager().OnFinishChanges();
3380 mpLayout->GetUpdatesManager().UpdateNow();
8e08b761
JS
3381}
3382
3383
3384/*** row/bar resizing related methods ***/
3385
3386void cbDockPane::DrawVertHandle( wxDC& dc, int x, int y, int height )
3387{
5515f252 3388 int lower = y + height;
8e08b761 3389
5515f252
GT
3390 dc.SetPen( mpLayout->mLightPen );
3391 dc.DrawLine( x,y, x, lower );
8e08b761 3392
5515f252
GT
3393 dc.SetPen( mpLayout->mGrayPen );
3394 int i;
3395 for ( i = 0; i != mProps.mResizeHandleSize-1; ++i )
3396 {
3397 ++x;
3398 dc.DrawLine( x,y, x, lower );
3399 }
8e08b761 3400
5515f252
GT
3401 dc.SetPen( mpLayout->mDarkPen );
3402 ++x;
3403 dc.DrawLine( x,y, x, lower );
8e08b761 3404
5515f252
GT
3405 dc.SetPen( mpLayout->mBlackPen );
3406 ++x;
3407 dc.DrawLine( x,y, x, lower );
8e08b761
JS
3408}
3409
3410void cbDockPane::DrawHorizHandle( wxDC& dc, int x, int y, int width )
3411{
5515f252 3412 int right = x + width;
8e08b761 3413
5515f252
GT
3414 dc.SetPen( mpLayout->mLightPen );
3415 dc.DrawLine( x,y, right, y );
8e08b761 3416
5515f252 3417 dc.SetPen( mpLayout->mGrayPen );
8e08b761 3418
5515f252
GT
3419 int i;
3420 for ( i = 0; i != mProps.mResizeHandleSize-1; ++i )
3421 {
3422 ++y;
3423 dc.DrawLine( x,y, right, y );
3424 }
8e08b761 3425
5515f252
GT
3426 dc.SetPen( mpLayout->mDarkPen );
3427 dc.DrawLine( x,y, right, ++y );
8e08b761 3428
5515f252
GT
3429 dc.SetPen( mpLayout->mBlackPen );
3430 dc.DrawLine( x,y, right, ++y );
8e08b761
JS
3431}
3432
3433cbBarInfo* cbDockPane::GetBarInfoByWindow( wxWindow* pBarWnd )
3434{
5515f252 3435 wxBarIterator i( mRows );
8e08b761 3436
5515f252
GT
3437 while( i.Next() )
3438
3439 if ( i.BarInfo().mpBarWnd == pBarWnd )
8e08b761 3440
5515f252 3441 return &i.BarInfo();
8e08b761 3442
5515f252 3443 return NULL;
8e08b761
JS
3444}
3445
3446void cbDockPane::GetRowShapeData( cbRowInfo* pRow, wxList* pLst )
3447{
b02a6dc2
WS
3448 if(pLst)
3449 {
3450 WX_CLEAR_LIST(wxList,*pLst);
3451 }
3452
5515f252 3453 pLst->Clear();
8e08b761 3454
5515f252
GT
3455 size_t i;
3456 for ( i = 0; i != pRow->mBars.Count(); ++i )
3457 {
3458 cbBarInfo& bar = *pRow->mBars[i];
8e08b761 3459
5515f252 3460 cbBarShapeData* pData = new cbBarShapeData();
8e08b761 3461
5515f252 3462 pLst->Append( (wxObject*)pData );
8e08b761 3463
5515f252
GT
3464 pData->mBounds = bar.mBounds;
3465 pData->mLenRatio = bar.mLenRatio;
3466 }
8e08b761
JS
3467}
3468
3469void cbDockPane::SetRowShapeData( cbRowInfo* pRow, wxList* pLst )
3470{
8495ba53 3471 if ( pLst->GetFirst() == NULL )
5515f252 3472 return;
8e08b761 3473
b02a6dc2 3474 wxObjectList::compatibility_iterator pData = pLst->GetFirst();
8e08b761 3475
5515f252
GT
3476 size_t i;
3477 for ( i = 0; i != pRow->mBars.Count(); ++i )
3478 {
3479 wxASSERT( pData ); // DBG::
8e08b761 3480
5515f252 3481 cbBarInfo& bar = *pRow->mBars[i];;
8e08b761 3482
8495ba53 3483 cbBarShapeData& data = *((cbBarShapeData*)pData->GetData());
8e08b761 3484
5515f252
GT
3485 bar.mBounds = data.mBounds;
3486 bar.mLenRatio = data.mLenRatio;
8e08b761 3487
8495ba53 3488 pData = pData->GetNext();
5515f252 3489 }
8e08b761
JS
3490}
3491
3492/***** Implementation for class cbUpdatesManagerBase *****/
3493
3494IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase, wxObject )
3495
3496/***** Implementation for class cbPluginBase *****/
3497
3498IMPLEMENT_ABSTRACT_CLASS( cbPluginBase, wxEvtHandler )
3499
3500cbPluginBase::~cbPluginBase()
3501{
5515f252 3502 // nothing
8e08b761
JS
3503}
3504
3505bool cbPluginBase::ProcessEvent(wxEvent& event)
3506{
5515f252 3507 if ( mPaneMask == wxALL_PANES )
8e08b761 3508
5515f252 3509 return wxEvtHandler::ProcessEvent( event );
8e08b761 3510
5515f252 3511 // extract mask info. from received event
8e08b761 3512
5515f252 3513 cbPluginEvent& evt = *( (cbPluginEvent*)&event );
8e08b761 3514
5515f252
GT
3515 if ( evt.mpPane == 0 &&
3516 mPaneMask == wxALL_PANES )
8e08b761 3517
5515f252 3518 return wxEvtHandler::ProcessEvent( event );
8e08b761 3519
5515f252 3520 int mask = 0;
8e08b761 3521
5515f252
GT
3522 switch ( evt.mpPane->mAlignment )
3523 {
3524 case FL_ALIGN_TOP : mask = FL_ALIGN_TOP_PANE; break;
3525 case FL_ALIGN_BOTTOM : mask = FL_ALIGN_BOTTOM_PANE;break;
3526 case FL_ALIGN_LEFT : mask = FL_ALIGN_LEFT_PANE; break;
3527 case FL_ALIGN_RIGHT : mask = FL_ALIGN_RIGHT_PANE; break;
3528 }
8e08b761 3529
5515f252 3530 // if event's pane maks matches the plugin's mask
8e08b761 3531
5515f252 3532 if ( mPaneMask & mask )
8e08b761 3533
5515f252 3534 return wxEvtHandler::ProcessEvent( event );
8e08b761 3535
5515f252 3536 // otherwise pass to the next handler if present
8e08b761 3537
5515f252 3538 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event ) )
8e08b761 3539
c82c42d4 3540 return true;
5515f252 3541 else
c82c42d4 3542 return false;
8e08b761
JS
3543}
3544