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