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