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