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