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