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