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