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