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