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