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