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