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