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