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