]> git.saurik.com Git - wxWidgets.git/blob - utils/framelayout/src/controlbar.cpp
Corrected link error for missing wxRegTipProvider::GetTip by giving it
[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 ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW), 1, wxSOLID ),
236 mLightPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHILIGHT), 1, wxSOLID ),
237 mGrayPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE), 1, wxSOLID ),
238 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID ),
239 mBorderPen( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE), 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
249 mCheckFocusWhenIdle( FALSE ),
250 mRecalcPending( TRUE ),
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 ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW), 1, wxSOLID ),
268 mLightPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHILIGHT), 1, wxSOLID ),
269 mGrayPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE), 1, wxSOLID ),
270 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID ),
271 mBorderPen( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE), 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( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) );
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( cbRowLayoutPlugin ) );
1567 AddPlugin( CLASSINFO( cbBarDragPlugin ) );
1568 AddPlugin( CLASSINFO( cbPaneDrawPlugin ) );
1569 }
1570
1571 void wxFrameLayout::AddPlugin( wxClassInfo* pPlInfo, int paneMask )
1572 {
1573 if ( FindPlugin ( pPlInfo ) ) return; // same type of plugin cannot be added twice
1574
1575 cbPluginBase* pObj = (cbPluginBase*)pPlInfo->CreateObject();
1576
1577 wxASSERT(pObj); // DBG:: plugin's class should be dynamic
1578
1579 pObj->mPaneMask = paneMask;
1580 pObj->mpLayout = this;
1581
1582 PushPlugin( pObj );
1583 }
1584
1585 void wxFrameLayout::AddPluginBefore( wxClassInfo* pNextPlInfo, wxClassInfo* pPlInfo,
1586 int paneMask )
1587 {
1588 wxASSERT( pNextPlInfo != pPlInfo ); // DBG:: no sence
1589
1590 cbPluginBase* pNextPl = FindPlugin( pNextPlInfo );
1591
1592 if ( !pNextPl )
1593 {
1594 AddPlugin( pPlInfo, paneMask );
1595
1596 return;
1597 }
1598
1599 // remove existing one if present
1600
1601 cbPluginBase* pExistingPl = FindPlugin( pPlInfo );
1602
1603 if ( pExistingPl ) RemovePlugin( pPlInfo );
1604
1605 // create an instance
1606
1607 cbPluginBase* pNewPl = (cbPluginBase*)pPlInfo->CreateObject();
1608
1609 wxASSERT(pNewPl); // DBG:: plugin's class should be dynamic
1610
1611 // insert it to the chain
1612
1613 if ( pNextPl->GetPreviousHandler() )
1614
1615 pNextPl->GetPreviousHandler()->SetNextHandler( pNewPl );
1616 else
1617 mpTopPlugin = pNewPl;
1618
1619 pNewPl->SetNextHandler( pNextPl );
1620
1621 pNewPl->SetPreviousHandler( pNextPl->GetPreviousHandler() );
1622
1623 pNextPl->SetPreviousHandler( pNewPl );
1624
1625 // set it up
1626
1627 pNewPl->mPaneMask = paneMask;
1628 pNewPl->mpLayout = this;
1629
1630 pNewPl->OnInitPlugin();
1631 }
1632
1633 void wxFrameLayout::RemovePlugin( wxClassInfo* pPlInfo )
1634 {
1635 cbPluginBase* pPlugin = FindPlugin( pPlInfo );
1636
1637 if ( !pPlugin ) return; // it's OK to remove not-existing plugin ;-)
1638
1639 if ( pPlugin->GetPreviousHandler() == NULL )
1640
1641 mpTopPlugin = (cbPluginBase*)pPlugin->GetNextHandler();
1642
1643 delete pPlugin;
1644 }
1645
1646 cbPluginBase* wxFrameLayout::FindPlugin( wxClassInfo* pPlInfo )
1647 {
1648 cbPluginBase *pCur = mpTopPlugin;
1649
1650 while( pCur )
1651 {
1652 // NOTE:: it might appear usefull matching plugin
1653 // classes "polymorphically":
1654
1655 if ( pCur->GetClassInfo()->IsKindOf( pPlInfo ) )
1656
1657 return pCur;
1658
1659 pCur = (cbPluginBase*)pCur->GetNextHandler();
1660 }
1661
1662 return NULL;
1663 }
1664
1665 /***** Implementation for class cbUpdateMgrData *****/
1666
1667 IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData, wxObject )
1668
1669 cbUpdateMgrData::cbUpdateMgrData()
1670
1671 : mPrevBounds( -1,-1,0,0 ),
1672 mIsDirty( TRUE ) // inidicate initial change
1673 {}
1674
1675 void cbUpdateMgrData::StoreItemState( const wxRect& boundsInParent )
1676 {
1677 mPrevBounds = boundsInParent;
1678 }
1679
1680 void cbUpdateMgrData::SetDirty( bool isDirty )
1681 {
1682 mIsDirty = isDirty;
1683 }
1684
1685 void cbUpdateMgrData::SetCustomData( wxObject* pCustomData )
1686 {
1687 mpCustomData = pCustomData;
1688 }
1689
1690 /***** Implementation for class cbDockPane *****/
1691
1692 void wxBarIterator::Reset()
1693 {
1694 mpRow = ( mpRows->Count() ) ? (*mpRows)[0] : NULL;
1695 mpBar = NULL;
1696 }
1697
1698 wxBarIterator::wxBarIterator( RowArrayT& rows )
1699
1700 : mpRow ( NULL ),
1701 mpBar ( NULL ),
1702 mpRows( &rows )
1703 {
1704 Reset();
1705 }
1706
1707 bool wxBarIterator::Next()
1708 {
1709 if( mpRow )
1710 {
1711 if( mpBar )
1712 mpBar = mpBar->mpNext;
1713 else
1714 {
1715 if ( mpRow->mBars.GetCount() == 0 )
1716 {
1717 return FALSE;
1718 }
1719
1720 mpBar = mpRow->mBars[0];
1721 }
1722
1723 if ( !mpBar )
1724 {
1725 // skip to the next row
1726
1727 mpRow = mpRow->mpNext;
1728
1729 if ( mpRow )
1730
1731 mpBar = mpRow->mBars[0];
1732 else
1733 return FALSE;
1734 }
1735
1736 return TRUE;
1737 }
1738 else
1739 return FALSE;
1740 }
1741
1742 cbBarInfo& wxBarIterator::BarInfo()
1743 {
1744 return *mpBar;
1745 }
1746
1747 cbRowInfo& wxBarIterator::RowInfo()
1748 {
1749 return *mpRow;
1750 }
1751
1752 /***** Implementation for class cbBarDimHandlerBase *****/
1753
1754 IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase, wxObject )
1755
1756 cbBarDimHandlerBase::cbBarDimHandlerBase()
1757 : mRefCount(0)
1758 {}
1759
1760 void cbBarDimHandlerBase::AddRef()
1761 {
1762 ++mRefCount;
1763 }
1764
1765 void cbBarDimHandlerBase::RemoveRef()
1766 {
1767 if ( --mRefCount <= 0 ) delete this;
1768 }
1769
1770 /***** Implementation for class cbDimInfo *****/
1771
1772 IMPLEMENT_DYNAMIC_CLASS( cbDimInfo, wxObject )
1773
1774 cbDimInfo::cbDimInfo()
1775
1776 : mIsFixed(TRUE),
1777 mpHandler( NULL ),
1778
1779 mHorizGap( 0 ),
1780 mVertGap ( 0 )
1781 {
1782 for( size_t i = 0; i != MAX_BAR_STATES; ++i )
1783 {
1784 mSizes[i].x = 20;
1785 mSizes[i].y = 20;
1786
1787 mBounds[i] = wxRect( -1,-1,-1,-1 );
1788 }
1789 }
1790
1791 cbDimInfo::cbDimInfo( cbBarDimHandlerBase* pDimHandler,
1792 bool isFixed )
1793
1794 : mHorizGap( 0 ),
1795 mVertGap ( 0 ),
1796 mIsFixed ( isFixed ),
1797
1798 mpHandler( pDimHandler )
1799 {
1800 if ( mpHandler )
1801 {
1802 int vtad = *((int*)mpHandler);
1803 mpHandler->AddRef();
1804 }
1805
1806 for( size_t i = 0; i != MAX_BAR_STATES; ++i )
1807 {
1808 mSizes[i].x = -1;
1809 mSizes[i].y = -1;
1810
1811 mBounds[i] = wxRect( -1,-1,-1,-1 );
1812 }
1813 }
1814
1815 cbDimInfo::cbDimInfo( int dh_x, int dh_y,
1816 int dv_x, int dv_y,
1817 int f_x, int f_y,
1818
1819 bool isFixed,
1820 int horizGap,
1821 int vertGap,
1822
1823 cbBarDimHandlerBase* pDimHandler
1824 )
1825 : mHorizGap ( horizGap ),
1826 mVertGap ( vertGap ),
1827 mIsFixed ( isFixed ),
1828 mpHandler( pDimHandler )
1829 {
1830 if ( mpHandler )
1831 {
1832 int vtad = *((int*)mpHandler);
1833 mpHandler->AddRef();
1834 }
1835
1836
1837 mSizes[wxCBAR_DOCKED_HORIZONTALLY].x = dh_x;
1838 mSizes[wxCBAR_DOCKED_HORIZONTALLY].y = dh_y;
1839 mSizes[wxCBAR_DOCKED_VERTICALLY ].x = dv_x;
1840 mSizes[wxCBAR_DOCKED_VERTICALLY ].y = dv_y;
1841 mSizes[wxCBAR_FLOATING ].x = f_x;
1842 mSizes[wxCBAR_FLOATING ].y = f_y;
1843
1844
1845 for( size_t i = 0; i != MAX_BAR_STATES; ++i )
1846
1847 mBounds[i] = wxRect( -1,-1,-1,-1 );
1848 }
1849
1850 cbDimInfo::~cbDimInfo()
1851 {
1852 if ( mpHandler )
1853
1854 mpHandler->RemoveRef();
1855 }
1856
1857 const cbDimInfo& cbDimInfo::operator=( cbDimInfo& other )
1858 {
1859 if ( this == &other ) return *this;
1860
1861 for( int i = 0; i != MAX_BAR_STATES; ++i )
1862
1863 mSizes[i] = other.mSizes[i];
1864
1865 mIsFixed = other.mIsFixed;
1866 mpHandler = other.mpHandler;
1867
1868 mVertGap = other.mVertGap;
1869 mHorizGap = other.mHorizGap;
1870
1871 if ( mpHandler )
1872
1873 mpHandler->AddRef();
1874
1875 return *this;
1876 }
1877
1878 /***** Implementation for structure cbCommonPaneProperties *****/
1879
1880 IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties, wxObject )
1881
1882 cbCommonPaneProperties::cbCommonPaneProperties(void)
1883
1884 : mRealTimeUpdatesOn ( TRUE ),
1885 mOutOfPaneDragOn ( TRUE ),
1886 mExactDockPredictionOn( FALSE ),
1887 mNonDestructFirctionOn( FALSE ),
1888 mShow3DPaneBorderOn ( TRUE ),
1889 mBarFloatingOn ( FALSE ),
1890 mRowProportionsOn ( FALSE ),
1891 mColProportionsOn ( TRUE ),
1892 mBarCollapseIconsOn ( FALSE ),
1893 mBarDragHintsOn ( FALSE ),
1894
1895 mMinCBarDim( 16, 16 ),
1896 mResizeHandleSize( 4 )
1897 {}
1898
1899 /***** Implementation for class cbRowInfo *****/
1900
1901 IMPLEMENT_DYNAMIC_CLASS( cbRowInfo, wxObject )
1902
1903 cbRowInfo::cbRowInfo(void)
1904
1905 : mpNext ( NULL ),
1906 mpPrev ( NULL ),
1907 mNotFixedBarsCnt( FALSE ),
1908 mpExpandedBar ( NULL )
1909 {}
1910
1911 cbRowInfo::~cbRowInfo()
1912 {
1913 // nothing! all bars are removed using global bar
1914 // list in wxFrameLayout class
1915 }
1916
1917 /***** Implementation for class cbBarInfo *****/
1918
1919 IMPLEMENT_DYNAMIC_CLASS( cbBarInfo, wxObject )
1920
1921 cbBarInfo::cbBarInfo(void)
1922
1923 : mpRow( NULL ),
1924
1925 mpNext( NULL ),
1926 mpPrev( NULL )
1927 {}
1928
1929 cbBarInfo::~cbBarInfo()
1930 {
1931 // nothing
1932 }
1933
1934 /***** Implementation for class cbDockPane *****/
1935
1936 IMPLEMENT_DYNAMIC_CLASS( cbDockPane, wxObject )
1937
1938 // FIXME:: how to eliminate these cut&pasted constructors?
1939
1940 cbDockPane::cbDockPane(void)
1941
1942 : mpLayout ( 0 ),
1943 mPaneWidth ( 32768 ), // fake-up very large pane dims,
1944 // since the real dimensions of the pane may not
1945 // be known, while inserting bars initially
1946 mPaneHeight( 32768 ),
1947 mAlignment ( -1 ),
1948 mpStoredRow( NULL ),
1949 mLeftMargin ( 1 ),
1950 mRightMargin ( 1 ),
1951 mTopMargin ( 1 ),
1952 mBottomMargin( 1 )
1953 {}
1954
1955 cbDockPane::cbDockPane( int alignment, wxFrameLayout* pPanel )
1956
1957 : mpLayout ( pPanel ),
1958 mPaneWidth ( 32768 ), // fake-up very large pane dims,
1959 // since the real dimensions of the pane may not
1960 // be known, while inserting bars initially
1961 mPaneHeight( 32768 ),
1962 mAlignment ( alignment ),
1963 mpStoredRow( NULL ),
1964
1965 mLeftMargin ( 1 ),
1966 mRightMargin ( 1 ),
1967 mTopMargin ( 1 ),
1968 mBottomMargin( 1 )
1969 {}
1970
1971 cbDockPane::~cbDockPane()
1972 {
1973 for( size_t i = 0; i != mRows.Count(); ++i )
1974
1975 delete mRows[i];
1976
1977 mRowShapeData.DeleteContents( TRUE );
1978
1979 // NOTE:: control bar infromation structures are cleaned-up
1980 // in wxFrameLayout's destructor, using global control-bar list
1981 }
1982
1983 void cbDockPane::SetMargins( int top, int bottom, int left, int right )
1984 {
1985 mTopMargin = top;
1986 mBottomMargin = bottom;
1987 mLeftMargin = left;
1988 mRightMargin = right;
1989 }
1990
1991 /*** helpers of cbDockPane ***/
1992
1993 void cbDockPane::PaintBarDecorations( cbBarInfo* pBar, wxDC& dc )
1994 {
1995 cbDrawBarDecorEvent evt( pBar, dc, this );
1996
1997 mpLayout->FirePluginEvent( evt );
1998 }
1999
2000 void cbDockPane::PaintBarHandles( cbBarInfo* pBar, wxDC& dc )
2001 {
2002 cbDrawBarHandlesEvent evt( pBar, dc, this );
2003
2004 mpLayout->FirePluginEvent( evt );
2005 }
2006
2007 void cbDockPane::PaintBar( cbBarInfo* pBar, wxDC& dc )
2008 {
2009 PaintBarDecorations( pBar, dc );
2010 PaintBarHandles( pBar, dc );
2011 }
2012
2013 void cbDockPane::PaintRowHandles( cbRowInfo* pRow, wxDC& dc )
2014 {
2015 cbDrawRowHandlesEvent evt( pRow, dc, this );
2016
2017 mpLayout->FirePluginEvent( evt );
2018
2019 cbDrawRowDecorEvent evt1( pRow, dc, this );
2020
2021 mpLayout->FirePluginEvent( evt1 );
2022 }
2023
2024 void cbDockPane::PaintRowBackground ( cbRowInfo* pRow, wxDC& dc )
2025 {
2026 cbDrawRowBkGroundEvent evt( pRow, dc, this );
2027
2028 mpLayout->FirePluginEvent( evt );
2029 }
2030
2031 void cbDockPane::PaintRowDecorations( cbRowInfo* pRow, wxDC& dc )
2032 {
2033 size_t i = 0;
2034
2035 // decorations first
2036 for( i = 0; i != pRow->mBars.Count(); ++i )
2037
2038 PaintBarDecorations( pRow->mBars[i], dc );
2039
2040 // then handles if present
2041 for( i = 0; i != pRow->mBars.Count(); ++i )
2042
2043 PaintBarHandles( pRow->mBars[i], dc );
2044 }
2045
2046 void cbDockPane::PaintRow( cbRowInfo* pRow, wxDC& dc )
2047 {
2048 PaintRowBackground ( pRow, dc );
2049 PaintRowDecorations( pRow, dc );
2050 PaintRowHandles ( pRow, dc );
2051 }
2052
2053 void cbDockPane::PaintPaneBackground( wxDC& dc )
2054 {
2055 cbDrawPaneBkGroundEvent evt( dc, this );
2056
2057 mpLayout->FirePluginEvent( evt );
2058 }
2059
2060 void cbDockPane::PaintPaneDecorations( wxDC& dc )
2061 {
2062 cbDrawPaneDecorEvent evt( dc, this );
2063
2064 mpLayout->FirePluginEvent( evt );
2065 }
2066
2067 void cbDockPane::PaintPane( wxDC& dc )
2068 {
2069 PaintPaneBackground( dc );
2070
2071 size_t i = 0;
2072
2073 // first decorations
2074 for( i = 0; i != mRows.Count(); ++i )
2075 {
2076 PaintRowBackground( mRows[i], dc );
2077 PaintRowDecorations( mRows[i], dc );
2078 }
2079
2080 // than handles
2081 for( i = 0; i != mRows.Count(); ++i )
2082
2083 PaintRowHandles( mRows[i], dc );
2084
2085 // and finally
2086 PaintPaneDecorations( dc );
2087 }
2088
2089 void cbDockPane::SizeBar( cbBarInfo* pBar )
2090 {
2091 cbSizeBarWndEvent evt( pBar, this );
2092
2093 mpLayout->FirePluginEvent( evt );
2094 return;
2095 }
2096
2097 void cbDockPane::SizeRowObjects( cbRowInfo* pRow )
2098 {
2099 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
2100
2101 SizeBar( pRow->mBars[i] );
2102 }
2103
2104 void cbDockPane::SizePaneObjects()
2105 {
2106 for( size_t i = 0; i != mRows.Count(); ++i )
2107
2108 SizeRowObjects( mRows[i] );
2109 }
2110
2111 wxDC* cbDockPane::StartDrawInArea( const wxRect& area )
2112 {
2113 wxDC* pDc = 0;
2114
2115 cbStartDrawInAreaEvent evt( area, &pDc, this );
2116
2117 mpLayout->FirePluginEvent( evt );
2118
2119 return pDc;
2120 }
2121
2122 void cbDockPane::FinishDrawInArea( const wxRect& area )
2123 {
2124 cbFinishDrawInAreaEvent evt( area, this );
2125
2126 mpLayout->FirePluginEvent( evt );
2127 }
2128
2129 bool cbDockPane::IsFixedSize( cbBarInfo* pInfo )
2130 {
2131 return ( pInfo->mDimInfo.mIsFixed );
2132 }
2133
2134 int cbDockPane::GetNotFixedBarsCount( cbRowInfo* pRow )
2135 {
2136 int cnt = 0;
2137
2138 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
2139
2140 if ( !pRow->mBars[i]->IsFixed() ) ++cnt;
2141
2142 return cnt;
2143 }
2144
2145 void cbDockPane::RemoveBar( cbBarInfo* pBar )
2146 {
2147 bool needsRestoring = mProps.mNonDestructFirctionOn &&
2148 mpStoredRow == pBar->mpRow;
2149
2150 cbRemoveBarEvent evt( pBar, this );
2151
2152 mpLayout->FirePluginEvent( evt );
2153
2154 if ( needsRestoring )
2155 {
2156 SetRowShapeData( mpStoredRow, &mRowShapeData );
2157
2158 mpStoredRow = NULL;
2159 }
2160 }
2161
2162 void cbDockPane::SyncRowFlags( cbRowInfo* pRow )
2163 {
2164 // setup mHasOnlyFixedBars flag for the row information
2165 pRow->mHasOnlyFixedBars = TRUE;
2166
2167 pRow->mNotFixedBarsCnt = 0;
2168
2169 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
2170 {
2171 cbBarInfo& bar = *pRow->mBars[i];
2172
2173 bar.mpRow = pRow;
2174
2175 if ( !bar.IsFixed() )
2176 {
2177 pRow->mHasOnlyFixedBars = FALSE;
2178 ++pRow->mNotFixedBarsCnt;
2179 }
2180 }
2181 }
2182
2183 void cbDockPane::FrameToPane( long* x, long* y )
2184 {
2185 *x -= mLeftMargin;
2186 *y -= mTopMargin;
2187
2188 if ( mAlignment == wxTOP ||
2189 mAlignment == wxBOTTOM
2190 )
2191 {
2192 *x -= mBoundsInParent.x;
2193 *y -= mBoundsInParent.y;
2194 }
2195 else
2196 {
2197 int rx = *x, ry = *y;
2198
2199 *x = ry - mBoundsInParent.y;
2200
2201 *y = rx - mBoundsInParent.x;
2202 }
2203 }
2204
2205 void cbDockPane::PaneToFrame( long* x, long* y )
2206 {
2207 if ( mAlignment == wxTOP ||
2208 mAlignment == wxBOTTOM
2209 )
2210 {
2211 *x += mBoundsInParent.x;
2212 *y += mBoundsInParent.y;
2213 }
2214 else
2215 {
2216 int rx = *x, ry = *y;
2217
2218 *x = ry + mBoundsInParent.x;
2219
2220 *y = mBoundsInParent.y + rx;
2221 }
2222
2223 *x += mLeftMargin;
2224 *y += mTopMargin;
2225 }
2226
2227 void cbDockPane::FrameToPane( wxRect* pRect )
2228 {
2229 wxPoint upperLeft ( pRect->x, pRect->y );
2230 wxPoint lowerRight( pRect->x + pRect->width,
2231 pRect->y + pRect->height );
2232
2233 FrameToPane( &upperLeft.x, &upperLeft.y );
2234 FrameToPane( &lowerRight.x, &lowerRight.y );
2235
2236 pRect->x = wxMin(upperLeft.x,lowerRight.x);
2237 pRect->y = wxMin(upperLeft.y,lowerRight.y);
2238
2239 pRect->width = abs( lowerRight.x - upperLeft.x );
2240 pRect->height = abs( lowerRight.y - upperLeft.y );
2241 }
2242
2243 void cbDockPane::PaneToFrame( wxRect* pRect )
2244 {
2245 wxPoint upperLeft ( pRect->x, pRect->y );
2246 wxPoint lowerRight( pRect->x + pRect->width,
2247 pRect->y + pRect->height );
2248
2249 PaneToFrame( &upperLeft.x, &upperLeft.y );
2250 PaneToFrame( &lowerRight.x, &lowerRight.y );
2251
2252 //wxRect newRect = wxRect( upperLeft, lowerRight );
2253
2254 pRect->x = wxMin(upperLeft.x,lowerRight.x);
2255 pRect->y = wxMin(upperLeft.y,lowerRight.y);
2256
2257 pRect->width = abs( lowerRight.x - upperLeft.x );
2258 pRect->height = abs( lowerRight.y - upperLeft.y );
2259 }
2260
2261 int cbDockPane::GetRowAt( int paneY )
2262 {
2263 if ( paneY < 0 ) return -1;
2264
2265 int curY = 0;
2266
2267 size_t i = 0;
2268
2269 for( ; i != mRows.Count(); ++i )
2270 {
2271 int rowHeight = mRows[i]->mRowHeight;
2272
2273 int third = rowHeight/3;
2274
2275 if ( paneY >= curY && paneY < curY + third )
2276 return i-1;
2277
2278 if ( paneY >= curY + third && paneY < curY + rowHeight - third )
2279 return i;
2280
2281 curY += rowHeight;
2282 }
2283
2284 return i;
2285 }
2286
2287 int cbDockPane::GetRowAt( int upperY, int lowerY )
2288 {
2289 /*
2290 // OLD STUFF::
2291 int range = lowerY - upperY;
2292 int oneThird = range / 3;
2293
2294 wxNode* pRow = mRows.First();
2295 int row = 0;
2296 int curY = 0;
2297
2298 if ( lowerY <= 0 ) return -1;
2299
2300 while( pRow )
2301 {
2302 int rowHeight = GetRowHeight( (wxList*)pRow->Data() );
2303
2304 if ( upperY >= curY &&
2305 lowerY < curY ) return row;
2306
2307 if ( upperY <= curY &&
2308 lowerY >= curY &&
2309 curY - upperY >= oneThird ) return row-1;
2310
2311 if ( ( upperY < curY + rowHeight &&
2312 lowerY >= curY + rowHeight &&
2313 curY + rowHeight - lowerY >= oneThird )
2314 )
2315 return row+1;
2316
2317 if ( lowerY <= curY + rowHeight ) return row;
2318
2319 ++row;
2320 curY += rowHeight;
2321 pRow = pRow->Next();
2322 }
2323 */
2324
2325 int mid = upperY + (lowerY - upperY)/2;
2326
2327 if ( mid < 0 ) return -1;
2328
2329 int curY = 0;
2330 size_t i = 0;
2331
2332 for( ; i != mRows.Count(); ++i )
2333 {
2334 int rowHeight = mRows[i]->mRowHeight;
2335
2336 if ( mid >= curY && mid < curY + rowHeight ) return i;
2337
2338 curY += rowHeight;
2339 }
2340
2341 return i;
2342 }
2343
2344 int cbDockPane::GetRowY( cbRowInfo* pRow )
2345 {
2346 int curY = 0;
2347
2348 for( size_t i = 0; i != mRows.Count(); ++i )
2349 {
2350 if ( mRows[i] == pRow ) break;
2351
2352 curY += mRows[i]->mRowHeight;
2353 }
2354
2355 return curY;
2356 }
2357
2358 bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo* pRow )
2359 {
2360 while ( pRow->mpPrev )
2361 {
2362 pRow = pRow->mpPrev;
2363
2364 if ( pRow->mHasOnlyFixedBars )
2365
2366 return TRUE;
2367 }
2368
2369 return FALSE;
2370 }
2371
2372 bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo* pRow )
2373 {
2374 while( pRow->mpNext )
2375 {
2376 pRow = pRow->mpNext;
2377
2378 if ( pRow->mHasOnlyFixedBars )
2379
2380 return TRUE;
2381 }
2382
2383 return FALSE;
2384 }
2385
2386 bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo* pBar )
2387 {
2388 while( pBar->mpPrev )
2389 {
2390 pBar = pBar->mpPrev;
2391
2392 if ( pBar->IsFixed() )
2393
2394 return TRUE;
2395 }
2396
2397 return FALSE;
2398 }
2399
2400 bool cbDockPane::HasNotFixedBarsRight( cbBarInfo* pBar )
2401 {
2402 while( pBar->mpNext )
2403 {
2404 pBar = pBar->mpNext;
2405
2406 if ( pBar->IsFixed() )
2407
2408 return TRUE;
2409 }
2410
2411 return FALSE;
2412 }
2413
2414 void cbDockPane::CalcLenghtRatios( cbRowInfo* pInRow )
2415 {
2416 int totalWidth = 0;
2417
2418 size_t i = 0;
2419
2420 // clac current-maximal-total-length of all maximized bars
2421
2422 for( i = 0; i != pInRow->mBars.GetCount(); ++i )
2423 {
2424 cbBarInfo& bar = *pInRow->mBars[i];
2425
2426 if ( !bar.IsFixed() )
2427
2428 totalWidth += bar.mBounds.width;
2429 }
2430
2431 // set up persentages of occupied space for each maximized bar
2432
2433 for( i = 0; i != pInRow->mBars.Count(); ++i )
2434 {
2435 cbBarInfo& bar = *pInRow->mBars[i];
2436
2437 if ( !bar.IsFixed() )
2438
2439 bar.mLenRatio = double(bar.mBounds.width)/double(totalWidth);
2440 }
2441 }
2442
2443 void cbDockPane::RecalcRowLayout( cbRowInfo* pRow )
2444 {
2445 cbLayoutRowEvent evt( pRow, this );
2446
2447 mpLayout->FirePluginEvent( evt );
2448 }
2449
2450 void cbDockPane::ExpandBar( cbBarInfo* pBar )
2451 {
2452 mpLayout->GetUpdatesManager().OnStartChanges();
2453
2454 if ( !pBar->mpRow->mpExpandedBar )
2455 {
2456 // save ratios only when there arent any bars expanded yet
2457
2458 cbArrayFloat& ratios = pBar->mpRow->mSavedRatios;
2459
2460 ratios.Clear();
2461 ratios.Alloc( pBar->mpRow->mNotFixedBarsCnt );
2462
2463 cbBarInfo* pCur = pBar->mpRow->mBars[0];
2464
2465 while( pCur )
2466 {
2467 if ( !pCur->IsFixed() )
2468 {
2469 ratios.Add( 0.0 );
2470 ratios[ ratios.GetCount() - 1 ] = pCur->mLenRatio;
2471 }
2472
2473 pCur = pCur->mpNext;
2474 }
2475 }
2476
2477 cbBarInfo* pCur = pBar->mpRow->mBars[0];
2478
2479 while( pCur )
2480 {
2481 pCur->mLenRatio = 0.0; // minimize the rest
2482
2483 pCur = pCur->mpNext;
2484 }
2485
2486 pBar->mLenRatio = 1.0; // 100%
2487 pBar->mBounds.width = 0;
2488
2489 pBar->mpRow->mpExpandedBar = pBar;
2490
2491 mpLayout->RecalcLayout( FALSE );
2492
2493 mpLayout->GetUpdatesManager().OnFinishChanges();
2494 mpLayout->GetUpdatesManager().UpdateNow();
2495 }
2496
2497 void cbDockPane::ContractBar( cbBarInfo* pBar )
2498 {
2499 mpLayout->GetUpdatesManager().OnStartChanges();
2500
2501 double ratio = 1.0/ double( pBar->mpRow->mNotFixedBarsCnt );
2502
2503 // restore ratios which were present before expansion
2504
2505 cbBarInfo* pCur = pBar->mpRow->mBars[0];
2506
2507 cbArrayFloat& ratios = pBar->mpRow->mSavedRatios;
2508
2509 size_t i = 0;
2510
2511 while( pCur )
2512 {
2513 if ( !pCur->IsFixed() )
2514 {
2515 pCur->mLenRatio = ratios[i];
2516 ++i;
2517 }
2518
2519 pCur = pCur->mpNext;
2520 }
2521
2522 ratios.Clear();
2523 ratios.Shrink();
2524
2525 pBar->mpRow->mpExpandedBar = NULL;
2526
2527 mpLayout->RecalcLayout( FALSE );
2528
2529 mpLayout->GetUpdatesManager().OnFinishChanges();
2530 mpLayout->GetUpdatesManager().UpdateNow();
2531 }
2532
2533 void cbDockPane::InitLinksForRow( cbRowInfo* pRow )
2534 {
2535 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
2536 {
2537 cbBarInfo& bar = *pRow->mBars[i];
2538
2539 if ( i == 0 )
2540
2541 bar.mpPrev = NULL;
2542 else
2543 bar.mpPrev = pRow->mBars[i-1];
2544
2545 if ( i == pRow->mBars.Count() - 1 )
2546
2547 bar.mpNext = NULL;
2548 else
2549 bar.mpNext = pRow->mBars[i+1];
2550 }
2551 }
2552
2553 void cbDockPane::InitLinksForRows()
2554 {
2555 for( size_t i = 0; i != mRows.Count(); ++i )
2556 {
2557 cbRowInfo& row = *mRows[i];
2558
2559 if ( i == 0 )
2560
2561 row.mpPrev = NULL;
2562 else
2563 row.mpPrev = mRows[i-1];
2564
2565 if ( i == mRows.Count() - 1 )
2566
2567 row.mpNext = NULL;
2568 else
2569 row.mpNext = mRows[i+1];
2570 }
2571 }
2572
2573 void cbDockPane::DoInsertBar( cbBarInfo* pBar, int rowNo )
2574 {
2575 cbRowInfo* pRow = NULL;
2576
2577 if ( rowNo == -1 || rowNo >= (int)mRows.Count() )
2578 {
2579 pRow = new cbRowInfo();
2580
2581 if ( rowNo == -1 && mRows.Count() )
2582
2583 mRows.Insert( pRow, 0 );
2584 else
2585 mRows.Add( pRow );
2586
2587 InitLinksForRows();
2588 }
2589 else
2590 {
2591 pRow = mRows[rowNo];
2592
2593 if ( mProps.mNonDestructFirctionOn == TRUE )
2594 {
2595 // store original shape of the row (before the bar is inserted)
2596
2597 mpStoredRow = pRow;
2598
2599 GetRowShapeData( mpStoredRow, &mRowShapeData );
2600 }
2601 }
2602
2603 if ( pRow->mBars.Count() )
2604
2605 pRow->mpExpandedBar = NULL;
2606
2607 cbInsertBarEvent insEvt( pBar, pRow, this );
2608
2609 mpLayout->FirePluginEvent( insEvt );
2610
2611 mpLayout->GetUpdatesManager().OnRowWillChange( pRow, this );
2612 }
2613
2614 void cbDockPane::InsertBar( cbBarInfo* pBarInfo, const wxRect& atRect )
2615 {
2616 wxRect rect = atRect;
2617 FrameToPane( &rect );
2618
2619 pBarInfo->mBounds.x = rect.x;
2620 pBarInfo->mBounds.width = rect.width;
2621 pBarInfo->mBounds.height = rect.height;
2622
2623 int row = GetRowAt( rect.y, rect.y + rect.height );
2624
2625 DoInsertBar( pBarInfo, row );
2626 }
2627
2628 void cbDockPane::InsertBar( cbBarInfo* pBar, cbRowInfo* pIntoRow )
2629 {
2630 cbInsertBarEvent insEvt( pBar, pIntoRow, this );
2631
2632 mpLayout->FirePluginEvent( insEvt );
2633
2634 mpLayout->GetUpdatesManager().OnRowWillChange( pIntoRow, this );
2635 }
2636
2637 void cbDockPane::InsertBar( cbBarInfo* pBarInfo )
2638 {
2639 // set transient properties
2640
2641 pBarInfo->mpRow = NULL;
2642 pBarInfo->mHasLeftHandle = FALSE;
2643 pBarInfo->mHasRightHandle = FALSE;
2644 pBarInfo->mLenRatio = 0.0;
2645
2646 // set preferred bar demensions, according to the state in which
2647 // the bar is being inserted
2648
2649 pBarInfo->mBounds.width = pBarInfo->mDimInfo.mSizes[ pBarInfo->mState ].x;
2650 pBarInfo->mBounds.height = pBarInfo->mDimInfo.mSizes[ pBarInfo->mState ].y;
2651
2652 DoInsertBar( pBarInfo, pBarInfo->mRowNo );
2653 }
2654
2655 void cbDockPane::RemoveRow( cbRowInfo* pRow )
2656 {
2657 // first, hide all bar-windows in the removed row
2658 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
2659
2660 if ( pRow->mBars[i]->mpBarWnd )
2661
2662 pRow->mBars[i]->mpBarWnd->Show( FALSE );
2663
2664 mRows.Remove( pRow );
2665
2666 pRow->mUMgrData.SetDirty(TRUE);
2667 }
2668
2669 void cbDockPane::InsertRow( cbRowInfo* pRow, cbRowInfo* pBeforeRow )
2670 {
2671 if ( !pBeforeRow )
2672
2673 mRows.Add( pRow );
2674 else
2675 mRows.Insert( pRow, mRows.Index( pBeforeRow ) );
2676
2677 InitLinksForRows();
2678
2679 pRow->mUMgrData.SetDirty(TRUE);
2680
2681 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
2682
2683 pRow->mBars[i]->mUMgrData.SetDirty( TRUE );
2684
2685 SyncRowFlags( pRow );
2686 }
2687
2688 void cbDockPane::SetPaneWidth(int width)
2689 {
2690 if ( IsHorizontal() )
2691
2692 mPaneWidth = width - mLeftMargin - mRightMargin;
2693 else
2694 mPaneWidth = width - mTopMargin - mBottomMargin;
2695 }
2696
2697
2698 void cbDockPane::SetBoundsInParent( const wxRect& rect )
2699 {
2700
2701 mBoundsInParent = rect;
2702
2703 // set pane dimensions in local coordinates
2704
2705 if ( IsHorizontal() )
2706 {
2707 mPaneWidth = mBoundsInParent.width - ( mRightMargin + mLeftMargin );
2708 mPaneHeight = mBoundsInParent.height - ( mTopMargin + mBottomMargin );
2709 }
2710 else
2711 {
2712 mPaneWidth = mBoundsInParent.height - ( mTopMargin + mBottomMargin );
2713 mPaneHeight = mBoundsInParent.width - ( mRightMargin + mLeftMargin );
2714 }
2715
2716 // convert bounding rectangles of all pane items into parent frame's coordinates
2717
2718 wxBarIterator i( mRows );
2719
2720 wxRect noMarginsRect = mBoundsInParent;
2721
2722 noMarginsRect.x += mLeftMargin;
2723 noMarginsRect.y += mTopMargin;
2724 noMarginsRect.width -= ( mLeftMargin + mRightMargin );
2725 noMarginsRect.height -= ( mTopMargin + mBottomMargin );
2726
2727 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2728
2729 if ( mBoundsInParent.width < 0 ||
2730 mBoundsInParent.height < 0 )
2731
2732 hide_rect( mBoundsInParent );
2733
2734 if ( noMarginsRect.width < 0 ||
2735 noMarginsRect.height < 0 )
2736
2737 hide_rect( noMarginsRect );
2738
2739 // calculate mBoundsInParent for each item in the pane
2740
2741 while( i.Next() )
2742 {
2743 cbBarInfo& bar = i.BarInfo();
2744
2745 cbRowInfo* pRowInfo = bar.mpRow;
2746
2747 // set up row info, if this is first bar in the row
2748
2749 if ( pRowInfo && bar.mpPrev == NULL )
2750 {
2751 pRowInfo->mBoundsInParent.y = pRowInfo->mRowY;
2752 pRowInfo->mBoundsInParent.x = 0;
2753 pRowInfo->mBoundsInParent.width = mPaneWidth;
2754 pRowInfo->mBoundsInParent.height = pRowInfo->mRowHeight;
2755
2756 PaneToFrame( &pRowInfo->mBoundsInParent );
2757
2758 clip_rect_against_rect( pRowInfo->mBoundsInParent, noMarginsRect );
2759 }
2760
2761 wxRect bounds = bar.mBounds;
2762
2763 // exclude dimensions of handles, when calculating
2764 // bar's bounds in parent (i.e. "visual bounds")
2765
2766 if ( bar.mHasLeftHandle )
2767 {
2768 bounds.x += mProps.mResizeHandleSize;
2769 bounds.width -= mProps.mResizeHandleSize;
2770 }
2771
2772 if ( bar.mHasRightHandle )
2773
2774 bounds.width -= mProps.mResizeHandleSize;
2775
2776 PaneToFrame( &bounds );
2777
2778 clip_rect_against_rect( bounds, noMarginsRect );
2779
2780 bar.mBoundsInParent = bounds;
2781 }
2782 }
2783
2784 bool cbDockPane::BarPresent( cbBarInfo* pBar )
2785 {
2786 wxBarIterator iter( mRows );
2787
2788 while( iter.Next() )
2789
2790 if ( &iter.BarInfo() == pBar ) return TRUE;
2791
2792 return FALSE;
2793 }
2794
2795 cbRowInfo* cbDockPane::GetRow( int row )
2796 {
2797 if ( row >= (int)mRows.Count() ) return NULL;
2798
2799 return mRows[ row ];
2800 }
2801
2802 int cbDockPane::GetRowIndex( cbRowInfo* pRow )
2803 {
2804 for( size_t i = 0; i != mRows.Count(); ++i )
2805
2806 if ( mRows[i] == pRow ) return i;
2807
2808 wxASSERT(0); // DBG:: row should be present
2809
2810 return 0;
2811 }
2812
2813 int cbDockPane::GetPaneHeight()
2814 {
2815 // first, recalculate row heights and the Y-positions
2816
2817 cbLayoutRowsEvent evt( this );
2818 mpLayout->FirePluginEvent( evt );
2819
2820 int height = 0;
2821
2822 if ( IsHorizontal() )
2823
2824 height += mTopMargin + mBottomMargin;
2825 else
2826 height += mLeftMargin + mRightMargin;
2827
2828 int count = mRows.Count();
2829
2830 if ( count )
2831
2832 height += mRows[count-1]->mRowY + mRows[count-1]->mRowHeight;
2833
2834 return height;
2835 }
2836
2837 int cbDockPane::GetAlignment()
2838 {
2839 return mAlignment;
2840 }
2841
2842 bool cbDockPane::MatchesMask( int paneMask )
2843 {
2844 int thisMask = 0;
2845
2846 // FIXME:: use array instead of switch()
2847
2848 switch (mAlignment)
2849 {
2850 case wxTOP : thisMask = wxTOP_PANE; break;
2851 case wxBOTTOM : thisMask = wxBOTTOM_PANE;break;
2852 case wxLEFT : thisMask = wxLEFT_PANE; break;
2853 case wxRIGHT : thisMask = wxRIGHT_PANE; break;
2854
2855 default: wxASSERT(0); // DBG:: bogous alignment type
2856 }
2857
2858 return ( thisMask & paneMask );
2859 }
2860
2861 void cbDockPane::RecalcLayout()
2862 {
2863 // first, reposition rows and items vertically
2864
2865 cbLayoutRowsEvent evt( this );
2866 mpLayout->FirePluginEvent( evt );
2867
2868 // then horizontally in each row
2869
2870 for( size_t i = 0; i != mRows.Count(); ++i )
2871
2872 RecalcRowLayout( mRows[i] );
2873 }
2874
2875 int cbDockPane::GetDockingState()
2876 {
2877 if ( mAlignment == wxTOP ||
2878 mAlignment == wxBOTTOM )
2879 {
2880 return wxCBAR_DOCKED_HORIZONTALLY;
2881 }
2882 else
2883 return wxCBAR_DOCKED_VERTICALLY;
2884 }
2885
2886 inline bool cbDockPane::HasPoint( const wxPoint& pos, int x, int y,
2887 int width, int height )
2888 {
2889 return ( pos.x >= x &&
2890 pos.y >= y &&
2891 pos.x < x + width &&
2892 pos.y < y + height );
2893 }
2894
2895 int cbDockPane::HitTestPaneItems( const wxPoint& pos,
2896 cbRowInfo** ppRow,
2897 cbBarInfo** ppBar
2898 )
2899 {
2900 (*ppRow) = NULL;
2901 (*ppBar) = NULL;
2902
2903 for( size_t i = 0; i != mRows.Count(); ++i )
2904 {
2905 cbRowInfo& row = *mRows[i];
2906
2907 *ppRow = &row;
2908
2909 // hit-test handles of the row, if present
2910
2911 if ( row.mHasUpperHandle )
2912 {
2913 if ( HasPoint( pos, 0, row.mRowY,
2914 row.mRowWidth, mProps.mResizeHandleSize ) )
2915
2916 return CB_UPPER_ROW_HANDLE_HITTED;
2917 }
2918 else
2919 if ( row.mHasLowerHandle )
2920 {
2921 if ( HasPoint( pos, 0, row.mRowY + row.mRowHeight - mProps.mResizeHandleSize,
2922 row.mRowWidth, mProps.mResizeHandleSize ) )
2923
2924 return CB_LOWER_ROW_HANDLE_HITTED;
2925 }
2926
2927 // hit-test bar handles and bar content
2928
2929 for( size_t k = 0; k != row.mBars.Count(); ++k )
2930 {
2931 cbBarInfo& bar = *row.mBars[k];
2932 wxRect& bounds = bar.mBounds;
2933
2934 *ppBar = &bar;
2935
2936 if ( bar.mHasLeftHandle )
2937 {
2938 if ( HasPoint( pos, bounds.x, bounds.y,
2939 mProps.mResizeHandleSize, bounds.height ) )
2940
2941 return CB_LEFT_BAR_HANDLE_HITTED;
2942 }
2943 else
2944 if ( bar.mHasRightHandle )
2945 {
2946 if ( HasPoint( pos, bounds.x + bounds.width - mProps.mResizeHandleSize, bounds.y,
2947 mProps.mResizeHandleSize, bounds.height ) )
2948
2949 return CB_RIGHT_BAR_HANDLE_HITTED;
2950 }
2951
2952 if ( HasPoint( pos, bounds.x, bounds.y, bounds.width, bounds.height ) )
2953
2954 return CB_BAR_CONTENT_HITTED;
2955
2956 } // hit-test next bar
2957
2958 } // next row
2959
2960 return CB_NO_ITEMS_HITTED;
2961 }
2962
2963 void cbDockPane::GetBarResizeRange( cbBarInfo* pBar, int* from, int *till,
2964 bool forLeftHandle )
2965 {
2966 cbBarInfo* pGivenBar = pBar;
2967
2968 int notFree = 0;
2969
2970 // calc unavailable space from the left
2971
2972 while( pBar->mpPrev )
2973 {
2974 pBar = pBar->mpPrev;
2975
2976 if ( !pBar->IsFixed() ) notFree += mProps.mMinCBarDim.x;
2977 else notFree += pBar->mBounds.width;
2978 }
2979
2980 *from = notFree;
2981
2982 pBar = pGivenBar;
2983
2984 notFree = 0;
2985
2986 // calc unavailable space from the right
2987
2988 while( pBar->mpNext )
2989 {
2990 pBar = pBar->mpNext;
2991
2992 if ( pBar->mBounds.x >= mPaneWidth ) break;
2993
2994 // treat not-fixed bars as minimized
2995
2996 if ( !pBar->IsFixed() )
2997
2998 notFree += mProps.mMinCBarDim.x;
2999 else
3000 {
3001 if ( pBar->mBounds.x + pBar->mBounds.width >= mPaneWidth )
3002 {
3003 notFree += mPaneWidth - pBar->mBounds.x;
3004 break;
3005 }
3006 else
3007 notFree += pBar->mBounds.width;
3008 }
3009
3010 }
3011
3012 *till = mPaneWidth - notFree;
3013
3014 // do not let resizing totally deform the bar itself
3015
3016 if ( forLeftHandle )
3017
3018 (*till) -= mProps.mMinCBarDim.x;
3019 else
3020
3021 (*from) += mProps.mMinCBarDim.x;
3022 }
3023
3024 int cbDockPane::GetMinimalRowHeight( cbRowInfo* pRow )
3025 {
3026 int height = mProps.mMinCBarDim.y;
3027
3028 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
3029
3030 if ( pRow->mBars[i]->IsFixed() )
3031
3032 height = wxMax( height, pRow->mBars[i]->mBounds.height );
3033
3034 if ( pRow->mHasUpperHandle )
3035
3036 height += mProps.mResizeHandleSize;
3037
3038 if ( pRow->mHasLowerHandle )
3039
3040 height += mProps.mResizeHandleSize;
3041
3042 return height;
3043 }
3044
3045 void cbDockPane::SetRowHeight( cbRowInfo* pRow, int newHeight )
3046 {
3047 if ( pRow->mHasUpperHandle )
3048
3049 newHeight -= mProps.mResizeHandleSize;
3050
3051 if ( pRow->mHasLowerHandle )
3052
3053 newHeight -= mProps.mResizeHandleSize;
3054
3055 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
3056
3057 if ( !pRow->mBars[i]->IsFixed() )
3058
3059 pRow->mBars[i]->mBounds.height = newHeight;
3060 }
3061
3062 void cbDockPane::GetRowResizeRange( cbRowInfo* pRow, int* from, int* till,
3063 bool forUpperHandle )
3064 {
3065 cbRowInfo* pGivenRow = pRow;
3066
3067 // calc unavailable space from above
3068
3069 int notFree = 0;
3070
3071 while( pRow->mpPrev )
3072 {
3073 pRow = pRow->mpPrev;
3074
3075 notFree += GetMinimalRowHeight( pRow );
3076
3077 };
3078
3079 *from = notFree;
3080
3081 // allow accupy the client window space by resizing pane rows
3082 if ( mAlignment == wxBOTTOM )
3083
3084 *from -= mpLayout->GetClientHeight();
3085 else
3086 if ( mAlignment == wxRIGHT )
3087
3088 *from -= mpLayout->GetClientWidth();
3089
3090 // calc unavailable space from below
3091
3092 pRow = pGivenRow;
3093
3094 notFree = 0;
3095
3096 while( pRow->mpNext )
3097 {
3098 pRow = pRow->mpNext;
3099
3100 notFree += GetMinimalRowHeight( pRow );
3101
3102 }
3103
3104 *till = mPaneHeight - notFree;
3105
3106 // allow adjustinig pane space vs. client window space by resizing pane row heights
3107
3108 if ( mAlignment == wxTOP )
3109
3110 *till += mpLayout->GetClientHeight();
3111 else
3112 if ( mAlignment == wxLEFT )
3113
3114 *till += mpLayout->GetClientWidth();
3115
3116 // do not let the resizing of the row totally squeeze the row itself
3117
3118 cbRowInfo& row = *pGivenRow;
3119
3120 if ( forUpperHandle )
3121 {
3122 *till = row.mRowY + row.mRowHeight - GetMinimalRowHeight( pGivenRow );
3123
3124 if ( row.mHasUpperHandle )
3125
3126 *till -= mProps.mResizeHandleSize;
3127 }
3128 else
3129 {
3130 *from += GetMinimalRowHeight( pGivenRow );
3131
3132 if ( row.mHasLowerHandle )
3133
3134 *from -= mProps.mResizeHandleSize;
3135 }
3136 }
3137
3138 void cbDockPane::ResizeRow( cbRowInfo* pRow, int ofs,
3139 bool forUpperHandle )
3140 {
3141 cbResizeRowEvent evt( pRow, ofs, forUpperHandle, this );
3142
3143 mpLayout->FirePluginEvent( evt );
3144 }
3145
3146 void cbDockPane::ResizeBar( cbBarInfo* pBar, int ofs,
3147 bool forLeftHandle )
3148 {
3149 pBar->mpRow->mpExpandedBar = NULL;
3150
3151 mpLayout->GetUpdatesManager().OnStartChanges();
3152
3153 wxRect& bounds = pBar->mBounds;
3154
3155 if ( forLeftHandle )
3156 {
3157 // do not allow bar width become less then minimal
3158 if ( bounds.x + ofs > bounds.x + bounds.width - mProps.mMinCBarDim.x )
3159 {
3160 bounds.width = mProps.mMinCBarDim.x;
3161 bounds.x += ofs;
3162 }
3163 else
3164 {
3165 bounds.x += ofs;
3166 bounds.width -= ofs;
3167 }
3168 }
3169 else
3170 {
3171 // move bar left if necessary
3172 if ( bounds.width + ofs < mProps.mMinCBarDim.x )
3173 {
3174 bounds.x = bounds.x + bounds.width + ofs - mProps.mMinCBarDim.x;
3175 bounds.width = mProps.mMinCBarDim.x;
3176 }
3177 else
3178 // resize right border only
3179 bounds.width += ofs;
3180 }
3181
3182
3183 cbRowInfo* pToRow = pBar->mpRow;
3184
3185 this->RemoveBar( pBar );
3186
3187 InsertBar( pBar, pToRow );
3188
3189 mpLayout->RecalcLayout(FALSE);
3190
3191 mpLayout->GetUpdatesManager().OnFinishChanges();
3192 mpLayout->GetUpdatesManager().UpdateNow();
3193 }
3194
3195
3196 /*** row/bar resizing related methods ***/
3197
3198 void cbDockPane::DrawVertHandle( wxDC& dc, int x, int y, int height )
3199 {
3200 int lower = y + height;
3201
3202 dc.SetPen( mpLayout->mLightPen );
3203 dc.DrawLine( x,y, x, lower );
3204
3205 dc.SetPen( mpLayout->mGrayPen );
3206 for( int i = 0; i != mProps.mResizeHandleSize-1; ++i )
3207 {
3208 ++x;
3209 dc.DrawLine( x,y, x, lower );
3210 }
3211
3212 dc.SetPen( mpLayout->mDarkPen );
3213 ++x;
3214 dc.DrawLine( x,y, x, lower );
3215
3216 dc.SetPen( mpLayout->mBlackPen );
3217 ++x;
3218 dc.DrawLine( x,y, x, lower );
3219 }
3220
3221 void cbDockPane::DrawHorizHandle( wxDC& dc, int x, int y, int width )
3222 {
3223 int right = x + width;
3224
3225 dc.SetPen( mpLayout->mLightPen );
3226 dc.DrawLine( x,y, right, y );
3227
3228 dc.SetPen( mpLayout->mGrayPen );
3229
3230 for( int i = 0; i != mProps.mResizeHandleSize-1; ++i )
3231 {
3232 ++y;
3233 dc.DrawLine( x,y, right, y );
3234 }
3235
3236 dc.SetPen( mpLayout->mDarkPen );
3237 dc.DrawLine( x,y, right, ++y );
3238
3239 dc.SetPen( mpLayout->mBlackPen );
3240 dc.DrawLine( x,y, right, ++y );
3241 }
3242
3243 cbBarInfo* cbDockPane::GetBarInfoByWindow( wxWindow* pBarWnd )
3244 {
3245 wxBarIterator i( mRows );
3246
3247 while( i.Next() )
3248
3249 if ( i.BarInfo().mpBarWnd == pBarWnd )
3250
3251 return &i.BarInfo();
3252
3253 return NULL;
3254 }
3255
3256 void cbDockPane::GetRowShapeData( cbRowInfo* pRow, wxList* pLst )
3257 {
3258 pLst->DeleteContents( TRUE );
3259 pLst->Clear();
3260
3261 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
3262 {
3263 cbBarInfo& bar = *pRow->mBars[i];
3264
3265 cbBarShapeData* pData = new cbBarShapeData();
3266
3267 pLst->Append( (wxObject*)pData );
3268
3269 pData->mBounds = bar.mBounds;
3270 pData->mLenRatio = bar.mLenRatio;
3271 }
3272 }
3273
3274 void cbDockPane::SetRowShapeData( cbRowInfo* pRow, wxList* pLst )
3275 {
3276 if ( pLst->First() == NULL ) return;
3277
3278 wxNode* pData = pLst->First();
3279
3280 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
3281 {
3282 wxASSERT( pData ); // DBG::
3283
3284 cbBarInfo& bar = *pRow->mBars[i];;
3285
3286 cbBarShapeData& data = *((cbBarShapeData*)pData->Data());
3287
3288 bar.mBounds = data.mBounds;
3289 bar.mLenRatio = data.mLenRatio;
3290
3291 pData = pData->Next();
3292 }
3293 }
3294
3295 /***** Implementation for class cbUpdatesManagerBase *****/
3296
3297 IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase, wxObject )
3298
3299 /***** Implementation for class cbPluginBase *****/
3300
3301 IMPLEMENT_ABSTRACT_CLASS( cbPluginBase, wxEvtHandler )
3302
3303 cbPluginBase::~cbPluginBase()
3304 {
3305 // nothing
3306 }
3307
3308 bool cbPluginBase::ProcessEvent(wxEvent& event)
3309 {
3310 if ( mPaneMask == wxALL_PANES )
3311
3312 return wxEvtHandler::ProcessEvent( event );
3313
3314 // extract mask info. from received event
3315
3316 cbPluginEvent& evt = *( (cbPluginEvent*)&event );
3317
3318 if ( evt.mpPane == 0 &&
3319 mPaneMask == wxALL_PANES )
3320
3321 return wxEvtHandler::ProcessEvent( event );
3322
3323 int mask = 0;
3324
3325 switch ( evt.mpPane->mAlignment )
3326 {
3327 case wxTOP : mask = wxTOP_PANE; break;
3328 case wxBOTTOM : mask = wxBOTTOM_PANE;break;
3329 case wxLEFT : mask = wxLEFT_PANE; break;
3330 case wxRIGHT : mask = wxRIGHT_PANE; break;
3331 }
3332
3333 // if event's pane maks matches the plugin's mask
3334
3335 if ( mPaneMask & mask )
3336
3337 return wxEvtHandler::ProcessEvent( event );
3338
3339 // otherwise pass to the next handler if present
3340
3341 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event ) )
3342
3343 return TRUE;
3344 else
3345 return FALSE;
3346 }
3347
3348