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