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