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