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