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