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