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