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