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