]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/fl/controlbar.cpp
minor corrections for compilation with gcc 3.3 (use cast of address instead
[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 }
873a543b 980 wxFAIL_MSG(wxT("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{
a55e5190
JS
1159 mpFrame->ProcessEvent( event );
1160 event.Skip( FALSE ); // stop its progpagation
1161
5515f252 1162 if ( event.GetEventObject() == (wxObject*) mpFrame )
4cf0b34c
GT
1163 {
1164 GetUpdatesManager().OnStartChanges();
5515f252 1165 RecalcLayout(TRUE);
4cf0b34c
GT
1166 GetUpdatesManager().OnFinishChanges();
1167 GetUpdatesManager().UpdateNow();
1168 }
1169
8e08b761
JS
1170}
1171
1172/*** protected members ***/
1173
1174void wxFrameLayout::HideBarWindows()
1175{
5515f252
GT
1176 size_t i;
1177 for ( i = 0; i != mAllBars.Count(); ++i )
1178 if ( mAllBars[i]->mpBarWnd && mAllBars[i]->mState != wxCBAR_FLOATING )
1179 mAllBars[i]->mpBarWnd->Show( FALSE );
8e08b761 1180
5515f252 1181 // then floated frames
8e08b761 1182
5515f252 1183 ShowFloatedWindows( FALSE );
8e08b761 1184
5515f252 1185 if ( mpFrameClient )
8e08b761 1186
5515f252 1187 mpFrameClient->Show( FALSE );
8e08b761
JS
1188}
1189
1190void wxFrameLayout::UnhookFromFrame()
1191{
5515f252 1192 // NOTE:: the SetEvtHandlerEnabled() method is not used
4cbc57f0 1193 // here, since it is assumed that unhooking layout
5515f252
GT
1194 // from window may result destroying of the layout itself
1195 //
1196 // BUG BUG BUG (wx):: this would not be a problem if
4cbc57f0 1197 // wxEvtHandler's destructor checked if
5515f252
GT
1198 // this handler is currently the top-most
1199 // handler of some window, and additionally
4cbc57f0
JS
1200 // to the reconnecting itself from the chain.
1201 // It would also re-setup current event handler
5515f252
GT
1202 // of the window using wxWindow::SetEventHandler()
1203
1204 // FOR NOW::
1205
1206 if ( mpFrame->GetEventHandler() == this )
5921a14e 1207 {
5515f252
GT
1208 mpFrame->PopEventHandler();
1209 return;
5921a14e 1210 }
8e08b761 1211
5515f252
GT
1212 if ( mpFrame )
1213 {
1214 if ( this == mpFrame->GetEventHandler() )
5921a14e 1215 {
5515f252 1216 mpFrame->SetEventHandler( this->GetNextHandler() );
5921a14e 1217 }
5515f252
GT
1218 else
1219 {
1220 wxEvtHandler* pCur = mpFrame->GetEventHandler();
8e08b761 1221
5515f252
GT
1222 while ( pCur )
1223 {
1224 if ( pCur == this )
5921a14e 1225 break;
8e08b761 1226
5515f252
GT
1227 pCur = pCur->GetNextHandler();
1228 }
8e08b761 1229
5515f252
GT
1230 // do not try to unhook ourselves if we're not hooked yet
1231 if ( !pCur )
5921a14e 1232 return;
5515f252 1233 }
8e08b761 1234
5515f252
GT
1235 if ( GetPreviousHandler() )
1236 GetPreviousHandler()->SetNextHandler( GetNextHandler() );
1237 else
1238 {
1239 mpFrame->PopEventHandler();
1240 return;
1241 }
8e08b761 1242
5515f252
GT
1243 if ( GetNextHandler() )
1244 GetNextHandler()->SetPreviousHandler( GetPreviousHandler() );
8e08b761 1245
5515f252
GT
1246 SetNextHandler( NULL );
1247 SetPreviousHandler( NULL );
1248 }
8e08b761
JS
1249}
1250
1251void wxFrameLayout::HookUpToFrame()
1252{
5515f252 1253 // unhook us first, we're already hooked up
8e08b761 1254
5515f252 1255 UnhookFromFrame();
8e08b761 1256
5515f252 1257 // put ourselves on top
8e08b761 1258
5515f252 1259 mpFrame->PushEventHandler( this );
8e08b761
JS
1260}
1261
1262cbDockPane* wxFrameLayout::GetBarPane( cbBarInfo* pBar )
1263{
5515f252
GT
1264 int i;
1265 for ( i = 0; i != MAX_PANES; ++i )
1266 if ( mPanes[i]->BarPresent( pBar ) )
1267 return mPanes[i];
8e08b761 1268
5515f252 1269 return NULL;
8e08b761
JS
1270}
1271
1272void wxFrameLayout::CreateCursors()
1273{
5515f252
GT
1274 /*
1275 // FIXME:: The below code somehow doesn't work - cursors remain unchanged
1276 char bits[64];
1277
1278 set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
8e08b761 1279
5515f252 1280 mpHorizCursor = new wxCursor( bits, 32, 16 );
8e08b761 1281
5515f252 1282 set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
8e08b761 1283
5515f252
GT
1284 mpVertCursor = new wxCursor( bits, 32, 16 );
1285 */
8e08b761 1286
5515f252 1287 // FOR NOW:: use standard ones
8e08b761
JS
1288
1289 mpHorizCursor = new wxCursor(wxCURSOR_SIZEWE);
1290 mpVertCursor = new wxCursor(wxCURSOR_SIZENS);
5515f252
GT
1291 mpNormalCursor = new wxCursor(wxCURSOR_ARROW );
1292 mpDragCursor = new wxCursor(wxCURSOR_CROSS );
1293 mpNECursor = new wxCursor(wxCURSOR_NO_ENTRY);
8e08b761 1294
5515f252
GT
1295 mFloatingPosStep.x = 25;
1296 mFloatingPosStep.y = 25;
8e08b761 1297
5515f252
GT
1298 mNextFloatedWndPos.x = mFloatingPosStep.x;
1299 mNextFloatedWndPos.y = mFloatingPosStep.y;
8e08b761
JS
1300}
1301
1302bool wxFrameLayout::HitTestPane( cbDockPane* pPane, int x, int y )
1303{
5515f252 1304 return rect_contains_point( pPane->GetRealRect(), x, y );
8e08b761
JS
1305}
1306
1307cbDockPane* wxFrameLayout::HitTestPanes( const wxRect& rect,
5515f252 1308 cbDockPane* pCurPane )
8e08b761 1309{
5515f252 1310 // first, give the privilege to the current pane
8e08b761 1311
5515f252
GT
1312 if ( pCurPane && rect_hits_rect( pCurPane->GetRealRect(), rect ) )
1313
1314 return pCurPane;
8e08b761 1315
5515f252
GT
1316 int i;
1317 for ( i = 0; i != MAX_PANES; ++i )
1318 {
1319 if ( pCurPane != mPanes[i] &&
1320 rect_hits_rect( mPanes[i]->GetRealRect(), rect ) )
1321 {
1322 return mPanes[i];
1323 }
1324 }
1325 return 0;
8e08b761
JS
1326}
1327
1328void wxFrameLayout::ForwardMouseEvent( wxMouseEvent& event,
5515f252
GT
1329 cbDockPane* pToPane,
1330 int eventType )
8e08b761 1331{
5515f252
GT
1332 wxPoint pos( event.m_x, event.m_y );
1333 pToPane->FrameToPane( &pos.x, &pos.y );
8e08b761 1334
5515f252
GT
1335 if ( eventType == cbEVT_PL_LEFT_DOWN )
1336 {
1337 cbLeftDownEvent evt( pos, pToPane );
1338 FirePluginEvent( evt );
1339 }
1340 else if ( eventType == cbEVT_PL_LEFT_DCLICK )
1341 {
1342 cbLeftDClickEvent evt( pos, pToPane );
1343 FirePluginEvent( evt );
1344 }
1345 else if ( eventType == cbEVT_PL_LEFT_UP )
1346 {
1347 cbLeftUpEvent evt( pos, pToPane );
1348 FirePluginEvent( evt );
1349 }
1350 else if ( eventType == cbEVT_PL_RIGHT_DOWN )
1351 {
1352 cbRightDownEvent evt( pos, pToPane );
1353 FirePluginEvent( evt );
1354 }
1355 else if ( eventType == cbEVT_PL_RIGHT_UP )
1356 {
1357 cbRightUpEvent evt( pos, pToPane );
1358 FirePluginEvent( evt );
1359 }
1360 else if ( eventType == cbEVT_PL_MOTION )
1361 {
1362 cbMotionEvent evt( pos, pToPane );
1363 FirePluginEvent( evt );
1364 }
1365 else
1366 {
1367 int avoidCompilerWarning = 0;
1368 wxASSERT(avoidCompilerWarning); // DBG::
1369 }
8e08b761
JS
1370} // wxFrameLayout::ForwardMouseEvent()
1371
1372
1373void wxFrameLayout::RouteMouseEvent( wxMouseEvent& event, int pluginEvtType )
1374{
5515f252 1375 if ( mpPaneInFocus )
8e08b761 1376
5515f252
GT
1377 ForwardMouseEvent( event, mpPaneInFocus, pluginEvtType );
1378 else
1379 {
1380 int i;
1381 for ( i = 0; i != MAX_PANES; ++i )
1382 {
1383 if ( HitTestPane( mPanes[i], event.m_x, event.m_y ) )
1384 {
1385 ForwardMouseEvent( event, mPanes[i], pluginEvtType );
1386 return;
1387 }
1388 }
1389 }
8e08b761
JS
1390}
1391
1392/*** event handlers ***/
1393
1394void wxFrameLayout::OnRButtonDown( wxMouseEvent& event )
1395{
5515f252 1396 RouteMouseEvent( event, cbEVT_PL_RIGHT_DOWN );
8e08b761
JS
1397}
1398
1399void wxFrameLayout::OnRButtonUp( wxMouseEvent& event )
1400{
5515f252 1401 RouteMouseEvent( event, cbEVT_PL_RIGHT_UP );
8e08b761
JS
1402}
1403
1404void wxFrameLayout::OnLButtonDown( wxMouseEvent& event )
1405{
5515f252 1406 RouteMouseEvent( event, cbEVT_PL_LEFT_DOWN );
8e08b761
JS
1407}
1408
1409void wxFrameLayout::OnLDblClick( wxMouseEvent& event )
1410{
5515f252 1411 RouteMouseEvent( event, cbEVT_PL_LEFT_DCLICK );
8e08b761
JS
1412}
1413
1414void wxFrameLayout::OnLButtonUp( wxMouseEvent& event )
1415{
5515f252 1416 RouteMouseEvent( event, cbEVT_PL_LEFT_UP );
8e08b761
JS
1417}
1418
1419void wxFrameLayout::OnMouseMove( wxMouseEvent& event )
1420{
5515f252
GT
1421 if ( mpPaneInFocus )
1422
1423 ForwardMouseEvent( event, mpPaneInFocus, cbEVT_PL_MOTION );
1424 else
1425 {
1426 int i;
1427 for ( i = 0; i != MAX_PANES; ++i )
1428 {
1429 if ( HitTestPane( mPanes[i], event.m_x, event.m_y ) )
1430 {
1431 if ( mpLRUPane && mpLRUPane != mPanes[i] )
1432 {
1433 // simulate "mouse-leave" event
1434 ForwardMouseEvent( event, mpLRUPane, cbEVT_PL_MOTION );
1435 }
8e08b761 1436
5515f252 1437 ForwardMouseEvent( event, mPanes[i], cbEVT_PL_MOTION );
8e08b761 1438
5515f252 1439 mpLRUPane = mPanes[i];
8e08b761 1440
5515f252
GT
1441 return;
1442 }
1443 }
1444 }
8e08b761 1445
5515f252
GT
1446 if ( mpLRUPane )
1447 {
1448 // simulate "mouse-leave" event
1449 ForwardMouseEvent( event, mpLRUPane, cbEVT_PL_MOTION );
1450 mpLRUPane = 0;
1451 }
8e08b761
JS
1452}
1453
1454void wxFrameLayout::OnPaint( wxPaintEvent& event )
1455{
5515f252
GT
1456 if ( mRecalcPending )
1457 RecalcLayout( TRUE );
8e08b761 1458
5515f252 1459 wxPaintDC dc(mpFrame);
8e08b761 1460
5515f252
GT
1461 int i;
1462 for ( i = 0; i != MAX_PANES; ++i )
1463 {
1464 wxRect& rect = mPanes[i]->mBoundsInParent;
8e08b761 1465
5515f252 1466 dc.SetClippingRegion( rect.x, rect.y, rect.width, rect.height );
8e08b761 1467
5515f252 1468 mPanes[i]->PaintPane(dc);
8e08b761 1469
5515f252
GT
1470 dc.DestroyClippingRegion();
1471 }
8e08b761 1472
5515f252 1473 event.Skip();
8e08b761
JS
1474}
1475
1476void wxFrameLayout::OnEraseBackground( wxEraseEvent& event )
1477{
5515f252 1478 // do nothing
8e08b761
JS
1479}
1480
1481void wxFrameLayout::OnIdle( wxIdleEvent& event )
1482{
5515f252 1483 wxWindow* focus = wxWindow::FindFocus();
8e08b761 1484
5515f252
GT
1485 if ( !focus && mCheckFocusWhenIdle )
1486 {
873a543b 1487 wxMessageBox(wxT("Hi, no more focus in this app!"));
8e08b761 1488
5515f252
GT
1489 mCheckFocusWhenIdle = FALSE;
1490 //ShowFloatedWindows( FALSE );
1491 }
8e08b761 1492
5515f252 1493 mCheckFocusWhenIdle = FALSE;
8e08b761 1494
5515f252 1495 event.Skip();
8e08b761
JS
1496}
1497
1498
1499void wxFrameLayout::OnKillFocus( wxFocusEvent& event )
1500{
5515f252
GT
1501 //wxMessageBox( "wxFrameLayoutGot Kill Focus!" );
1502 //ShowFloatedWindows( FALSE );
8e08b761
JS
1503}
1504
1505void wxFrameLayout::OnSetFocus( wxFocusEvent& event )
1506{
5515f252 1507 //ShowFloatedWindows( TRUE );
8e08b761
JS
1508}
1509
1510void wxFrameLayout::OnActivate( wxActivateEvent& event )
1511{
1512#if 0
5515f252
GT
1513 if ( event.GetActive() == FALSE )
1514 {
1515 wxWindow* focus = wxWindow::FindFocus();
8e08b761 1516
5515f252
GT
1517 if ( !focus || focus == &GetParentFrame() )
1518 {
1519 mCheckFocusWhenIdle = TRUE;
8e08b761 1520
5515f252 1521 if ( !focus )
8e08b761 1522
5515f252 1523 wxMessageBox("Deactivated!" );
8e08b761 1524
5515f252
GT
1525 }
1526 }
8e08b761
JS
1527#endif
1528}
1529
1530void wxFrameLayout::GetPaneProperties( cbCommonPaneProperties& props, int alignment )
1531{
5515f252 1532 props = mPanes[alignment]->mProps;
8e08b761
JS
1533}
1534
1535void wxFrameLayout::SetPaneProperties( const cbCommonPaneProperties& props, int paneMask )
1536{
5515f252
GT
1537 int i;
1538 for ( i = 0; i != MAX_PANES; ++i )
1539 {
1540 if ( mPanes[i]->MatchesMask( paneMask ) )
1541 mPanes[i]->mProps = props;
1542 }
8e08b761
JS
1543}
1544
1545void wxFrameLayout::SetMargins( int top, int bottom, int left, int right,
5515f252 1546 int paneMask )
8e08b761 1547{
5515f252
GT
1548 int i;
1549 for ( i = 0; i != MAX_PANES; ++i )
1550 {
1551 cbDockPane& pane = *mPanes[i];
8e08b761 1552
5515f252
GT
1553 if ( pane.MatchesMask( paneMask ) )
1554 {
1555 pane.mTopMargin = top;
1556 pane.mBottomMargin = bottom;
1557 pane.mLeftMargin = left;
1558 pane.mRightMargin = right;
1559 }
1560 }
8e08b761
JS
1561}
1562
1563void wxFrameLayout::SetPaneBackground( const wxColour& colour )
1564{
5515f252 1565 mBorderPen.SetColour( colour );
8e08b761
JS
1566}
1567
1568void wxFrameLayout::RefreshNow( bool recalcLayout )
1569{
4cf0b34c
GT
1570 if ( recalcLayout )
1571 RecalcLayout( TRUE );
8e08b761 1572
4cf0b34c
GT
1573 if ( mpFrame )
1574 mpFrame->Refresh();
8e08b761
JS
1575}
1576
1577/*** plugin-related methods ***/
1578
1579void wxFrameLayout::FirePluginEvent( cbPluginEvent& event )
1580{
5515f252 1581 // check state of input capture, before processing the event
8e08b761 1582
5515f252
GT
1583 if ( mpCaputesInput )
1584 {
1585 bool isInputEvt = TRUE;
8e08b761 1586#if wxCHECK_VERSION(2,3,0)
5515f252
GT
1587 if ( event.m_eventType != cbEVT_PL_LEFT_DOWN &&
1588 event.m_eventType != cbEVT_PL_LEFT_UP &&
1589 event.m_eventType != cbEVT_PL_RIGHT_DOWN &&
1590 event.m_eventType != cbEVT_PL_RIGHT_UP &&
1591 event.m_eventType != cbEVT_PL_MOTION )
1592 isInputEvt = FALSE;
8e08b761 1593#else
5515f252
GT
1594 switch ( event.m_eventType )
1595 {
1596 case cbEVT_PL_LEFT_DOWN : break;
1597 case cbEVT_PL_LEFT_UP : break;
1598 case cbEVT_PL_RIGHT_DOWN : break;
1599 case cbEVT_PL_RIGHT_UP : break;
1600 case cbEVT_PL_MOTION : break;
1601
1602 default : isInputEvt = FALSE; break;
1603 }
8e08b761
JS
1604#endif // #if wxCHECK_VERSION(2,3,0)
1605
5515f252
GT
1606 if ( isInputEvt )
1607 {
1608 mpCaputesInput->ProcessEvent( event );
1609 return;
1610 }
1611 }
8e08b761 1612
5515f252 1613 GetTopPlugin().ProcessEvent( event );
8e08b761
JS
1614}
1615
1616void wxFrameLayout::CaptureEventsForPlugin ( cbPluginBase* pPlugin )
1617{
5515f252
GT
1618 // cannot capture events for more than one plugin at a time
1619 wxASSERT( mpCaputesInput == NULL );
8e08b761 1620
5515f252 1621 mpCaputesInput = pPlugin;
8e08b761
JS
1622
1623}
1624
1625void wxFrameLayout::ReleaseEventsFromPlugin( cbPluginBase* pPlugin )
1626{
5515f252
GT
1627 // events should be captured first
1628 wxASSERT( mpCaputesInput != NULL );
8e08b761 1629
5515f252 1630 mpCaputesInput = NULL;
8e08b761
JS
1631}
1632
1633void wxFrameLayout::CaptureEventsForPane( cbDockPane* toPane )
1634{
5515f252
GT
1635 // cannot capture events twice (without releasing)
1636 wxASSERT( mpPaneInFocus == NULL );
8e08b761 1637
5515f252 1638 mpFrame->CaptureMouse();
8e08b761 1639
5515f252 1640 mpPaneInFocus = toPane;
8e08b761
JS
1641}
1642
1643void wxFrameLayout::ReleaseEventsFromPane( cbDockPane* fromPane )
1644{
5515f252
GT
1645 // cannot release events without capturing them
1646 wxASSERT( mpPaneInFocus != NULL );
8e08b761 1647
5515f252 1648 mpFrame->ReleaseMouse();
8e08b761 1649
5515f252 1650 mpPaneInFocus = NULL;
8e08b761
JS
1651}
1652
1653cbPluginBase& wxFrameLayout::GetTopPlugin()
1654{
5515f252
GT
1655 if ( !mpTopPlugin )
1656
1657 PushDefaultPlugins(); // automatic configuration
8e08b761 1658
5515f252 1659 return *mpTopPlugin;
8e08b761
JS
1660}
1661
1662void wxFrameLayout::SetTopPlugin( cbPluginBase* pPlugin )
1663{
5515f252 1664 mpTopPlugin = pPlugin;
8e08b761
JS
1665}
1666
1667bool wxFrameLayout::HasTopPlugin()
1668{
5515f252 1669 return ( mpTopPlugin != NULL );
8e08b761
JS
1670}
1671
1672void wxFrameLayout::PushPlugin( cbPluginBase* pPlugin )
1673{
5515f252
GT
1674 if ( !mpTopPlugin )
1675
1676 mpTopPlugin = pPlugin;
1677 else
1678 {
1679 pPlugin->SetNextHandler( mpTopPlugin );
8e08b761 1680
5515f252 1681 mpTopPlugin->SetPreviousHandler( pPlugin );
8e08b761 1682
5515f252
GT
1683 mpTopPlugin = pPlugin;
1684 }
8e08b761 1685
5515f252 1686 mpTopPlugin->OnInitPlugin(); // notification
8e08b761
JS
1687}
1688
1689void wxFrameLayout::PopPlugin()
1690{
5515f252 1691 wxASSERT( mpTopPlugin ); // DBG:: at least one plugin should be present
8e08b761 1692
5515f252 1693 cbPluginBase* pPopped = mpTopPlugin;
8e08b761 1694
5515f252 1695 mpTopPlugin = (cbPluginBase*)mpTopPlugin->GetNextHandler();
8e08b761 1696
5515f252 1697 delete pPopped;
8e08b761
JS
1698}
1699
1700void wxFrameLayout::PopAllPlugins()
1701{
5515f252 1702 while( mpTopPlugin ) PopPlugin();
8e08b761
JS
1703}
1704
1705void wxFrameLayout::PushDefaultPlugins()
1706{
5515f252 1707 // FIXME:: to much of the stuff for the default...
8e08b761 1708
5515f252
GT
1709 AddPlugin( CLASSINFO( cbRowLayoutPlugin ) );
1710 AddPlugin( CLASSINFO( cbBarDragPlugin ) );
1711 AddPlugin( CLASSINFO( cbPaneDrawPlugin ) );
8e08b761
JS
1712}
1713
1714void wxFrameLayout::AddPlugin( wxClassInfo* pPlInfo, int paneMask )
1715{
5515f252 1716 if ( FindPlugin ( pPlInfo ) ) return; // same type of plugin cannot be added twice
8e08b761 1717
5515f252 1718 cbPluginBase* pObj = (cbPluginBase*)pPlInfo->CreateObject();
8e08b761 1719
5515f252 1720 wxASSERT(pObj); // DBG:: plugin's class should be dynamic
8e08b761 1721
5515f252
GT
1722 pObj->mPaneMask = paneMask;
1723 pObj->mpLayout = this;
8e08b761 1724
5515f252 1725 PushPlugin( pObj );
8e08b761
JS
1726}
1727
1728void wxFrameLayout::AddPluginBefore( wxClassInfo* pNextPlInfo, wxClassInfo* pPlInfo,
5515f252 1729 int paneMask )
8e08b761 1730{
5515f252 1731 wxASSERT( pNextPlInfo != pPlInfo ); // DBG:: no sense
8e08b761 1732
5515f252 1733 cbPluginBase* pNextPl = FindPlugin( pNextPlInfo );
8e08b761 1734
5515f252
GT
1735 if ( !pNextPl )
1736 {
1737 AddPlugin( pPlInfo, paneMask );
8e08b761 1738
5515f252
GT
1739 return;
1740 }
8e08b761 1741
5515f252 1742 // remove existing one if present
8e08b761 1743
5515f252
GT
1744 cbPluginBase* pExistingPl = FindPlugin( pPlInfo );
1745
1746 if ( pExistingPl ) RemovePlugin( pPlInfo );
8e08b761 1747
5515f252 1748 // create an instance
8e08b761 1749
5515f252 1750 cbPluginBase* pNewPl = (cbPluginBase*)pPlInfo->CreateObject();
8e08b761 1751
5515f252 1752 wxASSERT(pNewPl); // DBG:: plugin's class should be dynamic
8e08b761 1753
5515f252 1754 // insert it to the chain
8e08b761 1755
5515f252
GT
1756 if ( pNextPl->GetPreviousHandler() )
1757
1758 pNextPl->GetPreviousHandler()->SetNextHandler( pNewPl );
1759 else
1760 mpTopPlugin = pNewPl;
8e08b761 1761
5515f252 1762 pNewPl->SetNextHandler( pNextPl );
8e08b761 1763
5515f252 1764 pNewPl->SetPreviousHandler( pNextPl->GetPreviousHandler() );
8e08b761 1765
5515f252 1766 pNextPl->SetPreviousHandler( pNewPl );
8e08b761 1767
5515f252 1768 // set it up
8e08b761 1769
5515f252
GT
1770 pNewPl->mPaneMask = paneMask;
1771 pNewPl->mpLayout = this;
8e08b761 1772
5515f252 1773 pNewPl->OnInitPlugin();
8e08b761
JS
1774}
1775
1776void wxFrameLayout::RemovePlugin( wxClassInfo* pPlInfo )
1777{
5515f252 1778 cbPluginBase* pPlugin = FindPlugin( pPlInfo );
8e08b761 1779
5515f252 1780 if ( !pPlugin ) return; // it's OK to remove not-existing plugin ;-)
8e08b761 1781
5515f252 1782 if ( pPlugin->GetPreviousHandler() == NULL )
8e08b761 1783
5515f252 1784 mpTopPlugin = (cbPluginBase*)pPlugin->GetNextHandler();
8e08b761 1785
5515f252 1786 delete pPlugin;
8e08b761
JS
1787}
1788
1789cbPluginBase* wxFrameLayout::FindPlugin( wxClassInfo* pPlInfo )
1790{
5515f252 1791 cbPluginBase *pCur = mpTopPlugin;
8e08b761 1792
5515f252
GT
1793 while( pCur )
1794 {
1795 // NOTE:: it might appear useful matching plugin
1796 // classes "polymorphically":
8e08b761 1797
5515f252 1798 if ( pCur->GetClassInfo()->IsKindOf( pPlInfo ) )
8e08b761 1799
5515f252 1800 return pCur;
8e08b761 1801
5515f252
GT
1802 pCur = (cbPluginBase*)pCur->GetNextHandler();
1803 }
8e08b761 1804
5515f252 1805 return NULL;
8e08b761
JS
1806}
1807
1808/***** Implementation for class cbUpdateMgrData *****/
1809
1810IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData, wxObject )
1811
1812cbUpdateMgrData::cbUpdateMgrData()
1813
5515f252
GT
1814 : mPrevBounds( -1,-1,0,0 ),
1815 mIsDirty( TRUE ) // inidicate initial change
8e08b761
JS
1816{}
1817
1818void cbUpdateMgrData::StoreItemState( const wxRect& boundsInParent )
1819{
5515f252 1820 mPrevBounds = boundsInParent;
8e08b761
JS
1821}
1822
1823void cbUpdateMgrData::SetDirty( bool isDirty )
1824{
5515f252 1825 mIsDirty = isDirty;
8e08b761
JS
1826}
1827
1828void cbUpdateMgrData::SetCustomData( wxObject* pCustomData )
1829{
5515f252 1830 mpCustomData = pCustomData;
8e08b761
JS
1831}
1832
1833/***** Implementation for class cbDockPane *****/
1834
1835void wxBarIterator::Reset()
1836{
5515f252
GT
1837 mpRow = ( mpRows->Count() ) ? (*mpRows)[0] : NULL;
1838 mpBar = NULL;
8e08b761
JS
1839}
1840
1841wxBarIterator::wxBarIterator( RowArrayT& rows )
1842
5515f252
GT
1843 : mpRows( &rows ),
1844 mpRow ( NULL ),
1845 mpBar ( NULL )
8e08b761 1846{
5515f252 1847 Reset();
8e08b761
JS
1848}
1849
1850bool wxBarIterator::Next()
5515f252
GT
1851{
1852 if ( mpRow )
1853 {
1854 if ( mpBar )
1855 mpBar = mpBar->mpNext;
1856 else
1857 {
1858 if ( mpRow->mBars.GetCount() == 0 )
1859 {
1860 return FALSE;
1861 }
1862
1863 mpBar = mpRow->mBars[0];
1864 }
1865
1866 if ( !mpBar )
1867 {
1868 // skip to the next row
1869
1870 mpRow = mpRow->mpNext;
1871
1872 if ( mpRow )
1873
1874 mpBar = mpRow->mBars[0];
1875 else
1876 return FALSE;
1877 }
1878
1879 return TRUE;
1880 }
1881 else
1882 return FALSE;
8e08b761
JS
1883}
1884
1885cbBarInfo& wxBarIterator::BarInfo()
1886{
5515f252 1887 return *mpBar;
8e08b761
JS
1888}
1889
1890cbRowInfo& wxBarIterator::RowInfo()
1891{
5515f252 1892 return *mpRow;
8e08b761
JS
1893}
1894
1895/***** Implementation for class cbBarDimHandlerBase *****/
1896
1897IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase, wxObject )
1898
1899cbBarDimHandlerBase::cbBarDimHandlerBase()
5515f252 1900 : mRefCount(0)
8e08b761
JS
1901{}
1902
1903void cbBarDimHandlerBase::AddRef()
1904{
5515f252 1905 ++mRefCount;
8e08b761
JS
1906}
1907
1908void cbBarDimHandlerBase::RemoveRef()
1909{
5515f252 1910 if ( --mRefCount <= 0 ) delete this;
8e08b761
JS
1911}
1912
1913/***** Implementation for class cbDimInfo *****/
1914
1915IMPLEMENT_DYNAMIC_CLASS( cbDimInfo, wxObject )
1916
1917cbDimInfo::cbDimInfo()
1918
5515f252
GT
1919 : mVertGap ( 0 ),
1920 mHorizGap( 0 ),
8e08b761 1921
5515f252
GT
1922 mIsFixed(TRUE),
1923 mpHandler( NULL )
8e08b761 1924{
5515f252
GT
1925 size_t i;
1926 for ( i = 0; i != MAX_BAR_STATES; ++i )
1927 {
1928 mSizes[i].x = 20;
1929 mSizes[i].y = 20;
8e08b761 1930
5515f252
GT
1931 mBounds[i] = wxRect( -1,-1,-1,-1 );
1932 }
8e08b761
JS
1933}
1934
1935cbDimInfo::cbDimInfo( cbBarDimHandlerBase* pDimHandler,
5515f252 1936 bool isFixed )
8e08b761 1937
5515f252
GT
1938 : mVertGap ( 0 ),
1939 mHorizGap( 0 ),
1940 mIsFixed ( isFixed ),
8e08b761 1941
5515f252 1942 mpHandler( pDimHandler )
8e08b761 1943{
5515f252
GT
1944 if ( mpHandler )
1945 {
1946 // int vtad = *((int*)mpHandler);
1947 mpHandler->AddRef();
1948 }
1949
1950 size_t i;
1951 for ( i = 0; i != MAX_BAR_STATES; ++i )
1952 {
1953 mSizes[i].x = -1;
1954 mSizes[i].y = -1;
8e08b761 1955
5515f252
GT
1956 mBounds[i] = wxRect( -1,-1,-1,-1 );
1957 }
8e08b761
JS
1958}
1959
1960cbDimInfo::cbDimInfo( int dh_x, int dh_y,
5515f252
GT
1961 int dv_x, int dv_y,
1962 int f_x, int f_y,
1963
1964 bool isFixed,
1965 int horizGap,
1966 int vertGap,
1967
1968 cbBarDimHandlerBase* pDimHandler
1969 )
1970 : mVertGap ( vertGap ),
1971 mHorizGap ( horizGap ),
1972 mIsFixed ( isFixed ),
1973 mpHandler( pDimHandler )
1974{
1975 if ( mpHandler )
1976 {
1977 // int vtad = *((int*)mpHandler);
1978 mpHandler->AddRef();
1979 }
1980
1981 mSizes[wxCBAR_DOCKED_HORIZONTALLY].x = dh_x;
1982 mSizes[wxCBAR_DOCKED_HORIZONTALLY].y = dh_y;
1983 mSizes[wxCBAR_DOCKED_VERTICALLY ].x = dv_x;
1984 mSizes[wxCBAR_DOCKED_VERTICALLY ].y = dv_y;
1985 mSizes[wxCBAR_FLOATING ].x = f_x;
1986 mSizes[wxCBAR_FLOATING ].y = f_y;
1987
1988 size_t i;
1989 for ( i = 0; i != MAX_BAR_STATES; ++i )
1990 mBounds[i] = wxRect( -1,-1,-1,-1 );
1991}
8e08b761
JS
1992
1993cbDimInfo::cbDimInfo( int x, int y,
1994 bool isFixed, int gap,
1995 cbBarDimHandlerBase* pDimHandler)
1996 : mVertGap ( gap ),
1997 mHorizGap ( gap ),
1998 mIsFixed ( isFixed ),
1999 mpHandler( pDimHandler )
2000{
2001 if ( mpHandler )
2002 {
2003 // int vtad = *((int*)mpHandler);
2004 mpHandler->AddRef();
2005 }
2006
2007 mSizes[wxCBAR_DOCKED_HORIZONTALLY].x = x;
2008 mSizes[wxCBAR_DOCKED_HORIZONTALLY].y = y;
2009 mSizes[wxCBAR_DOCKED_VERTICALLY ].x = x;
2010 mSizes[wxCBAR_DOCKED_VERTICALLY ].y = y;
2011 mSizes[wxCBAR_FLOATING ].x = x;
2012 mSizes[wxCBAR_FLOATING ].y = y;
5515f252
GT
2013
2014 size_t i;
2015 for ( i = 0; i != MAX_BAR_STATES; ++i )
8e08b761
JS
2016 mBounds[i] = wxRect( -1,-1,-1,-1 );
2017}
2018
2019cbDimInfo::~cbDimInfo()
2020{
5515f252
GT
2021 if ( mpHandler )
2022
2023 mpHandler->RemoveRef();
8e08b761
JS
2024}
2025
2026const cbDimInfo& cbDimInfo::operator=( const cbDimInfo& other )
2027{
5515f252
GT
2028 if ( this == &other )
2029 return *this;
8e08b761 2030
5515f252
GT
2031 int i;
2032 for ( i = 0; i != MAX_BAR_STATES; ++i )
2033 mSizes[i] = other.mSizes[i];
8e08b761 2034
5515f252
GT
2035 mIsFixed = other.mIsFixed;
2036 mpHandler = other.mpHandler;
8e08b761 2037
5515f252
GT
2038 mVertGap = other.mVertGap;
2039 mHorizGap = other.mHorizGap;
8e08b761 2040
5515f252 2041 if ( mpHandler )
8e08b761 2042
5515f252 2043 mpHandler->AddRef();
8e08b761 2044
5515f252 2045 return *this;
8e08b761
JS
2046}
2047
2048/***** Implementation for structure cbCommonPaneProperties *****/
2049
2050IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties, wxObject )
2051
2052cbCommonPaneProperties::cbCommonPaneProperties(void)
2053
5515f252
GT
2054 : mRealTimeUpdatesOn ( TRUE ),
2055 mOutOfPaneDragOn ( TRUE ),
2056 mExactDockPredictionOn( FALSE ),
6e8515a3 2057 mNonDestructFrictionOn( FALSE ),
5515f252
GT
2058 mShow3DPaneBorderOn ( TRUE ),
2059 mBarFloatingOn ( FALSE ),
2060 mRowProportionsOn ( FALSE ),
2061 mColProportionsOn ( TRUE ),
2062 mBarCollapseIconsOn ( FALSE ),
2063 mBarDragHintsOn ( FALSE ),
2064
2065 mMinCBarDim( 16, 16 ),
2066 mResizeHandleSize( 4 )
8e08b761
JS
2067{}
2068
69b8ed1b
GD
2069cbCommonPaneProperties::cbCommonPaneProperties(const cbCommonPaneProperties& props)
2070
2071 : wxObject(),
2072 mRealTimeUpdatesOn (props.mRealTimeUpdatesOn),
2073 mOutOfPaneDragOn (props.mOutOfPaneDragOn),
2074 mExactDockPredictionOn(props.mExactDockPredictionOn),
2075 mNonDestructFrictionOn(props.mNonDestructFrictionOn),
2076 mShow3DPaneBorderOn (props.mShow3DPaneBorderOn),
2077 mBarFloatingOn (props.mBarFloatingOn),
2078 mRowProportionsOn (props.mRowProportionsOn),
2079 mColProportionsOn (props.mColProportionsOn),
2080 mBarCollapseIconsOn (props.mBarCollapseIconsOn),
2081 mBarDragHintsOn (props.mBarDragHintsOn),
2082
2083 mMinCBarDim(props.mMinCBarDim),
2084 mResizeHandleSize(props.mResizeHandleSize)
2085{}
2086
2087cbCommonPaneProperties& cbCommonPaneProperties::operator=(const cbCommonPaneProperties& props)
2088{
2708457a
GD
2089 mRealTimeUpdatesOn = props.mRealTimeUpdatesOn;
2090 mOutOfPaneDragOn = props.mOutOfPaneDragOn;
2091 mExactDockPredictionOn = props.mExactDockPredictionOn;
2092 mNonDestructFrictionOn = props.mNonDestructFrictionOn;
2093 mShow3DPaneBorderOn = props.mShow3DPaneBorderOn;
2094 mBarFloatingOn = props.mBarFloatingOn;
2095 mRowProportionsOn = props.mRowProportionsOn;
2096 mColProportionsOn = props.mColProportionsOn;
2097 mBarCollapseIconsOn = props.mBarCollapseIconsOn;
2098 mBarDragHintsOn = props.mBarDragHintsOn;
2099
2100 mMinCBarDim = props.mMinCBarDim;
2101 mResizeHandleSize = props.mResizeHandleSize;
2102
69b8ed1b
GD
2103 return *this;
2104}
2105
8e08b761
JS
2106/***** Implementation for class cbRowInfo *****/
2107
2108IMPLEMENT_DYNAMIC_CLASS( cbRowInfo, wxObject )
2109
2110cbRowInfo::cbRowInfo(void)
2111
5515f252
GT
2112 : mNotFixedBarsCnt( FALSE ),
2113 mpNext ( NULL ),
2114 mpPrev ( NULL ),
2115 mpExpandedBar ( NULL )
8e08b761
JS
2116{}
2117
2118cbRowInfo::~cbRowInfo()
2119{
5515f252
GT
2120 // nothing! all bars are removed using global bar
2121 // list in wxFrameLayout class
8e08b761
JS
2122}
2123
2124/***** Implementation for class cbBarInfo *****/
2125
2126IMPLEMENT_DYNAMIC_CLASS( cbBarInfo, wxObject )
2127
2128cbBarInfo::cbBarInfo(void)
2129
5515f252 2130 : mpRow( NULL ),
5515f252 2131 mpNext( NULL ),
fc7c8ae9
JS
2132 mpPrev( NULL ),
2133 mFloatingOn( TRUE )
8e08b761
JS
2134{}
2135
2136cbBarInfo::~cbBarInfo()
2137{
5515f252 2138 // nothing
8e08b761
JS
2139}
2140
2141/***** Implementation for class cbDockPane *****/
2142
2143IMPLEMENT_DYNAMIC_CLASS( cbDockPane, wxObject )
2144
2145// FIXME:: how to eliminate these cut&pasted constructors?
2146
5515f252
GT
2147cbDockPane::cbDockPane(void)
2148 : mLeftMargin ( 1 ),
2149 mRightMargin ( 1 ),
2150 mTopMargin ( 1 ),
2151 mBottomMargin( 1 ),
2152 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2153 // since the real dimensions of the pane may not
2154 // be known, while inserting bars initially
2155 mPaneHeight( 32768 ),
2156 mAlignment ( -1 ),
2157 mpLayout ( 0 ),
2158 mpStoredRow( NULL )
8e08b761
JS
2159{}
2160
2161cbDockPane::cbDockPane( int alignment, wxFrameLayout* pPanel )
5515f252
GT
2162
2163 : mLeftMargin ( 1 ),
2164 mRightMargin ( 1 ),
2165 mTopMargin ( 1 ),
2166 mBottomMargin( 1 ),
2167 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2168 // since the real dimensions of the pane may not
2169 // be known, while inserting bars initially
2170 mPaneHeight( 32768 ),
2171 mAlignment ( alignment ),
2172 mpLayout ( pPanel ),
2173 mpStoredRow( NULL )
8e08b761
JS
2174{}
2175
2176cbDockPane::~cbDockPane()
2177{
5515f252
GT
2178 size_t i;
2179 for ( i = 0; i != mRows.Count(); ++i )
2180 delete mRows[i];
8e08b761 2181
5515f252
GT
2182 mRowShapeData.DeleteContents( TRUE );
2183
2184 // NOTE:: control bar infromation structures are cleaned-up
2185 // in wxFrameLayout's destructor, using global control-bar list
8e08b761
JS
2186}
2187
2188void cbDockPane::SetMargins( int top, int bottom, int left, int right )
2189{
5515f252
GT
2190 mTopMargin = top;
2191 mBottomMargin = bottom;
2192 mLeftMargin = left;
2193 mRightMargin = right;
8e08b761
JS
2194}
2195
2196/*** helpers of cbDockPane ***/
2197
2198void cbDockPane::PaintBarDecorations( cbBarInfo* pBar, wxDC& dc )
2199{
5515f252 2200 cbDrawBarDecorEvent evt( pBar, dc, this );
8e08b761 2201
5515f252 2202 mpLayout->FirePluginEvent( evt );
8e08b761
JS
2203}
2204
2205void cbDockPane::PaintBarHandles( cbBarInfo* pBar, wxDC& dc )
2206{
5515f252 2207 cbDrawBarHandlesEvent evt( pBar, dc, this );
8e08b761 2208
5515f252 2209 mpLayout->FirePluginEvent( evt );
8e08b761
JS
2210}
2211
2212void cbDockPane::PaintBar( cbBarInfo* pBar, wxDC& dc )
2213{
5515f252
GT
2214 PaintBarDecorations( pBar, dc );
2215 PaintBarHandles( pBar, dc );
8e08b761
JS
2216}
2217
2218void cbDockPane::PaintRowHandles( cbRowInfo* pRow, wxDC& dc )
2219{
5515f252 2220 cbDrawRowHandlesEvent evt( pRow, dc, this );
8e08b761 2221
5515f252 2222 mpLayout->FirePluginEvent( evt );
8e08b761 2223
5515f252 2224 cbDrawRowDecorEvent evt1( pRow, dc, this );
8e08b761 2225
5515f252 2226 mpLayout->FirePluginEvent( evt1 );
8e08b761
JS
2227}
2228
2229void cbDockPane::PaintRowBackground ( cbRowInfo* pRow, wxDC& dc )
2230{
5515f252 2231 cbDrawRowBkGroundEvent evt( pRow, dc, this );
8e08b761 2232
5515f252 2233 mpLayout->FirePluginEvent( evt );
8e08b761
JS
2234}
2235
2236void cbDockPane::PaintRowDecorations( cbRowInfo* pRow, wxDC& dc )
2237{
5515f252 2238 size_t i = 0;
8e08b761 2239
5515f252
GT
2240 // decorations first
2241 for ( i = 0; i != pRow->mBars.Count(); ++i )
2242
2243 PaintBarDecorations( pRow->mBars[i], dc );
8e08b761 2244
5515f252
GT
2245 // then handles if present
2246 for ( i = 0; i != pRow->mBars.Count(); ++i )
8e08b761 2247
5515f252 2248 PaintBarHandles( pRow->mBars[i], dc );
8e08b761
JS
2249}
2250
2251void cbDockPane::PaintRow( cbRowInfo* pRow, wxDC& dc )
2252{
5515f252
GT
2253 PaintRowBackground ( pRow, dc );
2254 PaintRowDecorations( pRow, dc );
2255 PaintRowHandles ( pRow, dc );
8e08b761
JS
2256}
2257
2258void cbDockPane::PaintPaneBackground( wxDC& dc )
2259{
5515f252 2260 cbDrawPaneBkGroundEvent evt( dc, this );
8e08b761 2261
5515f252 2262 mpLayout->FirePluginEvent( evt );
8e08b761
JS
2263}
2264
2265void cbDockPane::PaintPaneDecorations( wxDC& dc )
2266{
5515f252 2267 cbDrawPaneDecorEvent evt( dc, this );
8e08b761 2268
5515f252 2269 mpLayout->FirePluginEvent( evt );
8e08b761
JS
2270}
2271
2272void cbDockPane::PaintPane( wxDC& dc )
2273{
5515f252 2274 PaintPaneBackground( dc );
8e08b761 2275
5515f252 2276 size_t i = 0;
8e08b761 2277
5515f252
GT
2278 // first decorations
2279 for ( i = 0; i != mRows.Count(); ++i )
2280 {
2281 PaintRowBackground( mRows[i], dc );
2282 PaintRowDecorations( mRows[i], dc );
2283 }
8e08b761 2284
5515f252
GT
2285 // than handles
2286 for ( i = 0; i != mRows.Count(); ++i )
2287 PaintRowHandles( mRows[i], dc );
8e08b761 2288
5515f252
GT
2289 // and finally
2290 PaintPaneDecorations( dc );
8e08b761
JS
2291}
2292
2293void cbDockPane::SizeBar( cbBarInfo* pBar )
2294{
5515f252 2295 cbSizeBarWndEvent evt( pBar, this );
8e08b761 2296
5515f252
GT
2297 mpLayout->FirePluginEvent( evt );
2298 return;
8e08b761
JS
2299}
2300
2301void cbDockPane::SizeRowObjects( cbRowInfo* pRow )
2302{
5515f252
GT
2303 size_t i;
2304 for ( i = 0; i != pRow->mBars.Count(); ++i )
2305 SizeBar( pRow->mBars[i] );
8e08b761
JS
2306}
2307
2308void cbDockPane::SizePaneObjects()
2309{
5515f252
GT
2310 size_t i;
2311 for ( i = 0; i != mRows.Count(); ++i )
2312 SizeRowObjects( mRows[i] );
8e08b761
JS
2313}
2314
2315wxDC* cbDockPane::StartDrawInArea( const wxRect& area )
2316{
5515f252 2317 wxDC* pDc = 0;
8e08b761 2318
5515f252 2319 cbStartDrawInAreaEvent evt( area, &pDc, this );
8e08b761 2320
5515f252 2321 mpLayout->FirePluginEvent( evt );
8e08b761 2322
5515f252 2323 return pDc;
8e08b761
JS
2324}
2325
2326void cbDockPane::FinishDrawInArea( const wxRect& area )
2327{
5515f252 2328 cbFinishDrawInAreaEvent evt( area, this );
8e08b761 2329
5515f252 2330 mpLayout->FirePluginEvent( evt );
8e08b761
JS
2331}
2332
2333bool cbDockPane::IsFixedSize( cbBarInfo* pInfo )
2334{
5515f252 2335 return ( pInfo->mDimInfo.mIsFixed );
8e08b761
JS
2336}
2337
2338int cbDockPane::GetNotFixedBarsCount( cbRowInfo* pRow )
2339{
5515f252 2340 int cnt = 0;
8e08b761 2341
5515f252
GT
2342 size_t i;
2343 for ( i = 0; i != pRow->mBars.Count(); ++i )
2344 {
2345 if ( !pRow->mBars[i]->IsFixed() )
2346 ++cnt;
2347 }
8e08b761 2348
5515f252 2349 return cnt;
8e08b761
JS
2350}
2351
2352void cbDockPane::RemoveBar( cbBarInfo* pBar )
2353{
6e8515a3 2354 bool needsRestoring = mProps.mNonDestructFrictionOn &&
5515f252 2355 mpStoredRow == pBar->mpRow;
8e08b761 2356
5515f252 2357 cbRemoveBarEvent evt( pBar, this );
8e08b761 2358
5515f252 2359 mpLayout->FirePluginEvent( evt );
8e08b761 2360
5515f252
GT
2361 if ( needsRestoring )
2362 {
2363 SetRowShapeData( mpStoredRow, &mRowShapeData );
8e08b761 2364
5515f252
GT
2365 mpStoredRow = NULL;
2366 }
8e08b761
JS
2367}
2368
2369void cbDockPane::SyncRowFlags( cbRowInfo* pRow )
2370{
5515f252
GT
2371 // setup mHasOnlyFixedBars flag for the row information
2372 pRow->mHasOnlyFixedBars = TRUE;
8e08b761 2373
5515f252 2374 pRow->mNotFixedBarsCnt = 0;
8e08b761 2375
5515f252
GT
2376 size_t i;
2377 for ( i = 0; i != pRow->mBars.Count(); ++i )
2378 {
2379 cbBarInfo& bar = *pRow->mBars[i];
8e08b761 2380
5515f252 2381 bar.mpRow = pRow;
8e08b761 2382
5515f252
GT
2383 if ( !bar.IsFixed() )
2384 {
2385 pRow->mHasOnlyFixedBars = FALSE;
2386 ++pRow->mNotFixedBarsCnt;
2387 }
2388 }
8e08b761
JS
2389}
2390
2391void cbDockPane::FrameToPane( int* x, int* y )
2392{
5515f252
GT
2393 *x -= mLeftMargin;
2394 *y -= mTopMargin;
8e08b761 2395
5515f252
GT
2396 if ( mAlignment == FL_ALIGN_TOP ||
2397 mAlignment == FL_ALIGN_BOTTOM
2398 )
2399 {
2400 *x -= mBoundsInParent.x;
2401 *y -= mBoundsInParent.y;
2402 }
2403 else
2404 {
2405 int rx = *x, ry = *y;
8e08b761 2406
5515f252 2407 *x = ry - mBoundsInParent.y;
8e08b761 2408
5515f252
GT
2409 *y = rx - mBoundsInParent.x;
2410 }
8e08b761
JS
2411}
2412
2413void cbDockPane::PaneToFrame( int* x, int* y )
2414{
5515f252
GT
2415 if ( mAlignment == FL_ALIGN_TOP ||
2416 mAlignment == FL_ALIGN_BOTTOM
2417 )
2418 {
2419 *x += mBoundsInParent.x;
2420 *y += mBoundsInParent.y;
2421 }
2422 else
2423 {
2424 int rx = *x, ry = *y;
8e08b761 2425
5515f252 2426 *x = ry + mBoundsInParent.x;
8e08b761 2427
5515f252
GT
2428 *y = mBoundsInParent.y + rx;
2429 }
8e08b761 2430
5515f252
GT
2431 *x += mLeftMargin;
2432 *y += mTopMargin;
8e08b761
JS
2433}
2434
2435void cbDockPane::FrameToPane( wxRect* pRect )
2436{
5515f252
GT
2437 wxPoint upperLeft ( pRect->x, pRect->y );
2438 wxPoint lowerRight( pRect->x + pRect->width,
2439 pRect->y + pRect->height );
8e08b761 2440
5515f252
GT
2441 FrameToPane( &upperLeft.x, &upperLeft.y );
2442 FrameToPane( &lowerRight.x, &lowerRight.y );
8e08b761 2443
5515f252
GT
2444 pRect->x = wxMin(upperLeft.x,lowerRight.x);
2445 pRect->y = wxMin(upperLeft.y,lowerRight.y);
8e08b761 2446
5515f252
GT
2447 pRect->width = abs( lowerRight.x - upperLeft.x );
2448 pRect->height = abs( lowerRight.y - upperLeft.y );
8e08b761
JS
2449}
2450
2451void cbDockPane::PaneToFrame( wxRect* pRect )
2452{
5515f252
GT
2453 wxPoint upperLeft ( pRect->x, pRect->y );
2454 wxPoint lowerRight( pRect->x + pRect->width,
2455 pRect->y + pRect->height );
8e08b761 2456
5515f252
GT
2457 PaneToFrame( &upperLeft.x, &upperLeft.y );
2458 PaneToFrame( &lowerRight.x, &lowerRight.y );
8e08b761 2459
5515f252 2460 //wxRect newRect = wxRect( upperLeft, lowerRight );
8e08b761 2461
5515f252
GT
2462 pRect->x = wxMin(upperLeft.x,lowerRight.x);
2463 pRect->y = wxMin(upperLeft.y,lowerRight.y);
8e08b761 2464
5515f252
GT
2465 pRect->width = abs( lowerRight.x - upperLeft.x );
2466 pRect->height = abs( lowerRight.y - upperLeft.y );
8e08b761
JS
2467}
2468
2469int cbDockPane::GetRowAt( int paneY )
2470{
5515f252
GT
2471 if ( paneY < 0 )
2472 return -1;
8e08b761 2473
5515f252 2474 int curY = 0;
8e08b761 2475
5515f252 2476 size_t i = 0;
8e08b761 2477
5515f252
GT
2478 for ( ; i != mRows.Count(); ++i )
2479 {
2480 int rowHeight = mRows[i]->mRowHeight;
8e08b761 2481
5515f252
GT
2482 int third = rowHeight/3;
2483
2484 if ( paneY >= curY && paneY < curY + third )
2485 return i-1;
8e08b761 2486
5515f252
GT
2487 if ( paneY >= curY + third && paneY < curY + rowHeight - third )
2488 return i;
8e08b761 2489
5515f252
GT
2490 curY += rowHeight;
2491 }
8e08b761 2492
5515f252 2493 return i;
8e08b761
JS
2494}
2495
2496int cbDockPane::GetRowAt( int upperY, int lowerY )
2497{
5515f252
GT
2498 /*
2499 // OLD STUFF::
2500 int range = lowerY - upperY;
2501 int oneThird = range / 3;
8e08b761 2502
5515f252
GT
2503 wxNode* pRow = mRows.First();
2504 int row = 0;
2505 int curY = 0;
8e08b761 2506
5515f252 2507 if ( lowerY <= 0 ) return -1;
8e08b761 2508
5515f252
GT
2509 while( pRow )
2510 {
2511 int rowHeight = GetRowHeight( (wxList*)pRow->Data() );
8e08b761 2512
5515f252
GT
2513 if ( upperY >= curY &&
2514 lowerY < curY ) return row;
8e08b761 2515
5515f252
GT
2516 if ( upperY <= curY &&
2517 lowerY >= curY &&
2518 curY - upperY >= oneThird ) return row-1;
8e08b761 2519
5515f252
GT
2520 if ( ( upperY < curY + rowHeight &&
2521 lowerY >= curY + rowHeight &&
2522 curY + rowHeight - lowerY >= oneThird )
2523 )
2524 return row+1;
8e08b761 2525
5515f252 2526 if ( lowerY <= curY + rowHeight ) return row;
8e08b761 2527
5515f252
GT
2528 ++row;
2529 curY += rowHeight;
2530 pRow = pRow->Next();
2531 }
2532 */
8e08b761 2533
5515f252 2534 int mid = upperY + (lowerY - upperY)/2;
8e08b761 2535
5515f252
GT
2536 if ( mid < 0 )
2537 return -1;
8e08b761 2538
5515f252
GT
2539 int curY = 0;
2540 size_t i = 0;
8e08b761 2541
5515f252
GT
2542 for ( ; i != mRows.Count(); ++i )
2543 {
2544 int rowHeight = mRows[i]->mRowHeight;
8e08b761 2545
5515f252 2546 if ( mid >= curY && mid < curY + rowHeight ) return i;
8e08b761 2547
5515f252
GT
2548 curY += rowHeight;
2549 }
8e08b761 2550
5515f252 2551 return i;
8e08b761
JS
2552}
2553
2554int cbDockPane::GetRowY( cbRowInfo* pRow )
2555{
5515f252 2556 int curY = 0;
8e08b761 2557
5515f252
GT
2558 size_t i;
2559 for ( i = 0; i != mRows.Count(); ++i )
2560 {
2561 if ( mRows[i] == pRow )
2562 break;
8e08b761 2563
5515f252
GT
2564 curY += mRows[i]->mRowHeight;
2565 }
8e08b761 2566
5515f252 2567 return curY;
8e08b761
JS
2568}
2569
2570bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo* pRow )
2571{
5515f252
GT
2572 while ( pRow->mpPrev )
2573 {
2574 pRow = pRow->mpPrev;
8e08b761 2575
5515f252 2576 if ( pRow->mHasOnlyFixedBars )
8e08b761 2577
5515f252
GT
2578 return TRUE;
2579 }
8e08b761 2580
5515f252 2581 return FALSE;
8e08b761
JS
2582}
2583
2584bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo* pRow )
2585{
5515f252
GT
2586 while( pRow->mpNext )
2587 {
2588 pRow = pRow->mpNext;
8e08b761 2589
5515f252 2590 if ( pRow->mHasOnlyFixedBars )
8e08b761 2591
5515f252
GT
2592 return TRUE;
2593 }
8e08b761 2594
5515f252 2595 return FALSE;
8e08b761
JS
2596}
2597
2598bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo* pBar )
2599{
5515f252
GT
2600 while( pBar->mpPrev )
2601 {
2602 pBar = pBar->mpPrev;
8e08b761 2603
5515f252 2604 if ( pBar->IsFixed() )
8e08b761 2605
5515f252
GT
2606 return TRUE;
2607 }
2608
2609 return FALSE;
8e08b761
JS
2610}
2611
2612bool cbDockPane::HasNotFixedBarsRight( cbBarInfo* pBar )
2613{
5515f252
GT
2614 while( pBar->mpNext )
2615 {
2616 pBar = pBar->mpNext;
8e08b761 2617
5515f252 2618 if ( pBar->IsFixed() )
8e08b761 2619
5515f252
GT
2620 return TRUE;
2621 }
2622
2623 return FALSE;
8e08b761
JS
2624}
2625
2626void cbDockPane::CalcLengthRatios( cbRowInfo* pInRow )
2627{
5515f252 2628 int totalWidth = 0;
8e08b761 2629
5515f252 2630 size_t i = 0;
8e08b761 2631
4cbc57f0 2632 // calc current-maximal-total-length of all maximized bars
8e08b761 2633
5515f252
GT
2634 for ( i = 0; i != pInRow->mBars.GetCount(); ++i )
2635 {
2636 cbBarInfo& bar = *pInRow->mBars[i];
8e08b761 2637
5515f252
GT
2638 if ( !bar.IsFixed() )
2639 totalWidth += bar.mBounds.width;
2640 }
8e08b761 2641
4cbc57f0 2642 // set up percentages of occupied space for each maximized bar
8e08b761 2643
5515f252
GT
2644 for ( i = 0; i != pInRow->mBars.Count(); ++i )
2645 {
2646 cbBarInfo& bar = *pInRow->mBars[i];
8e08b761 2647
5515f252
GT
2648 if ( !bar.IsFixed() )
2649 bar.mLenRatio = double(bar.mBounds.width)/double(totalWidth);
2650 }
8e08b761
JS
2651}
2652
2653void cbDockPane::RecalcRowLayout( cbRowInfo* pRow )
2654{
5515f252
GT
2655 cbLayoutRowEvent evt( pRow, this );
2656
2657 mpLayout->FirePluginEvent( evt );
8e08b761
JS
2658}
2659
2660void cbDockPane::ExpandBar( cbBarInfo* pBar )
2661{
5515f252 2662 mpLayout->GetUpdatesManager().OnStartChanges();
8e08b761 2663
5515f252
GT
2664 if ( !pBar->mpRow->mpExpandedBar )
2665 {
2666 // save ratios only when there arent any bars expanded yet
8e08b761 2667
5515f252 2668 cbArrayFloat& ratios = pBar->mpRow->mSavedRatios;
8e08b761 2669
5515f252
GT
2670 ratios.Clear();
2671 ratios.Alloc( pBar->mpRow->mNotFixedBarsCnt );
8e08b761 2672
5515f252 2673 cbBarInfo* pCur = pBar->mpRow->mBars[0];
8e08b761 2674
5515f252
GT
2675 while( pCur )
2676 {
2677 if ( !pCur->IsFixed() )
2678 {
2679 ratios.Add( 0.0 );
2680 ratios[ ratios.GetCount() - 1 ] = pCur->mLenRatio;
2681 }
8e08b761 2682
5515f252
GT
2683 pCur = pCur->mpNext;
2684 }
2685 }
8e08b761 2686
5515f252 2687 cbBarInfo* pCur = pBar->mpRow->mBars[0];
8e08b761 2688
5515f252
GT
2689 while( pCur )
2690 {
2691 pCur->mLenRatio = 0.0; // minimize the rest
8e08b761 2692
5515f252
GT
2693 pCur = pCur->mpNext;
2694 }
8e08b761 2695
5515f252
GT
2696 pBar->mLenRatio = 1.0; // 100%
2697 pBar->mBounds.width = 0;
8e08b761 2698
5515f252 2699 pBar->mpRow->mpExpandedBar = pBar;
8e08b761 2700
5515f252 2701 mpLayout->RecalcLayout( FALSE );
8e08b761 2702
5515f252
GT
2703 mpLayout->GetUpdatesManager().OnFinishChanges();
2704 mpLayout->GetUpdatesManager().UpdateNow();
8e08b761
JS
2705}
2706
2707void cbDockPane::ContractBar( cbBarInfo* pBar )
2708{
5515f252 2709 mpLayout->GetUpdatesManager().OnStartChanges();
8e08b761
JS
2710
2711 // FIXME: What's the purpose of this???
2712 // double ratio = 1.0/ double( pBar->mpRow->mNotFixedBarsCnt );
2713
5515f252 2714 // restore ratios which were present before expansion
8e08b761 2715
5515f252 2716 cbBarInfo* pCur = pBar->mpRow->mBars[0];
8e08b761 2717
5515f252 2718 cbArrayFloat& ratios = pBar->mpRow->mSavedRatios;
8e08b761 2719
5515f252 2720 size_t i = 0;
8e08b761 2721
5515f252
GT
2722 while( pCur )
2723 {
2724 if ( !pCur->IsFixed() )
2725 {
2726 pCur->mLenRatio = ratios[i];
2727 ++i;
2728 }
8e08b761 2729
5515f252
GT
2730 pCur = pCur->mpNext;
2731 }
8e08b761 2732
5515f252
GT
2733 ratios.Clear();
2734 ratios.Shrink();
8e08b761 2735
5515f252 2736 pBar->mpRow->mpExpandedBar = NULL;
8e08b761 2737
5515f252 2738 mpLayout->RecalcLayout( FALSE );
8e08b761 2739
5515f252
GT
2740 mpLayout->GetUpdatesManager().OnFinishChanges();
2741 mpLayout->GetUpdatesManager().UpdateNow();
8e08b761
JS
2742}
2743
2744void cbDockPane::InitLinksForRow( cbRowInfo* pRow )
2745{
5515f252
GT
2746 size_t i;
2747 for ( i = 0; i != pRow->mBars.Count(); ++i )
2748 {
2749 cbBarInfo& bar = *pRow->mBars[i];
8e08b761 2750
5515f252
GT
2751 if ( i == 0 )
2752 bar.mpPrev = NULL;
2753 else
2754 bar.mpPrev = pRow->mBars[i-1];
8e08b761 2755
5515f252
GT
2756 if ( i == pRow->mBars.Count() - 1 )
2757 bar.mpNext = NULL;
2758 else
2759 bar.mpNext = pRow->mBars[i+1];
2760 }
8e08b761
JS
2761}
2762
2763void cbDockPane::InitLinksForRows()
2764{
5515f252
GT
2765 size_t i;
2766 for ( i = 0; i != mRows.Count(); ++i )
2767 {
2768 cbRowInfo& row = *mRows[i];
8e08b761 2769
5515f252
GT
2770 if ( i == 0 )
2771 row.mpPrev = NULL;
2772 else
2773 row.mpPrev = mRows[i-1];
8e08b761 2774
5515f252
GT
2775 if ( i == mRows.Count() - 1 )
2776 row.mpNext = NULL;
2777 else
2778 row.mpNext = mRows[i+1];
2779 }
8e08b761
JS
2780}
2781
2782void cbDockPane::DoInsertBar( cbBarInfo* pBar, int rowNo )
2783{
5515f252 2784 cbRowInfo* pRow = NULL;
8e08b761 2785
5515f252
GT
2786 if ( rowNo == -1 || rowNo >= (int)mRows.Count() )
2787 {
2788 pRow = new cbRowInfo();
8e08b761 2789
5515f252
GT
2790 if ( rowNo == -1 && mRows.Count() )
2791
2792 mRows.Insert( pRow, 0 );
2793 else
2794 mRows.Add( pRow );
8e08b761 2795
5515f252
GT
2796 InitLinksForRows();
2797 }
2798 else
2799 {
2800 pRow = mRows[rowNo];
8e08b761 2801
6e8515a3 2802 if ( mProps.mNonDestructFrictionOn == TRUE )
5515f252
GT
2803 {
2804 // store original shape of the row (before the bar is inserted)
8e08b761 2805
5515f252
GT
2806 mpStoredRow = pRow;
2807
2808 GetRowShapeData( mpStoredRow, &mRowShapeData );
2809 }
2810 }
8e08b761 2811
5515f252 2812 if ( pRow->mBars.Count() )
8e08b761 2813
5515f252 2814 pRow->mpExpandedBar = NULL;
8e08b761 2815
5515f252 2816 cbInsertBarEvent insEvt( pBar, pRow, this );
8e08b761 2817
5515f252 2818 mpLayout->FirePluginEvent( insEvt );
8e08b761 2819
5515f252 2820 mpLayout->GetUpdatesManager().OnRowWillChange( pRow, this );
8e08b761
JS
2821}
2822
2823void cbDockPane::InsertBar( cbBarInfo* pBarInfo, const wxRect& atRect )
2824{
5515f252
GT
2825 wxRect rect = atRect;
2826 FrameToPane( &rect );
8e08b761 2827
5515f252
GT
2828 pBarInfo->mBounds.x = rect.x;
2829 pBarInfo->mBounds.width = rect.width;
2830 pBarInfo->mBounds.height = rect.height;
8e08b761 2831
5515f252 2832 int row = GetRowAt( rect.y, rect.y + rect.height );
8e08b761 2833
5515f252 2834 DoInsertBar( pBarInfo, row );
8e08b761
JS
2835}
2836
2837void cbDockPane::InsertBar( cbBarInfo* pBar, cbRowInfo* pIntoRow )
2838{
5515f252 2839 cbInsertBarEvent insEvt( pBar, pIntoRow, this );
8e08b761 2840
5515f252 2841 mpLayout->FirePluginEvent( insEvt );
8e08b761 2842
5515f252 2843 mpLayout->GetUpdatesManager().OnRowWillChange( pIntoRow, this );
8e08b761
JS
2844}
2845
2846void cbDockPane::InsertBar( cbBarInfo* pBarInfo )
2847{
5515f252 2848 // set transient properties
8e08b761 2849
5515f252
GT
2850 pBarInfo->mpRow = NULL;
2851 pBarInfo->mHasLeftHandle = FALSE;
2852 pBarInfo->mHasRightHandle = FALSE;
2853 pBarInfo->mLenRatio = 0.0;
8e08b761 2854
5515f252
GT
2855 // set preferred bar dimensions, according to the state in which
2856 // the bar is being inserted
8e08b761 2857
5515f252
GT
2858 pBarInfo->mBounds.width = pBarInfo->mDimInfo.mSizes[ pBarInfo->mState ].x;
2859 pBarInfo->mBounds.height = pBarInfo->mDimInfo.mSizes[ pBarInfo->mState ].y;
8e08b761 2860
5515f252 2861 DoInsertBar( pBarInfo, pBarInfo->mRowNo );
8e08b761
JS
2862}
2863
2864void cbDockPane::RemoveRow( cbRowInfo* pRow )
2865{
5515f252
GT
2866 size_t i;
2867 // first, hide all bar-windows in the removed row
2868 for ( i = 0; i != pRow->mBars.Count(); ++i )
2869 {
2870 if ( pRow->mBars[i]->mpBarWnd )
2871 pRow->mBars[i]->mpBarWnd->Show( FALSE );
2872 }
8e08b761 2873
5515f252 2874 mRows.Remove( pRow );
8e08b761 2875
5515f252 2876 pRow->mUMgrData.SetDirty(TRUE);
8e08b761
JS
2877}
2878
2879void cbDockPane::InsertRow( cbRowInfo* pRow, cbRowInfo* pBeforeRow )
2880{
5515f252 2881 if ( !pBeforeRow )
8e08b761 2882
5515f252
GT
2883 mRows.Add( pRow );
2884 else
2885 mRows.Insert( pRow, mRows.Index( pBeforeRow ) );
8e08b761 2886
5515f252 2887 InitLinksForRows();
8e08b761 2888
5515f252 2889 pRow->mUMgrData.SetDirty(TRUE);
8e08b761 2890
5515f252
GT
2891 size_t i;
2892 for ( i = 0; i != pRow->mBars.Count(); ++i )
2893 pRow->mBars[i]->mUMgrData.SetDirty( TRUE );
8e08b761 2894
5515f252 2895 SyncRowFlags( pRow );
8e08b761
JS
2896}
2897
2898void cbDockPane::SetPaneWidth(int width)
2899{
5515f252
GT
2900 if ( IsHorizontal() )
2901 mPaneWidth = width - mLeftMargin - mRightMargin;
2902 else
2903 mPaneWidth = width - mTopMargin - mBottomMargin;
8e08b761
JS
2904}
2905
2906
2907void cbDockPane::SetBoundsInParent( const wxRect& rect )
2908{
5515f252 2909 mBoundsInParent = rect;
8e08b761 2910
5515f252 2911 // set pane dimensions in local coordinates
8e08b761 2912
5515f252
GT
2913 if ( IsHorizontal() )
2914 {
2915 mPaneWidth = mBoundsInParent.width - ( mRightMargin + mLeftMargin );
2916 mPaneHeight = mBoundsInParent.height - ( mTopMargin + mBottomMargin );
2917 }
2918 else
2919 {
2920 mPaneWidth = mBoundsInParent.height - ( mTopMargin + mBottomMargin );
2921 mPaneHeight = mBoundsInParent.width - ( mRightMargin + mLeftMargin );
2922 }
8e08b761 2923
5515f252 2924 // convert bounding rectangles of all pane items into parent frame's coordinates
8e08b761 2925
5515f252 2926 wxBarIterator i( mRows );
8e08b761 2927
5515f252 2928 wxRect noMarginsRect = mBoundsInParent;
8e08b761 2929
5515f252
GT
2930 noMarginsRect.x += mLeftMargin;
2931 noMarginsRect.y += mTopMargin;
2932 noMarginsRect.width -= ( mLeftMargin + mRightMargin );
2933 noMarginsRect.height -= ( mTopMargin + mBottomMargin );
8e08b761 2934
5515f252 2935 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
8e08b761 2936
5515f252
GT
2937 if ( mBoundsInParent.width < 0 ||
2938 mBoundsInParent.height < 0 )
8e08b761 2939
5515f252 2940 hide_rect( mBoundsInParent );
8e08b761 2941
5515f252
GT
2942 if ( noMarginsRect.width < 0 ||
2943 noMarginsRect.height < 0 )
2944
2945 hide_rect( noMarginsRect );
8e08b761 2946
5515f252 2947 // calculate mBoundsInParent for each item in the pane
8e08b761 2948
5515f252
GT
2949 while( i.Next() )
2950 {
2951 cbBarInfo& bar = i.BarInfo();
8e08b761 2952
5515f252 2953 cbRowInfo* pRowInfo = bar.mpRow;
8e08b761 2954
5515f252 2955 // set up row info, if this is first bar in the row
8e08b761 2956
5515f252
GT
2957 if ( pRowInfo && bar.mpPrev == NULL )
2958 {
2959 pRowInfo->mBoundsInParent.y = pRowInfo->mRowY;
2960 pRowInfo->mBoundsInParent.x = 0;
2961 pRowInfo->mBoundsInParent.width = mPaneWidth;
2962 pRowInfo->mBoundsInParent.height = pRowInfo->mRowHeight;
8e08b761 2963
5515f252 2964 PaneToFrame( &pRowInfo->mBoundsInParent );
8e08b761 2965
5515f252
GT
2966 clip_rect_against_rect( pRowInfo->mBoundsInParent, noMarginsRect );
2967 }
8e08b761 2968
5515f252 2969 wxRect bounds = bar.mBounds;
8e08b761 2970
5515f252
GT
2971 // exclude dimensions of handles, when calculating
2972 // bar's bounds in parent (i.e. "visual bounds")
8e08b761 2973
5515f252
GT
2974 if ( bar.mHasLeftHandle )
2975 {
2976 bounds.x += mProps.mResizeHandleSize;
2977 bounds.width -= mProps.mResizeHandleSize;
2978 }
8e08b761 2979
5515f252
GT
2980 if ( bar.mHasRightHandle )
2981
2982 bounds.width -= mProps.mResizeHandleSize;
8e08b761 2983
5515f252 2984 PaneToFrame( &bounds );
8e08b761 2985
5515f252 2986 clip_rect_against_rect( bounds, noMarginsRect );
8e08b761 2987
5515f252
GT
2988 bar.mBoundsInParent = bounds;
2989 }
8e08b761
JS
2990}
2991
2992bool cbDockPane::BarPresent( cbBarInfo* pBar )
2993{
5515f252 2994 wxBarIterator iter( mRows );
8e08b761 2995
5515f252
GT
2996 while( iter.Next() )
2997
2998 if ( &iter.BarInfo() == pBar ) return TRUE;
8e08b761 2999
5515f252 3000 return FALSE;
8e08b761
JS
3001}
3002
3003cbRowInfo* cbDockPane::GetRow( int row )
3004{
5515f252 3005 if ( row >= (int)mRows.Count() ) return NULL;
8e08b761 3006
5515f252 3007 return mRows[ row ];
8e08b761
JS
3008}
3009
3010int cbDockPane::GetRowIndex( cbRowInfo* pRow )
3011{
5515f252
GT
3012 size_t i;
3013 for ( i = 0; i != mRows.Count(); ++i )
3014 {
3015 if ( mRows[i] == pRow )
3016 return i;
3017 }
8e08b761 3018
873a543b 3019 wxFAIL_MSG(wxT("Row must be present to call cbDockPane::GetRowIndex()"));
8e08b761 3020
5515f252 3021 return 0;
8e08b761
JS
3022}
3023
3024int cbDockPane::GetPaneHeight()
3025{
5515f252 3026 // first, recalculate row heights and the Y-positions
8e08b761 3027
5515f252
GT
3028 cbLayoutRowsEvent evt( this );
3029 mpLayout->FirePluginEvent( evt );
8e08b761 3030
5515f252 3031 int height = 0;
8e08b761 3032
5515f252
GT
3033 if ( IsHorizontal() )
3034
3035 height += mTopMargin + mBottomMargin;
3036 else
3037 height += mLeftMargin + mRightMargin;
8e08b761 3038
5515f252 3039 int count = mRows.Count();
8e08b761 3040
5515f252
GT
3041 if ( count )
3042
3043 height += mRows[count-1]->mRowY + mRows[count-1]->mRowHeight;
8e08b761 3044
5515f252 3045 return height;
8e08b761
JS
3046}
3047
3048int cbDockPane::GetAlignment()
3049{
5515f252 3050 return mAlignment;
8e08b761
JS
3051}
3052
3053bool cbDockPane::MatchesMask( int paneMask )
3054{
5515f252 3055 int thisMask = 0;
8e08b761 3056
5515f252 3057 // FIXME:: use array instead of switch()
8e08b761 3058
5515f252
GT
3059 switch (mAlignment)
3060 {
3061 case FL_ALIGN_TOP : thisMask = FL_ALIGN_TOP_PANE; break;
3062 case FL_ALIGN_BOTTOM : thisMask = FL_ALIGN_BOTTOM_PANE;break;
3063 case FL_ALIGN_LEFT : thisMask = FL_ALIGN_LEFT_PANE; break;
3064 case FL_ALIGN_RIGHT : thisMask = FL_ALIGN_RIGHT_PANE; break;
8e08b761 3065
5515f252 3066 default:
873a543b 3067 wxFAIL_MSG(wxT("Bad FL alignment type detected in cbDockPane::MatchesMask()"));
5515f252 3068 }
8e08b761 3069
5515f252 3070 return ( thisMask & paneMask ) != 0;
8e08b761
JS
3071}
3072
3073void cbDockPane::RecalcLayout()
3074{
5515f252 3075 // first, reposition rows and items vertically
8e08b761 3076
5515f252
GT
3077 cbLayoutRowsEvent evt( this );
3078 mpLayout->FirePluginEvent( evt );
8e08b761 3079
5515f252 3080 // then horizontally in each row
8e08b761 3081
5515f252
GT
3082 size_t i;
3083 for ( i = 0; i != mRows.Count(); ++i )
3084 RecalcRowLayout( mRows[i] );
8e08b761
JS
3085}
3086
3087int cbDockPane::GetDockingState()
3088{
5515f252
GT
3089 if ( mAlignment == FL_ALIGN_TOP ||
3090 mAlignment == FL_ALIGN_BOTTOM )
3091 {
3092 return wxCBAR_DOCKED_HORIZONTALLY;
3093 }
3094 else
3095 return wxCBAR_DOCKED_VERTICALLY;
8e08b761
JS
3096}
3097
3098inline bool cbDockPane::HasPoint( const wxPoint& pos, int x, int y,
5515f252 3099 int width, int height )
8e08b761 3100{
5515f252
GT
3101 return ( pos.x >= x &&
3102 pos.y >= y &&
3103 pos.x < x + width &&
3104 pos.y < y + height );
8e08b761
JS
3105}
3106
3107int cbDockPane::HitTestPaneItems( const wxPoint& pos,
5515f252
GT
3108 cbRowInfo** ppRow,
3109 cbBarInfo** ppBar
3110 )
8e08b761 3111{
5515f252
GT
3112 (*ppRow) = NULL;
3113 (*ppBar) = NULL;
8e08b761 3114
5515f252
GT
3115 size_t i;
3116 for ( i = 0; i != mRows.Count(); ++i )
3117 {
3118 cbRowInfo& row = *mRows[i];
8e08b761 3119
5515f252 3120 *ppRow = &row;
8e08b761 3121
5515f252 3122 // hit-test handles of the row, if present
8e08b761 3123
5515f252
GT
3124 if ( row.mHasUpperHandle )
3125 {
3126 if ( HasPoint( pos, 0, row.mRowY,
3127 row.mRowWidth, mProps.mResizeHandleSize ) )
8e08b761 3128
5515f252
GT
3129 return CB_UPPER_ROW_HANDLE_HITTED;
3130 }
3131 else
3132 if ( row.mHasLowerHandle )
3133 {
3134 if ( HasPoint( pos, 0, row.mRowY + row.mRowHeight - mProps.mResizeHandleSize,
3135 row.mRowWidth, mProps.mResizeHandleSize ) )
8e08b761 3136
5515f252
GT
3137 return CB_LOWER_ROW_HANDLE_HITTED;
3138 }
8e08b761 3139
5515f252 3140 // hit-test bar handles and bar content
8e08b761 3141
5515f252
GT
3142 size_t k;
3143 for ( k = 0; k != row.mBars.Count(); ++k )
3144 {
3145 cbBarInfo& bar = *row.mBars[k];
3146 wxRect& bounds = bar.mBounds;
8e08b761 3147
5515f252 3148 *ppBar = &bar;
8e08b761 3149
5515f252
GT
3150 if ( bar.mHasLeftHandle )
3151 {
3152 if ( HasPoint( pos, bounds.x, bounds.y,
3153 mProps.mResizeHandleSize, bounds.height ) )
8e08b761 3154
5515f252
GT
3155 return CB_LEFT_BAR_HANDLE_HITTED;
3156 }
3157 else
3158 if ( bar.mHasRightHandle )
3159 {
3160 if ( HasPoint( pos, bounds.x + bounds.width - mProps.mResizeHandleSize, bounds.y,
3161 mProps.mResizeHandleSize, bounds.height ) )
3162
3163 return CB_RIGHT_BAR_HANDLE_HITTED;
3164 }
8e08b761 3165
5515f252
GT
3166 if ( HasPoint( pos, bounds.x, bounds.y, bounds.width, bounds.height ) )
3167 return CB_BAR_CONTENT_HITTED;
8e08b761 3168
5515f252 3169 } // hit-test next bar
8e08b761 3170
5515f252 3171 } // next row
8e08b761 3172
5515f252 3173 return CB_NO_ITEMS_HITTED;
8e08b761
JS
3174}
3175
3176void cbDockPane::GetBarResizeRange( cbBarInfo* pBar, int* from, int *till,
5515f252 3177 bool forLeftHandle )
8e08b761 3178{
5515f252 3179 cbBarInfo* pGivenBar = pBar;
8e08b761 3180
5515f252 3181 int notFree = 0;
8e08b761 3182
5515f252 3183 // calc unavailable space from the left
8e08b761 3184
5515f252
GT
3185 while( pBar->mpPrev )
3186 {
3187 pBar = pBar->mpPrev;
8e08b761 3188
5515f252
GT
3189 if ( !pBar->IsFixed() ) notFree += mProps.mMinCBarDim.x;
3190 else notFree += pBar->mBounds.width;
3191 }
8e08b761 3192
5515f252 3193 *from = notFree;
8e08b761 3194
5515f252 3195 pBar = pGivenBar;
8e08b761 3196
5515f252 3197 notFree = 0;
8e08b761 3198
5515f252 3199 // calc unavailable space from the right
8e08b761 3200
5515f252
GT
3201 while( pBar->mpNext )
3202 {
3203 pBar = pBar->mpNext;
8e08b761 3204
5515f252 3205 if ( pBar->mBounds.x >= mPaneWidth ) break;
8e08b761 3206
5515f252 3207 // treat not-fixed bars as minimized
8e08b761 3208
5515f252
GT
3209 if ( !pBar->IsFixed() )
3210
3211 notFree += mProps.mMinCBarDim.x;
3212 else
3213 {
3214 if ( pBar->mBounds.x + pBar->mBounds.width >= mPaneWidth )
3215 {
3216 notFree += mPaneWidth - pBar->mBounds.x;
3217 break;
3218 }
3219 else
3220 notFree += pBar->mBounds.width;
3221 }
8e08b761 3222
5515f252 3223 }
8e08b761 3224
5515f252 3225 *till = mPaneWidth - notFree;
8e08b761 3226
5515f252 3227 // do not let resizing totally deform the bar itself
8e08b761 3228
5515f252
GT
3229 if ( forLeftHandle )
3230
3231 (*till) -= mProps.mMinCBarDim.x;
3232 else
3233
3234 (*from) += mProps.mMinCBarDim.x;
8e08b761
JS
3235}
3236
3237int cbDockPane::GetMinimalRowHeight( cbRowInfo* pRow )
3238{
5515f252 3239 int height = mProps.mMinCBarDim.y;
8e08b761 3240
5515f252
GT
3241 size_t i;
3242 for ( i = 0; i != pRow->mBars.Count(); ++i )
3243 {
3244 if ( pRow->mBars[i]->IsFixed() )
3245 height = wxMax( height, pRow->mBars[i]->mBounds.height );
3246 }
8e08b761 3247
5515f252
GT
3248 if ( pRow->mHasUpperHandle )
3249 height += mProps.mResizeHandleSize;
8e08b761 3250
5515f252
GT
3251 if ( pRow->mHasLowerHandle )
3252 height += mProps.mResizeHandleSize;
3253
3254 return height;
8e08b761
JS
3255}
3256
3257void cbDockPane::SetRowHeight( cbRowInfo* pRow, int newHeight )
3258{
5515f252 3259 if ( pRow->mHasUpperHandle )
8e08b761 3260
5515f252 3261 newHeight -= mProps.mResizeHandleSize;
8e08b761 3262
5515f252 3263 if ( pRow->mHasLowerHandle )
8e08b761 3264
5515f252 3265 newHeight -= mProps.mResizeHandleSize;
8e08b761 3266
5515f252
GT
3267 size_t i;
3268 for ( i = 0; i != pRow->mBars.Count(); ++i )
3269 {
3270 if ( !pRow->mBars[i]->IsFixed() )
3271 pRow->mBars[i]->mBounds.height = newHeight;
3272 }
8e08b761
JS
3273}
3274
3275void cbDockPane::GetRowResizeRange( cbRowInfo* pRow, int* from, int* till,
5515f252 3276 bool forUpperHandle )
8e08b761 3277{
5515f252 3278 cbRowInfo* pGivenRow = pRow;
8e08b761 3279
5515f252 3280 // calc unavailable space from above
8e08b761 3281
5515f252 3282 int notFree = 0;
8e08b761 3283
5515f252
GT
3284 while( pRow->mpPrev )
3285 {
3286 pRow = pRow->mpPrev;
8e08b761 3287
5515f252 3288 notFree += GetMinimalRowHeight( pRow );
8e08b761 3289
5515f252 3290 };
8e08b761 3291
5515f252 3292 *from = notFree;
8e08b761 3293
5515f252
GT
3294 // allow accupy the client window space by resizing pane rows
3295 if ( mAlignment == FL_ALIGN_BOTTOM )
8e08b761 3296
5515f252
GT
3297 *from -= mpLayout->GetClientHeight();
3298 else
3299 if ( mAlignment == FL_ALIGN_RIGHT )
8e08b761 3300
5515f252 3301 *from -= mpLayout->GetClientWidth();
8e08b761 3302
5515f252 3303 // calc unavailable space from below
8e08b761 3304
5515f252 3305 pRow = pGivenRow;
8e08b761 3306
5515f252 3307 notFree = 0;
8e08b761 3308
5515f252
GT
3309 while( pRow->mpNext )
3310 {
3311 pRow = pRow->mpNext;
8e08b761 3312
5515f252 3313 notFree += GetMinimalRowHeight( pRow );
8e08b761 3314
5515f252 3315 }
8e08b761 3316
5515f252 3317 *till = mPaneHeight - notFree;
8e08b761 3318
5515f252 3319 // allow adjustinig pane space vs. client window space by resizing pane row heights
8e08b761 3320
5515f252 3321 if ( mAlignment == FL_ALIGN_TOP )
8e08b761 3322
5515f252
GT
3323 *till += mpLayout->GetClientHeight();
3324 else
3325 if ( mAlignment == FL_ALIGN_LEFT )
8e08b761 3326
5515f252 3327 *till += mpLayout->GetClientWidth();
8e08b761 3328
5515f252 3329 // do not let the resizing of the row totally squeeze the row itself
8e08b761 3330
5515f252 3331 cbRowInfo& row = *pGivenRow;
8e08b761 3332
5515f252
GT
3333 if ( forUpperHandle )
3334 {
3335 *till = row.mRowY + row.mRowHeight - GetMinimalRowHeight( pGivenRow );
8e08b761 3336
5515f252 3337 if ( row.mHasUpperHandle )
8e08b761 3338
5515f252
GT
3339 *till -= mProps.mResizeHandleSize;
3340 }
3341 else
3342 {
3343 *from += GetMinimalRowHeight( pGivenRow );
8e08b761 3344
5515f252 3345 if ( row.mHasLowerHandle )
8e08b761 3346
5515f252
GT
3347 *from -= mProps.mResizeHandleSize;
3348 }
8e08b761
JS
3349}
3350
3351void cbDockPane::ResizeRow( cbRowInfo* pRow, int ofs,
5515f252 3352 bool forUpperHandle )
8e08b761 3353{
5515f252 3354 cbResizeRowEvent evt( pRow, ofs, forUpperHandle, this );
8e08b761 3355
5515f252 3356 mpLayout->FirePluginEvent( evt );
8e08b761
JS
3357}
3358
3359void cbDockPane::ResizeBar( cbBarInfo* pBar, int ofs,
5515f252 3360 bool forLeftHandle )
8e08b761 3361{
5515f252 3362 pBar->mpRow->mpExpandedBar = NULL;
8e08b761 3363
5515f252 3364 mpLayout->GetUpdatesManager().OnStartChanges();
8e08b761 3365
5515f252 3366 wxRect& bounds = pBar->mBounds;
8e08b761 3367
5515f252
GT
3368 if ( forLeftHandle )
3369 {
3370 // do not allow bar width become less then minimal
3371 if ( bounds.x + ofs > bounds.x + bounds.width - mProps.mMinCBarDim.x )
3372 {
3373 bounds.width = mProps.mMinCBarDim.x;
3374 bounds.x += ofs;
3375 }
3376 else
3377 {
3378 bounds.x += ofs;
3379 bounds.width -= ofs;
3380 }
3381 }
3382 else
3383 {
3384 // move bar left if necessary
3385 if ( bounds.width + ofs < mProps.mMinCBarDim.x )
3386 {
3387 bounds.x = bounds.x + bounds.width + ofs - mProps.mMinCBarDim.x;
3388 bounds.width = mProps.mMinCBarDim.x;
3389 }
3390 else
3391 // resize right border only
3392 bounds.width += ofs;
3393 }
8e08b761
JS
3394
3395
5515f252 3396 cbRowInfo* pToRow = pBar->mpRow;
8e08b761 3397
5515f252 3398 this->RemoveBar( pBar );
8e08b761 3399
5515f252 3400 InsertBar( pBar, pToRow );
8e08b761 3401
5515f252 3402 mpLayout->RecalcLayout(FALSE);
8e08b761 3403
5515f252
GT
3404 mpLayout->GetUpdatesManager().OnFinishChanges();
3405 mpLayout->GetUpdatesManager().UpdateNow();
8e08b761
JS
3406}
3407
3408
3409/*** row/bar resizing related methods ***/
3410
3411void cbDockPane::DrawVertHandle( wxDC& dc, int x, int y, int height )
3412{
5515f252 3413 int lower = y + height;
8e08b761 3414
5515f252
GT
3415 dc.SetPen( mpLayout->mLightPen );
3416 dc.DrawLine( x,y, x, lower );
8e08b761 3417
5515f252
GT
3418 dc.SetPen( mpLayout->mGrayPen );
3419 int i;
3420 for ( i = 0; i != mProps.mResizeHandleSize-1; ++i )
3421 {
3422 ++x;
3423 dc.DrawLine( x,y, x, lower );
3424 }
8e08b761 3425
5515f252
GT
3426 dc.SetPen( mpLayout->mDarkPen );
3427 ++x;
3428 dc.DrawLine( x,y, x, lower );
8e08b761 3429
5515f252
GT
3430 dc.SetPen( mpLayout->mBlackPen );
3431 ++x;
3432 dc.DrawLine( x,y, x, lower );
8e08b761
JS
3433}
3434
3435void cbDockPane::DrawHorizHandle( wxDC& dc, int x, int y, int width )
3436{
5515f252 3437 int right = x + width;
8e08b761 3438
5515f252
GT
3439 dc.SetPen( mpLayout->mLightPen );
3440 dc.DrawLine( x,y, right, y );
8e08b761 3441
5515f252 3442 dc.SetPen( mpLayout->mGrayPen );
8e08b761 3443
5515f252
GT
3444 int i;
3445 for ( i = 0; i != mProps.mResizeHandleSize-1; ++i )
3446 {
3447 ++y;
3448 dc.DrawLine( x,y, right, y );
3449 }
8e08b761 3450
5515f252
GT
3451 dc.SetPen( mpLayout->mDarkPen );
3452 dc.DrawLine( x,y, right, ++y );
8e08b761 3453
5515f252
GT
3454 dc.SetPen( mpLayout->mBlackPen );
3455 dc.DrawLine( x,y, right, ++y );
8e08b761
JS
3456}
3457
3458cbBarInfo* cbDockPane::GetBarInfoByWindow( wxWindow* pBarWnd )
3459{
5515f252 3460 wxBarIterator i( mRows );
8e08b761 3461
5515f252
GT
3462 while( i.Next() )
3463
3464 if ( i.BarInfo().mpBarWnd == pBarWnd )
8e08b761 3465
5515f252 3466 return &i.BarInfo();
8e08b761 3467
5515f252 3468 return NULL;
8e08b761
JS
3469}
3470
3471void cbDockPane::GetRowShapeData( cbRowInfo* pRow, wxList* pLst )
3472{
5515f252
GT
3473 pLst->DeleteContents( TRUE );
3474 pLst->Clear();
8e08b761 3475
5515f252
GT
3476 size_t i;
3477 for ( i = 0; i != pRow->mBars.Count(); ++i )
3478 {
3479 cbBarInfo& bar = *pRow->mBars[i];
8e08b761 3480
5515f252 3481 cbBarShapeData* pData = new cbBarShapeData();
8e08b761 3482
5515f252 3483 pLst->Append( (wxObject*)pData );
8e08b761 3484
5515f252
GT
3485 pData->mBounds = bar.mBounds;
3486 pData->mLenRatio = bar.mLenRatio;
3487 }
8e08b761
JS
3488}
3489
3490void cbDockPane::SetRowShapeData( cbRowInfo* pRow, wxList* pLst )
3491{
5515f252
GT
3492 if ( pLst->First() == NULL )
3493 return;
8e08b761 3494
5515f252 3495 wxNode* pData = pLst->First();
8e08b761 3496
5515f252
GT
3497 size_t i;
3498 for ( i = 0; i != pRow->mBars.Count(); ++i )
3499 {
3500 wxASSERT( pData ); // DBG::
8e08b761 3501
5515f252 3502 cbBarInfo& bar = *pRow->mBars[i];;
8e08b761 3503
5515f252 3504 cbBarShapeData& data = *((cbBarShapeData*)pData->Data());
8e08b761 3505
5515f252
GT
3506 bar.mBounds = data.mBounds;
3507 bar.mLenRatio = data.mLenRatio;
8e08b761 3508
5515f252
GT
3509 pData = pData->Next();
3510 }
8e08b761
JS
3511}
3512
3513/***** Implementation for class cbUpdatesManagerBase *****/
3514
3515IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase, wxObject )
3516
3517/***** Implementation for class cbPluginBase *****/
3518
3519IMPLEMENT_ABSTRACT_CLASS( cbPluginBase, wxEvtHandler )
3520
3521cbPluginBase::~cbPluginBase()
3522{
5515f252 3523 // nothing
8e08b761
JS
3524}
3525
3526bool cbPluginBase::ProcessEvent(wxEvent& event)
3527{
5515f252 3528 if ( mPaneMask == wxALL_PANES )
8e08b761 3529
5515f252 3530 return wxEvtHandler::ProcessEvent( event );
8e08b761 3531
5515f252 3532 // extract mask info. from received event
8e08b761 3533
5515f252 3534 cbPluginEvent& evt = *( (cbPluginEvent*)&event );
8e08b761 3535
5515f252
GT
3536 if ( evt.mpPane == 0 &&
3537 mPaneMask == wxALL_PANES )
8e08b761 3538
5515f252 3539 return wxEvtHandler::ProcessEvent( event );
8e08b761 3540
5515f252 3541 int mask = 0;
8e08b761 3542
5515f252
GT
3543 switch ( evt.mpPane->mAlignment )
3544 {
3545 case FL_ALIGN_TOP : mask = FL_ALIGN_TOP_PANE; break;
3546 case FL_ALIGN_BOTTOM : mask = FL_ALIGN_BOTTOM_PANE;break;
3547 case FL_ALIGN_LEFT : mask = FL_ALIGN_LEFT_PANE; break;
3548 case FL_ALIGN_RIGHT : mask = FL_ALIGN_RIGHT_PANE; break;
3549 }
8e08b761 3550
5515f252 3551 // if event's pane maks matches the plugin's mask
8e08b761 3552
5515f252 3553 if ( mPaneMask & mask )
8e08b761 3554
5515f252 3555 return wxEvtHandler::ProcessEvent( event );
8e08b761 3556
5515f252 3557 // otherwise pass to the next handler if present
8e08b761 3558
5515f252 3559 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event ) )
8e08b761 3560
5515f252
GT
3561 return TRUE;
3562 else
3563 return FALSE;
8e08b761
JS
3564}
3565