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