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