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