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