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