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