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