1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Contrib. demo
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "controlbar.h"
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
31 #include "wx/string.h"
32 #include "wx/utils.h" // import wxMin,wxMax macros
33 #include "wx/minifram.h"
35 #include "controlbar.h"
37 // import classes of default plugins
39 #include "panedrawpl.h"
40 #include "rowlayoutpl.h"
41 #include "antiflickpl.h"
42 #include "bardragpl.h"
45 #include "gcupdatesmgr.h" // import default updates manager class ("garbage-collecting" one)
46 #include "updatesmgr.h"
50 // some ascii-art, still can't get these *nice* cursors working on wx... :-(
52 static const char* _gHorizCursorImg
[] =
54 "............XX....XX............",
55 "............XX....XX............",
56 "............XX....XX............",
57 "............XX....XX............",
58 "............XX....XX............",
59 "...X........XX....XX........X...",
60 "..XX........XX....XX........XX..",
61 ".XXX........XX....XX........XXX.",
62 "XXXXXXXXXXXXXX....XXXXXXXXXXXXXX",
63 ".XXX........XX....XX........XXX.",
64 "..XX........XX....XX........XX..",
65 "...X........XX....XX........X...",
66 "............XX....XX............",
67 "............XX....XX............",
68 "............XX....XX............",
69 "............XX....XX............"
72 static const char* _gVertCursorImg
[] =
74 "................X...............",
75 "...............XXX..............",
76 "..............XXXXX.............",
77 ".............XXXXXXX............",
78 "................X...............",
79 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
80 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
81 "................................",
82 "................................",
83 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
84 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
85 "................X...............",
86 ".............XXXXXXX............",
87 "..............XXXXX.............",
88 "...............XXX..............",
89 "................X..............."
92 // helper inline functions
94 static inline bool rect_contains_point( const wxRect
& rect
, int x
, int y
)
96 return ( x
>= rect
.x
&&
98 x
< rect
.x
+ rect
.width
&&
99 y
< rect
.y
+ rect
.height
);
102 static inline bool rect_hits_rect( const wxRect
& r1
, const wxRect
& r2
)
104 if ( ( r2
.x
>= r1
.x
&& r2
.x
<= r1
.x
+ r1
.width
) ||
105 ( r1
.x
>= r2
.x
&& r1
.x
<= r2
.x
+ r2
.width
) )
107 if ( ( r2
.y
>= r1
.y
&& r2
.y
<= r1
.y
+ r1
.height
) ||
108 ( r1
.y
>= r2
.y
&& r1
.y
<= r2
.y
+ r2
.height
) )
115 static inline void hide_rect( wxRect
& r
)
123 static inline void clip_rect_against_rect( wxRect
& r1
, const wxRect
& r2
)
127 r1
.x
>= r2
.x
+ r2
.width
||
128 r1
.y
>= r2
.y
+ r2
.height
136 if ( r1
.x
+ r1
.width
> r2
.x
+ r2
.width
)
138 r1
.width
= r2
.x
+ r2
.width
- r1
.x
;
140 if ( r1
.y
+ r1
.height
> r2
.y
+ r2
.height
)
142 r1
.height
= r2
.y
+ r2
.height
- r1
.y
;
146 /***** Implementation for class cbBarSpy *****/
148 IMPLEMENT_DYNAMIC_CLASS( cbBarSpy
, wxEvtHandler
)
150 cbBarSpy::cbBarSpy(void)
155 cbBarSpy::cbBarSpy( wxFrameLayout
* pPanel
)
161 void cbBarSpy::SetBarWindow( wxWindow
* pWnd
)
166 bool cbBarSpy::ProcessEvent(wxEvent
& event
)
168 bool handled
= wxEvtHandler::ProcessEvent( event
);
170 int type
= event
.GetEventType();
172 if ( !handled
&& ( type
== wxEVT_LEFT_DOWN
||
173 type
== wxEVT_LEFT_DCLICK
) )
175 wxMouseEvent
& mevent
= *((wxMouseEvent
*)&event
);
180 mpBarWnd
->ClientToScreen( &x
, &y
);
181 mpLayout
->GetParentFrame().ScreenToClient( &x
, &y
);
186 // forwared not-handled event to frame-layout
188 if ( type
== wxEVT_LEFT_DOWN
)
190 //mpLayout->OnLButtonDown( mevent );
194 mpLayout
->OnLDblClick( mevent
);
202 /***** Implementation for class wxFrameLayout *****/
204 IMPLEMENT_DYNAMIC_CLASS( wxFrameLayout
, wxEvtHandler
)
206 BEGIN_EVENT_TABLE( wxFrameLayout
, wxEvtHandler
)
208 EVT_PAINT ( wxFrameLayout::OnPaint
)
209 EVT_SIZE ( wxFrameLayout::OnSize
)
210 EVT_LEFT_DOWN ( wxFrameLayout::OnLButtonDown
)
211 EVT_LEFT_UP ( wxFrameLayout::OnLButtonUp
)
212 EVT_RIGHT_DOWN ( wxFrameLayout::OnRButtonDown
)
213 EVT_RIGHT_UP ( wxFrameLayout::OnRButtonUp
)
214 EVT_MOTION ( wxFrameLayout::OnMouseMove
)
216 EVT_LEFT_DCLICK( wxFrameLayout::OnLDblClick
)
218 EVT_IDLE ( wxFrameLayout::OnIdle
)
219 EVT_SET_FOCUS ( wxFrameLayout::OnSetFocus
)
220 EVT_KILL_FOCUS ( wxFrameLayout::OnKillFocus
)
222 EVT_ACTIVATE ( wxFrameLayout::OnActivate
)
224 EVT_ERASE_BACKGROUND( wxFrameLayout::OnEraseBackground
)
228 // FIXME:: how to eliminate these cut&pasted constructors?
230 wxFrameLayout::wxFrameLayout(void)
233 mpFrameClient( NULL
),
235 mDarkPen ( wxColour(128,128,128), 1, wxSOLID
),
236 mLightPen ( wxColour(255,255,255), 1, wxSOLID
),
237 mGrayPen ( wxColour(192,192,192), 1, wxSOLID
),
238 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID
),
239 mBorderPen( wxColour(192,192,192), 1, wxSOLID
),
241 mpPaneInFocus( NULL
),
244 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT
),
246 mpTopPlugin ( NULL
),
247 mpCaputesInput( NULL
),
248 mRecalcPending( TRUE
),
250 mCheckFocusWhenIdle( FALSE
),
251 mClientWndRefreshPending( FALSE
)
255 for( int i
= 0; i
!= MAX_PANES
; ++i
)
259 mFloatingOn
= CanReparent();
262 wxFrameLayout::wxFrameLayout( wxWindow
* pParentFrame
, wxWindow
* pFrameClient
, bool activateNow
)
264 : mpFrame( pParentFrame
),
265 mpFrameClient(pFrameClient
),
267 mDarkPen ( wxColour(128,128,128), 1, wxSOLID
),
268 mLightPen ( wxColour(255,255,255), 1, wxSOLID
),
269 mGrayPen ( wxColour(192,192,192), 1, wxSOLID
),
270 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID
),
271 mBorderPen( wxColour(192,192,192), 1, wxSOLID
),
273 mpPaneInFocus( NULL
),
276 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT
),
278 mpUpdatesMgr( NULL
),
280 mpTopPlugin ( NULL
),
281 mpCaputesInput( NULL
),
283 mRecalcPending( TRUE
),
285 mFloatingOn ( TRUE
),
287 mCheckFocusWhenIdle( FALSE
),
288 mClientWndRefreshPending( FALSE
)
292 for( int i
= 0; i
!= MAX_PANES
; ++i
)
294 mPanes
[i
] = new cbDockPane( i
, this );
301 // DBG:: set RED color of frame's background for the
302 // prurpose of tracking engine bugs "visually"
304 GetParentFrame().SetBackgroundColour( wxColour(192,192,192) );
307 mFloatingOn
= CanReparent();
310 // NOTE:: below are the only plaftorm-check "ifdef"s in the docking system!
312 bool wxFrameLayout::CanReparent()
322 return FALSE
; // reparenting is not yet supported by Motif and others
331 void wxFrameLayout::ReparentWindow( wxWindow
* pChild
, wxWindow
* pNewParent
)
335 if ( pChild
->GetParent() )
337 bool success
= pChild
->GetParent()->GetChildren()->DeleteObject( pChild
);
339 wxASSERT( success
); // DBG::
342 ::SetParent( (HWND
)pChild
->m_hWnd
, (HWND
)pNewParent
->m_hWnd
);
344 pNewParent
->GetChildren()->Append( pChild
);
346 pChild
->SetParent( pNewParent
);
351 // FOR NOW:: floating with wxGtk still very buggy
357 pChild
->ReParent( pNewParent
);
362 wxMessageBox( "Sorry, docking is not supported for ports other than MSW and wxGTK" );
365 void wxFrameLayout::DestroyBarWindows()
367 wxNode
* pSpy
= mBarSpyList
.First();
371 cbBarSpy
& spy
= *((cbBarSpy
*)pSpy
->Data());
373 if ( spy
.mpBarWnd
->GetEventHandler() == &spy
)
375 spy
.mpBarWnd
->PopEventHandler();
384 for( size_t i
= 0; i
!= mAllBars
.Count(); ++i
)
386 if ( mAllBars
[i
]->mpBarWnd
)
388 mAllBars
[i
]->mpBarWnd
->Destroy();
389 mAllBars
[i
]->mpBarWnd
= NULL
;
394 void wxFrameLayout::ShowFloatedWindows( bool show
)
396 wxNode
* pNode
= mFloatedFrames
.First();
400 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
404 pNode
= pNode
->Next();
408 wxFrameLayout::~wxFrameLayout()
412 if ( mpUpdatesMgr
) delete mpUpdatesMgr
;
414 // destoy the chain of plugins from left to right
416 wxEvtHandler
* pCur
= mpTopPlugin
;
420 while ( pCur
->GetPreviousHandler() )
422 pCur
= pCur
->GetPreviousHandler();
426 wxEvtHandler
* pNext
= pCur
->GetNextHandler();
433 // destroy contents of arrays and lists
437 for( i
= 0; i
!= MAX_PANES
; ++i
)
439 if ( mPanes
[i
] ) delete mPanes
[i
];
441 if ( mpHorizCursor
) delete mpHorizCursor
;
442 if ( mpVertCursor
) delete mpVertCursor
;
443 if ( mpNormalCursor
) delete mpNormalCursor
;
444 if ( mpDragCursor
) delete mpDragCursor
;
445 if ( mpDragCursor
) delete mpNECursor
;
447 wxNode
* pSpy
= mBarSpyList
.First();
451 cbBarSpy
& spy
= *((cbBarSpy
*)pSpy
->Data());
453 if ( spy
.mpBarWnd
->GetEventHandler() == &spy
)
455 spy
.mpBarWnd
->PopEventHandler();
462 for( i
= 0; i
!= mAllBars
.Count(); ++i
)
467 void wxFrameLayout::EnableFloating( bool enable
)
469 mFloatingOn
= enable
&& CanReparent();
472 void wxFrameLayout::Activate()
478 ShowFloatedWindows( TRUE
);
481 void wxFrameLayout::Deactivate()
483 ShowFloatedWindows( FALSE
);
490 void wxFrameLayout::SetFrameClient( wxWindow
* pFrameClient
)
492 mpFrameClient
= pFrameClient
;
495 wxWindow
* wxFrameLayout::GetFrameClient()
497 return mpFrameClient
;
500 cbUpdatesManagerBase
& wxFrameLayout::GetUpdatesManager()
502 if ( !mpUpdatesMgr
) mpUpdatesMgr
= CreateUpdatesManager();
504 return *mpUpdatesMgr
;
507 void wxFrameLayout::SetUpdatesManager( cbUpdatesManagerBase
* pUMgr
)
509 if ( mpUpdatesMgr
) delete mpUpdatesMgr
;
511 mpUpdatesMgr
= pUMgr
;
513 mpUpdatesMgr
->SetLayout( this );
516 cbUpdatesManagerBase
* wxFrameLayout::CreateUpdatesManager()
518 return new cbGCUpdatesMgr( this );
519 //return new cbSimpleUpdatesMgr( this );
522 void wxFrameLayout::AddBar( wxWindow
* pBarWnd
,
528 const wxString
& name
,
533 if ( pBarWnd
&& spyEvents
)
535 // hook up spy to bar window
536 cbBarSpy
* pSpy
= new cbBarSpy( this );
538 pSpy
->SetBarWindow( pBarWnd
);
539 pBarWnd
->PushEventHandler( pSpy
);
541 mBarSpyList
.Append( pSpy
);
544 cbBarInfo
* pInfo
= new cbBarInfo();
547 pInfo
->mpBarWnd
= pBarWnd
;
548 pInfo
->mDimInfo
= dimInfo
;
549 pInfo
->mState
= state
;
550 pInfo
->mAlignment
= alignment
;
551 pInfo
->mRowNo
= rowNo
;
552 pInfo
->mBounds
.x
= columnPos
;
554 mAllBars
.Add( pInfo
);
556 DoSetBarState( pInfo
);
559 bool wxFrameLayout::RedockBar( cbBarInfo
* pBar
,
560 const wxRect
& shapeInParent
,
566 pToPane
= HitTestPanes( shapeInParent
, NULL
);
570 return FALSE
; // bar's shape does not hit any pane
571 // - redocking is NOT posssible
573 cbDockPane
* pBarPane
= GetBarPane( pBar
);
577 GetUpdatesManager().OnStartChanges();
579 pBarPane
->RemoveBar( pBar
);
581 // FIXME FIXME:: the below recalc. may be a *huge* performance
582 // hit, it could be eliminated though...
583 // but first the "pane-postion-changed" problem
586 RecalcLayout( FALSE
);
588 pToPane
->InsertBar( pBar
, shapeInParent
);
590 RecalcLayout( FALSE
);
592 // finish update "transaction"
596 GetUpdatesManager().OnFinishChanges();
597 GetUpdatesManager().UpdateNow();
603 cbBarInfo
* wxFrameLayout::FindBarByName( const wxString
& name
)
605 for( size_t i
= 0; i
!= mAllBars
.Count(); ++i
)
607 if ( mAllBars
[i
]->mName
== name
)
614 BarArrayT
& wxFrameLayout::GetBars()
619 void wxFrameLayout::SetBarState( cbBarInfo
* pBar
, int newState
, bool updateNow
)
621 if ( newState
== wxCBAR_FLOATING
&& !mFloatingOn
)
627 GetUpdatesManager().OnStartChanges();
629 pBar
->mUMgrData
.SetDirty(TRUE
);
631 // check bar's previous state
633 if ( pBar
->mState
!= wxCBAR_HIDDEN
&& pBar
->mState
!= wxCBAR_FLOATING
)
638 bool success
= LocateBar( pBar
, &pRow
, &pPane
);
640 wxASSERT( success
); // DBG::
642 // save LRU-dim info before removing bar
644 pBar
->mDimInfo
.mLRUPane
= pPane
->GetAlignment();
645 pBar
->mDimInfo
.mBounds
[ pPane
->GetAlignment() ] = pBar
->mBounds
;
647 // remove it from the pane it was docked on
649 pPane
->RemoveBar( pBar
);
653 if ( pBar
->mState
== wxCBAR_FLOATING
&& newState
!= wxCBAR_FLOATING
)
655 // remove bar's window form the containing mini-frame
656 // and set it's parent to be layout's parent frame
658 if ( pBar
->mpBarWnd
)
660 pBar
->mpBarWnd
->Show(FALSE
); // to avoid flicker upon reparenting
662 wxNode
* pNode
= mFloatedFrames
.First();
666 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
668 if ( pFFrm
->GetBar() == pBar
)
670 pFFrm
->Show( FALSE
); // reduces flicker sligthly
672 ReparentWindow( pBar
->mpBarWnd
, &GetParentFrame() );
674 pBar
->mBounds
= pBar
->mDimInfo
.mBounds
[ pBar
->mDimInfo
.mLRUPane
];
676 if ( newState
!= wxCBAR_HIDDEN
)
678 pBar
->mAlignment
= pBar
->mDimInfo
.mLRUPane
;
680 mFloatedFrames
.DeleteNode( pNode
);
682 pFFrm
->Show( FALSE
);
683 pFFrm
->Destroy(); break;
686 pNode
= pNode
->Next();
689 // FOR NOW:: excessive!
690 //if ( mpFrameClient ) mpFrameClient->Refresh();
691 if ( mpFrameClient
) mClientWndRefreshPending
= TRUE
;
695 pBar
->mState
= newState
;
697 DoSetBarState( pBar
);
703 GetUpdatesManager().OnFinishChanges();
704 GetUpdatesManager().UpdateNow();
708 void wxFrameLayout::ApplyBarProperties( cbBarInfo
* pBar
)
710 if ( pBar
->mState
== wxCBAR_FLOATING
)
712 RepositionFloatedBar( pBar
);
715 if ( pBar
->mState
== wxCBAR_DOCKED_HORIZONTALLY
||
716 pBar
->mState
== wxCBAR_DOCKED_VERTICALLY
724 void wxFrameLayout::RepositionFloatedBar( cbBarInfo
* pBar
)
726 if ( !mFloatingOn
) return;
728 wxNode
* pNode
= mFloatedFrames
.First();
732 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
734 if ( pFFrm
->GetBar() == pBar
)
736 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
741 GetParentFrame().ClientToScreen( &x
, &y
);
743 pFFrm
->PositionFloatedWnd( x
,y
,
750 pNode
= pNode
->Next();
754 void wxFrameLayout::DoSetBarState( cbBarInfo
* pBar
)
756 if ( pBar
->mState
!= wxCBAR_FLOATING
&&
757 pBar
->mState
!= wxCBAR_HIDDEN
)
761 mPanes
[pBar
->mAlignment
]->InsertBar( pBar
);
763 if ( pBar
->mState
== wxCBAR_HIDDEN
)
767 if ( pBar
->mpBarWnd
)
769 pBar
->mpBarWnd
->Show( FALSE
);
773 if ( !mFloatingOn
) return;
777 if ( pBar
->mpBarWnd
== NULL
|| !CanReparent() )
779 // FOR NOW:: just hide it
781 if ( pBar
->mpBarWnd
)
783 pBar
->mpBarWnd
->Show( FALSE
);
785 pBar
->mState
== wxCBAR_HIDDEN
;
790 cbFloatedBarWindow
* pMiniFrm
= new cbFloatedBarWindow();
792 pMiniFrm
->SetBar( pBar
);
793 pMiniFrm
->SetLayout( this );
795 pMiniFrm
->Create( &GetParentFrame(), -1, pBar
->mName
,
798 wxSTAY_ON_TOP
//| wxTHICK_FRAME
801 pMiniFrm
->SetClient( pBar
->mpBarWnd
);
803 ReparentWindow( pBar
->mpBarWnd
, pMiniFrm
);
805 mFloatedFrames
.Append( pMiniFrm
);
807 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
809 // check if it wasn't floated anytime before
811 if ( bounds
.width
== -1 )
813 wxRect
& clntRect
= GetClientRect();
815 // adjust position into which the next floated bar will be placed
817 if ( mNextFloatedWndPos
.x
+ bounds
.width
> clntRect
.width
)
819 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
821 if ( mNextFloatedWndPos
.y
+ bounds
.height
> clntRect
.height
)
823 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
825 bounds
.x
= mNextFloatedWndPos
.x
+ clntRect
.x
;
826 bounds
.y
= mNextFloatedWndPos
.y
+ clntRect
.y
;
828 bounds
.width
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].x
;
829 bounds
.height
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].y
;
831 mNextFloatedWndPos
.x
+= mFloatingPosStep
.x
;
832 mNextFloatedWndPos
.y
+= mFloatingPosStep
.y
;
835 pMiniFrm
->Show( TRUE
);
837 // FIXME:: this is excessive
838 pBar
->mpBarWnd
->Show(TRUE
);
842 void wxFrameLayout::RemoveBar( cbBarInfo
* pBarInfo
)
844 // first, try to "guess" what was the perviouse state of the bar
849 if ( LocateBar( pBarInfo
, &pRow
, &pPane
) )
851 // ...aha, bar was docked into one of the panes,
852 // remove it from there
854 pPane
->RemoveBar( pBarInfo
);
857 for( size_t i
= 0; i
!= mAllBars
.Count(); ++i
)
859 if ( mAllBars
[i
] == pBarInfo
)
861 mAllBars
.Remove( i
);
863 if ( pBarInfo
->mpBarWnd
) // hides it's window
865 pBarInfo
->mpBarWnd
->Show( FALSE
);
872 wxASSERT(0); // DBG:: bar info should be present in the list of all bars of all panes
876 bool wxFrameLayout::LocateBar( cbBarInfo
* pBarInfo
,
878 cbDockPane
** ppPane
)
883 for( int n
= 0; n
!= MAX_PANES
; ++n
)
885 wxBarIterator
i( mPanes
[n
]->GetRowList() );
889 if ( &i
.BarInfo() == pBarInfo
)
891 (*ppPane
) = mPanes
[n
];
892 (*ppRow
) = &i
.RowInfo();
901 void wxFrameLayout::RecalcLayout( bool repositionBarsNow
)
903 mRecalcPending
= FALSE
;
905 int frmWidth
, frmHeight
;
906 mpFrame
->GetClientSize( &frmWidth
, &frmHeight
);
913 // pane positioning priorities in decreasing order:
914 // top, bottom, left, right
918 cbDockPane
* pPane
= mPanes
[ wxTOP
];
921 pPane
->SetPaneWidth( frmWidth
);
922 pPane
->RecalcLayout();
924 paneHeight
= pPane
->GetPaneHeight();
928 rect
.width
= frmWidth
;
929 rect
.height
= wxMin( paneHeight
, frmHeight
- curY
);
931 pPane
->SetBoundsInParent( rect
);
937 pPane
= mPanes
[ wxBOTTOM
];
939 pPane
->SetPaneWidth( frmWidth
);
940 pPane
->RecalcLayout();
942 paneHeight
= pPane
->GetPaneHeight();
945 rect
.y
= wxMax( frmHeight
- paneHeight
, curY
);
946 rect
.width
= frmWidth
;
947 rect
.height
= frmHeight
- rect
.y
;
949 pPane
->SetBoundsInParent( rect
);
953 pPane
= mPanes
[ wxLEFT
];
956 pPane
->SetPaneWidth( rect
.y
- curY
);
958 pPane
->RecalcLayout();
959 paneHeight
= pPane
->GetPaneHeight();
962 rect
.height
= rect
.y
- curY
;
965 rect
.width
= wxMin( paneHeight
, frmWidth
);
967 pPane
->SetBoundsInParent( rect
);
973 pPane
= mPanes
[ wxRIGHT
];
975 // left pane's height
976 pPane
->SetPaneWidth( rect
.height
);
978 pPane
->RecalcLayout();
979 paneHeight
= pPane
->GetPaneHeight();
981 // left pane's height
982 rect
.height
= rect
.height
;
983 rect
.x
= wxMax( frmWidth
- paneHeight
, curX
);
985 rect
.width
= frmWidth
- rect
.x
;
987 pPane
->SetBoundsInParent( rect
);
989 // recalc bounds of the client-window
991 mClntWndBounds
.x
= mPanes
[wxLEFT
]->mBoundsInParent
.x
+
992 mPanes
[wxLEFT
]->mBoundsInParent
.width
;
993 mClntWndBounds
.y
= mPanes
[wxTOP
]->mBoundsInParent
.y
+
994 mPanes
[wxTOP
]->mBoundsInParent
.height
;
996 mClntWndBounds
.width
= mPanes
[wxRIGHT
]->mBoundsInParent
.x
-
998 mClntWndBounds
.height
= mPanes
[wxBOTTOM
]->mBoundsInParent
.y
-
1001 if ( repositionBarsNow
)
1006 int wxFrameLayout::GetClientHeight()
1008 // for better portablility wxWindow::GetSzie() is not used here
1010 return mClntWndBounds
.height
;
1013 int wxFrameLayout::GetClientWidth()
1015 // for better portablility wxWindow::GetSzie() is not used here
1017 return mClntWndBounds
.width
;
1020 void wxFrameLayout::PositionClientWindow()
1022 if ( mpFrameClient
)
1024 if ( mClntWndBounds
.width
>= 1 && mClntWndBounds
.height
>= 1 )
1026 mpFrameClient
->SetSize( mClntWndBounds
.x
, mClntWndBounds
.y
,
1027 mClntWndBounds
.width
, mClntWndBounds
.height
, 0 );
1029 if ( !mpFrameClient
->IsShown() )
1031 mpFrameClient
->Show( TRUE
);
1034 mpFrameClient
->Show( FALSE
);
1038 void wxFrameLayout::PositionPanes()
1040 PositionClientWindow();
1042 // FOR NOW:: excessive updates!
1043 // reposition bars within all panes
1045 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1047 mPanes
[i
]->SizePaneObjects();
1050 void wxFrameLayout::OnSize( wxSizeEvent
& event
)
1052 if ( event
.GetEventObject() == (wxObject
*) mpFrame
)
1057 /*** protected members ***/
1059 void wxFrameLayout::HideBarWindows()
1061 for( size_t i
= 0; i
!= mAllBars
.Count(); ++i
)
1063 if ( mAllBars
[i
]->mpBarWnd
&& mAllBars
[i
]->mState
!= wxCBAR_FLOATING
)
1065 mAllBars
[i
]->mpBarWnd
->Show( FALSE
);
1067 // then floated frames
1069 ShowFloatedWindows( FALSE
);
1071 if ( mpFrameClient
)
1073 mpFrameClient
->Show( FALSE
);
1076 void wxFrameLayout::UnhookFromFrame()
1078 // NOTE:: the SetEvtHandlerEnabled() method is not used
1079 // here, since it is assumed, that unhooking layout
1080 // from window may result destroying of the layout itself
1082 // BUG BUG BUG (wx):: this would not be a problem if
1083 // wxEvtHandler's destructor would check if
1084 // this handler is currently the top-most
1085 // handler of some window, and additionally
1086 // to the reconnecting itself from the chain
1087 // it would also re-setup current event handler
1088 // of the window using wxWindow::SetEventHandler()
1092 if ( mpFrame
->GetEventHandler() == this )
1094 mpFrame
->PopEventHandler();
1100 if ( this == mpFrame
->GetEventHandler() )
1102 mpFrame
->SetEventHandler( this->GetNextHandler() );
1105 wxEvtHandler
* pCur
= mpFrame
->GetEventHandler();
1109 if ( pCur
== this ); break;
1111 pCur
= pCur
->GetNextHandler();
1114 // do not try to unhook ourselves if we're not hooked yet
1115 if ( !pCur
) return;
1118 if ( GetPreviousHandler() )
1120 GetPreviousHandler()->SetNextHandler( GetNextHandler() );
1123 mpFrame
->PopEventHandler();
1128 if ( GetNextHandler() )
1130 GetNextHandler()->SetPreviousHandler( GetPreviousHandler() );
1132 SetNextHandler( NULL
);
1133 SetPreviousHandler( NULL
);
1137 void wxFrameLayout::HookUpToFrame()
1139 // unhook us first, we're already hooked up
1143 // put ourselves on top
1145 mpFrame
->PushEventHandler( this );
1148 cbDockPane
* wxFrameLayout::GetBarPane( cbBarInfo
* pBar
)
1150 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1152 if ( mPanes
[i
]->BarPresent( pBar
) ) return mPanes
[i
];
1157 void wxFrameLayout::CreateCursors()
1160 // FIXME:: the below code somehow doesn't work - curosors ramain unchaged
1163 set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
1165 mpHorizCursor = new wxCursor( bits, 32, 16 );
1167 set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
1169 mpVertCursor = new wxCursor( bits, 32, 16 );
1172 // FOR NOW:: use standard ones
1174 mpHorizCursor
= new wxCursor(wxCURSOR_SIZEWE
);
1175 mpVertCursor
= new wxCursor(wxCURSOR_SIZENS
);
1176 mpNormalCursor
= new wxCursor(wxCURSOR_ARROW
);
1177 mpDragCursor
= new wxCursor(wxCURSOR_CROSS
);
1178 mpNECursor
= new wxCursor(wxCURSOR_NO_ENTRY
);
1180 mFloatingPosStep
.x
= 25;
1181 mFloatingPosStep
.y
= 25;
1183 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
1184 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
1187 bool wxFrameLayout::HitTestPane( cbDockPane
* pPane
, int x
, int y
)
1189 return rect_contains_point( pPane
->GetRealRect(), x
, y
);
1192 cbDockPane
* wxFrameLayout::HitTestPanes( const wxRect
& rect
,
1193 cbDockPane
* pCurPane
)
1195 // first, give the privilege to the current pane
1197 if ( pCurPane
&& rect_hits_rect( pCurPane
->GetRealRect(), rect
) )
1201 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1203 if ( pCurPane
!= mPanes
[i
] &&
1204 rect_hits_rect( mPanes
[i
]->GetRealRect(), rect
) )
1211 void wxFrameLayout::ForwardMouseEvent( wxMouseEvent
& event
,
1212 cbDockPane
* pToPane
,
1215 wxPoint
pos( event
.m_x
, event
.m_y
);
1216 pToPane
->FrameToPane( &pos
.x
, &pos
.y
);
1218 switch ( eventType
)
1220 case cbEVT_PL_LEFT_DOWN
: { cbLeftDownEvent
evt( pos
, pToPane
);
1221 FirePluginEvent( evt
); break;
1224 case cbEVT_PL_LEFT_DCLICK
:{ cbLeftDClickEvent
evt( pos
, pToPane
);
1225 FirePluginEvent( evt
); break;
1228 case cbEVT_PL_LEFT_UP
: { cbLeftUpEvent
evt( pos
, pToPane
);
1229 FirePluginEvent( evt
); break;
1232 case cbEVT_PL_RIGHT_DOWN
: { cbRightDownEvent
evt( pos
, pToPane
);
1233 FirePluginEvent( evt
); break;
1236 case cbEVT_PL_RIGHT_UP
: { cbRightUpEvent
evt( pos
, pToPane
);
1237 FirePluginEvent( evt
); break;
1240 case cbEVT_PL_MOTION
: { cbMotionEvent
evt( pos
, pToPane
);
1241 FirePluginEvent( evt
); break;
1244 default : wxASSERT(0); // DBG::
1249 void wxFrameLayout::RouteMouseEvent( wxMouseEvent
& event
, int pluginEvtType
)
1251 if ( mpPaneInFocus
)
1253 ForwardMouseEvent( event
, mpPaneInFocus
, pluginEvtType
);
1255 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1257 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1259 ForwardMouseEvent( event
, mPanes
[i
], pluginEvtType
);
1265 /*** event handlers ***/
1267 void wxFrameLayout::OnRButtonDown( wxMouseEvent
& event
)
1269 RouteMouseEvent( event
, cbEVT_PL_RIGHT_DOWN
);
1272 void wxFrameLayout::OnRButtonUp( wxMouseEvent
& event
)
1274 RouteMouseEvent( event
, cbEVT_PL_RIGHT_UP
);
1277 void wxFrameLayout::OnLButtonDown( wxMouseEvent
& event
)
1279 RouteMouseEvent( event
, cbEVT_PL_LEFT_DOWN
);
1282 void wxFrameLayout::OnLDblClick( wxMouseEvent
& event
)
1284 RouteMouseEvent( event
, cbEVT_PL_LEFT_DCLICK
);
1287 void wxFrameLayout::OnLButtonUp( wxMouseEvent
& event
)
1289 RouteMouseEvent( event
, cbEVT_PL_LEFT_UP
);
1292 void wxFrameLayout::OnMouseMove( wxMouseEvent
& event
)
1294 if ( mpPaneInFocus
)
1296 ForwardMouseEvent( event
, mpPaneInFocus
, cbEVT_PL_MOTION
);
1298 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1300 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1302 if ( mpLRUPane
&& mpLRUPane
!= mPanes
[i
] )
1304 // simulate "mouse-leave" event
1305 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1308 ForwardMouseEvent( event
, mPanes
[i
], cbEVT_PL_MOTION
);
1310 mpLRUPane
= mPanes
[i
];
1317 // simulate "mouse-leave" event
1318 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1323 void wxFrameLayout::OnPaint( wxPaintEvent
& event
)
1325 if ( mRecalcPending
)
1327 RecalcLayout( TRUE
);
1329 wxPaintDC
dc(mpFrame
);
1331 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1333 wxRect
& rect
= mPanes
[i
]->mBoundsInParent
;
1335 dc
.SetClippingRegion( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1337 mPanes
[i
]->PaintPane(dc
);
1339 dc
.DestroyClippingRegion();
1345 void wxFrameLayout::OnEraseBackground( wxEraseEvent
& event
)
1350 void wxFrameLayout::OnIdle( wxIdleEvent
& event
)
1352 wxWindow
* focus
= wxWindow::FindFocus();
1354 if ( !focus
&& mCheckFocusWhenIdle
)
1356 wxMessageBox( "Hi, no more focus in this app!" );
1358 mCheckFocusWhenIdle
= FALSE
;
1359 //ShowFloatedWindows( FALSE );
1362 mCheckFocusWhenIdle
= FALSE
;
1368 void wxFrameLayout::OnKillFocus( wxFocusEvent
& event
)
1370 //wxMessageBox( "wxFrameLayoutGot Kill Focus!" );
1371 //ShowFloatedWindows( FALSE );
1374 void wxFrameLayout::OnSetFocus( wxFocusEvent
& event
)
1376 //ShowFloatedWindows( TRUE );
1379 void wxFrameLayout::OnActivate( wxActivateEvent
& event
)
1382 if ( event
.GetActive() == FALSE
)
1384 wxWindow
* focus
= wxWindow::FindFocus();
1386 if ( !focus
|| focus
== &GetParentFrame() )
1388 mCheckFocusWhenIdle
= TRUE
;
1392 wxMessageBox("Deactivated!" );
1399 void wxFrameLayout::GetPaneProperties( cbCommonPaneProperties
& props
, int alignment
)
1401 props
= mPanes
[alignment
]->mProps
;
1404 void wxFrameLayout::SetPaneProperties( const cbCommonPaneProperties
& props
, int paneMask
)
1406 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1408 if ( mPanes
[i
]->MatchesMask( paneMask
) )
1410 mPanes
[i
]->mProps
= props
;
1413 void wxFrameLayout::SetMargins( int top
, int bottom
, int left
, int right
,
1416 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1418 cbDockPane
& pane
= *mPanes
[i
];
1420 if ( pane
.MatchesMask( paneMask
) )
1422 pane
.mTopMargin
= top
;
1423 pane
.mBottomMargin
= bottom
;
1424 pane
.mLeftMargin
= left
;
1425 pane
.mRightMargin
= right
;
1430 void wxFrameLayout::SetPaneBackground( const wxColour
& colour
)
1432 mBorderPen
.SetColour( colour
);
1435 void wxFrameLayout::RefreshNow( bool recalcLayout
)
1437 if ( recalcLayout
) RecalcLayout( TRUE
);
1439 if ( mpFrame
) mpFrame
->Refresh();
1442 /*** plugin-related methods ***/
1444 void wxFrameLayout::FirePluginEvent( cbPluginEvent
& event
)
1446 // check state of input capture, before processing the event
1448 if ( mpCaputesInput
)
1450 bool isInputEvt
= TRUE
;
1452 switch ( event
.m_eventType
)
1454 case cbEVT_PL_LEFT_DOWN
: break;
1455 case cbEVT_PL_LEFT_UP
: break;
1456 case cbEVT_PL_RIGHT_DOWN
: break;
1457 case cbEVT_PL_RIGHT_UP
: break;
1458 case cbEVT_PL_MOTION
: break;
1460 default : isInputEvt
= FALSE
; break;
1465 mpCaputesInput
->ProcessEvent( event
);
1470 GetTopPlugin().ProcessEvent( event
);
1473 void wxFrameLayout::CaptureEventsForPlugin ( cbPluginBase
* pPlugin
)
1475 // cannot capture events for more than one plugin at a time
1476 wxASSERT( mpCaputesInput
== NULL
);
1478 mpCaputesInput
= pPlugin
;
1482 void wxFrameLayout::ReleaseEventsFromPlugin( cbPluginBase
* pPlugin
)
1484 // events should be captured first
1485 wxASSERT( mpCaputesInput
!= NULL
);
1487 mpCaputesInput
= NULL
;
1490 void wxFrameLayout::CaptureEventsForPane( cbDockPane
* toPane
)
1492 // cannot capture events twice (without releasing)
1493 wxASSERT( mpPaneInFocus
== NULL
);
1495 mpFrame
->CaptureMouse();
1497 mpPaneInFocus
= toPane
;
1500 void wxFrameLayout::ReleaseEventsFromPane( cbDockPane
* fromPane
)
1502 // cannot release events without capturing them
1503 wxASSERT( mpPaneInFocus
!= NULL
);
1505 mpFrame
->ReleaseMouse();
1507 mpPaneInFocus
= NULL
;
1510 cbPluginBase
& wxFrameLayout::GetTopPlugin()
1514 PushDefaultPlugins(); // automatic configuration
1516 return *mpTopPlugin
;
1519 void wxFrameLayout::SetTopPlugin( cbPluginBase
* pPlugin
)
1521 mpTopPlugin
= pPlugin
;
1524 bool wxFrameLayout::HasTopPlugin()
1526 return ( mpTopPlugin
!= NULL
);
1529 void wxFrameLayout::PushPlugin( cbPluginBase
* pPlugin
)
1533 mpTopPlugin
= pPlugin
;
1536 pPlugin
->SetNextHandler( mpTopPlugin
);
1538 mpTopPlugin
->SetPreviousHandler( pPlugin
);
1540 mpTopPlugin
= pPlugin
;
1543 mpTopPlugin
->OnInitPlugin(); // notification
1546 void wxFrameLayout::PopPlugin()
1548 wxASSERT( mpTopPlugin
); // DBG:: at least one plugin should be present
1550 cbPluginBase
* pPopped
= mpTopPlugin
;
1552 mpTopPlugin
= (cbPluginBase
*)mpTopPlugin
->GetNextHandler();
1557 void wxFrameLayout::PopAllPlugins()
1559 while( mpTopPlugin
) PopPlugin();
1562 void wxFrameLayout::PushDefaultPlugins()
1564 // FIXME:: to much of the stuff for the default...
1566 AddPlugin( CLASSINFO( cbSimpleCustomizationPlugin
) );
1567 AddPlugin( CLASSINFO( cbRowLayoutPlugin
) );
1568 AddPlugin( CLASSINFO( cbBarDragPlugin
) );
1569 AddPlugin( CLASSINFO( cbPaneDrawPlugin
) );
1570 AddPlugin( CLASSINFO( cbAntiflickerPlugin
) );
1573 void wxFrameLayout::AddPlugin( wxClassInfo
* pPlInfo
, int paneMask
)
1575 if ( FindPlugin ( pPlInfo
) ) return; // same type of plugin cannot be added twice
1577 cbPluginBase
* pObj
= (cbPluginBase
*)pPlInfo
->CreateObject();
1579 wxASSERT(pObj
); // DBG:: plugin's class should be dynamic
1581 pObj
->mPaneMask
= paneMask
;
1582 pObj
->mpLayout
= this;
1587 void wxFrameLayout::AddPluginBefore( wxClassInfo
* pNextPlInfo
, wxClassInfo
* pPlInfo
,
1590 wxASSERT( pNextPlInfo
!= pPlInfo
); // DBG:: no sence
1592 cbPluginBase
* pNextPl
= FindPlugin( pNextPlInfo
);
1596 AddPlugin( pPlInfo
, paneMask
);
1601 // remove existing one if present
1603 cbPluginBase
* pExistingPl
= FindPlugin( pPlInfo
);
1605 if ( pExistingPl
) RemovePlugin( pPlInfo
);
1607 // create an instance
1609 cbPluginBase
* pNewPl
= (cbPluginBase
*)pPlInfo
->CreateObject();
1611 wxASSERT(pNewPl
); // DBG:: plugin's class should be dynamic
1613 // insert it to the chain
1615 if ( pNextPl
->GetPreviousHandler() )
1617 pNextPl
->GetPreviousHandler()->SetNextHandler( pNewPl
);
1619 mpTopPlugin
= pNewPl
;
1621 pNewPl
->SetNextHandler( pNextPl
);
1623 pNewPl
->SetPreviousHandler( pNextPl
->GetPreviousHandler() );
1625 pNextPl
->SetPreviousHandler( pNewPl
);
1629 pNewPl
->mPaneMask
= paneMask
;
1630 pNewPl
->mpLayout
= this;
1632 pNewPl
->OnInitPlugin();
1635 void wxFrameLayout::RemovePlugin( wxClassInfo
* pPlInfo
)
1637 cbPluginBase
* pPlugin
= FindPlugin( pPlInfo
);
1639 if ( !pPlugin
) return; // it's OK to remove not-existing plugin ;-)
1641 if ( pPlugin
->GetPreviousHandler() == NULL
)
1643 mpTopPlugin
= (cbPluginBase
*)pPlugin
->GetNextHandler();
1648 cbPluginBase
* wxFrameLayout::FindPlugin( wxClassInfo
* pPlInfo
)
1650 cbPluginBase
*pCur
= mpTopPlugin
;
1654 // NOTE:: it might appear usefull matching plugin
1655 // classes "polymorphically":
1657 if ( pCur
->GetClassInfo()->IsKindOf( pPlInfo
) )
1661 pCur
= (cbPluginBase
*)pCur
->GetNextHandler();
1667 /***** Implementation for class cbUpdateMgrData *****/
1669 IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData
, wxObject
)
1671 cbUpdateMgrData::cbUpdateMgrData()
1673 : mPrevBounds( -1,-1,0,0 ),
1674 mIsDirty( TRUE
) // inidicate initial change
1677 void cbUpdateMgrData::StoreItemState( const wxRect
& boundsInParent
)
1679 mPrevBounds
= boundsInParent
;
1682 void cbUpdateMgrData::SetDirty( bool isDirty
)
1687 void cbUpdateMgrData::SetCustomData( wxObject
* pCustomData
)
1689 mpCustomData
= pCustomData
;
1692 /***** Implementation for class cbDockPane *****/
1694 void wxBarIterator::Reset()
1696 mpRow
= ( mpRows
->Count() ) ? (*mpRows
)[0] : NULL
;
1700 wxBarIterator::wxBarIterator( RowArrayT
& rows
)
1709 bool wxBarIterator::Next()
1714 mpBar
= mpBar
->mpNext
;
1717 if ( mpRow
->mBars
.GetCount() == 0 )
1722 mpBar
= mpRow
->mBars
[0];
1727 // skip to the next row
1729 mpRow
= mpRow
->mpNext
;
1733 mpBar
= mpRow
->mBars
[0];
1744 cbBarInfo
& wxBarIterator::BarInfo()
1749 cbRowInfo
& wxBarIterator::RowInfo()
1754 /***** Implementation for class cbBarDimHandlerBase *****/
1756 IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase
, wxObject
)
1758 cbBarDimHandlerBase::cbBarDimHandlerBase()
1762 void cbBarDimHandlerBase::AddRef()
1767 void cbBarDimHandlerBase::RemoveRef()
1769 if ( --mRefCount
<= 0 ) delete this;
1772 /***** Implementation for class cbDimInfo *****/
1774 IMPLEMENT_DYNAMIC_CLASS( cbDimInfo
, wxObject
)
1776 cbDimInfo::cbDimInfo()
1784 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1789 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1793 cbDimInfo::cbDimInfo( cbBarDimHandlerBase
* pDimHandler
,
1798 mIsFixed ( isFixed
),
1800 mpHandler( pDimHandler
)
1804 int vtad
= *((int*)mpHandler
);
1805 mpHandler
->AddRef();
1808 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1813 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1817 cbDimInfo::cbDimInfo( int dh_x
, int dh_y
,
1825 cbBarDimHandlerBase
* pDimHandler
1827 : mHorizGap ( horizGap
),
1828 mVertGap ( vertGap
),
1829 mIsFixed ( isFixed
),
1830 mpHandler( pDimHandler
)
1834 int vtad
= *((int*)mpHandler
);
1835 mpHandler
->AddRef();
1839 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= dh_x
;
1840 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= dh_y
;
1841 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= dv_x
;
1842 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= dv_y
;
1843 mSizes
[wxCBAR_FLOATING
].x
= f_x
;
1844 mSizes
[wxCBAR_FLOATING
].y
= f_y
;
1847 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1849 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1852 cbDimInfo::~cbDimInfo()
1856 mpHandler
->RemoveRef();
1859 const cbDimInfo
& cbDimInfo::operator=( cbDimInfo
& other
)
1861 if ( this == &other
) return *this;
1863 for( int i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1865 mSizes
[i
] = other
.mSizes
[i
];
1867 mIsFixed
= other
.mIsFixed
;
1868 mpHandler
= other
.mpHandler
;
1870 mVertGap
= other
.mVertGap
;
1871 mHorizGap
= other
.mHorizGap
;
1875 mpHandler
->AddRef();
1880 /***** Implementation for structure cbCommonPaneProperties *****/
1882 IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties
, wxObject
)
1884 cbCommonPaneProperties::cbCommonPaneProperties(void)
1886 : mRealTimeUpdatesOn ( TRUE
),
1887 mOutOfPaneDragOn ( TRUE
),
1888 mExactDockPredictionOn( FALSE
),
1889 mNonDestructFirctionOn( FALSE
),
1890 mShow3DPaneBorderOn ( TRUE
),
1891 mBarFloatingOn ( FALSE
),
1892 mRowProportionsOn ( FALSE
),
1893 mColProportionsOn ( TRUE
),
1894 mBarCollapseIconsOn ( FALSE
),
1895 mBarDragHintsOn ( FALSE
),
1897 mMinCBarDim( 16, 16 ),
1898 mResizeHandleSize( 4 )
1901 /***** Implementation for class cbRowInfo *****/
1903 IMPLEMENT_DYNAMIC_CLASS( cbRowInfo
, wxObject
)
1905 cbRowInfo::cbRowInfo(void)
1909 mNotFixedBarsCnt( FALSE
),
1910 mpExpandedBar ( NULL
)
1913 cbRowInfo::~cbRowInfo()
1915 // nothing! all bars are removed using global bar
1916 // list in wxFrameLayout class
1919 /***** Implementation for class cbBarInfo *****/
1921 IMPLEMENT_DYNAMIC_CLASS( cbBarInfo
, wxObject
)
1923 cbBarInfo::cbBarInfo(void)
1931 cbBarInfo::~cbBarInfo()
1936 /***** Implementation for class cbDockPane *****/
1938 IMPLEMENT_DYNAMIC_CLASS( cbDockPane
, wxObject
)
1940 // FIXME:: how to eliminate these cut&pasted constructors?
1942 cbDockPane::cbDockPane(void)
1945 mPaneWidth ( 32768 ), // fake-up very large pane dims,
1946 // since the real dimensions of the pane may not
1947 // be known, while inserting bars initially
1948 mPaneHeight( 32768 ),
1950 mpStoredRow( NULL
),
1957 cbDockPane::cbDockPane( int alignment
, wxFrameLayout
* pPanel
)
1959 : mpLayout ( pPanel
),
1960 mPaneWidth ( 32768 ), // fake-up very large pane dims,
1961 // since the real dimensions of the pane may not
1962 // be known, while inserting bars initially
1963 mPaneHeight( 32768 ),
1964 mAlignment ( alignment
),
1965 mpStoredRow( NULL
),
1973 cbDockPane::~cbDockPane()
1975 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
1979 mRowShapeData
.DeleteContents( TRUE
);
1981 // NOTE:: control bar infromation structures are cleaned-up
1982 // in wxFrameLayout's destructor, using global control-bar list
1985 void cbDockPane::SetMargins( int top
, int bottom
, int left
, int right
)
1988 mBottomMargin
= bottom
;
1990 mRightMargin
= right
;
1993 /*** helpers of cbDockPane ***/
1995 void cbDockPane::PaintBarDecorations( cbBarInfo
* pBar
, wxDC
& dc
)
1997 cbDrawBarDecorEvent
evt( pBar
, dc
, this );
1999 mpLayout
->FirePluginEvent( evt
);
2002 void cbDockPane::PaintBarHandles( cbBarInfo
* pBar
, wxDC
& dc
)
2004 cbDrawBarHandlesEvent
evt( pBar
, dc
, this );
2006 mpLayout
->FirePluginEvent( evt
);
2009 void cbDockPane::PaintBar( cbBarInfo
* pBar
, wxDC
& dc
)
2011 PaintBarDecorations( pBar
, dc
);
2012 PaintBarHandles( pBar
, dc
);
2015 void cbDockPane::PaintRowHandles( cbRowInfo
* pRow
, wxDC
& dc
)
2017 cbDrawRowHandlesEvent
evt( pRow
, dc
, this );
2019 mpLayout
->FirePluginEvent( evt
);
2021 cbDrawRowDecorEvent
evt1( pRow
, dc
, this );
2023 mpLayout
->FirePluginEvent( evt1
);
2026 void cbDockPane::PaintRowBackground ( cbRowInfo
* pRow
, wxDC
& dc
)
2028 cbDrawRowBkGroundEvent
evt( pRow
, dc
, this );
2030 mpLayout
->FirePluginEvent( evt
);
2033 void cbDockPane::PaintRowDecorations( cbRowInfo
* pRow
, wxDC
& dc
)
2037 // decorations first
2038 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2040 PaintBarDecorations( pRow
->mBars
[i
], dc
);
2042 // then handles if present
2043 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2045 PaintBarHandles( pRow
->mBars
[i
], dc
);
2048 void cbDockPane::PaintRow( cbRowInfo
* pRow
, wxDC
& dc
)
2050 PaintRowBackground ( pRow
, dc
);
2051 PaintRowDecorations( pRow
, dc
);
2052 PaintRowHandles ( pRow
, dc
);
2055 void cbDockPane::PaintPaneBackground( wxDC
& dc
)
2057 cbDrawPaneBkGroundEvent
evt( dc
, this );
2059 mpLayout
->FirePluginEvent( evt
);
2062 void cbDockPane::PaintPaneDecorations( wxDC
& dc
)
2064 cbDrawPaneDecorEvent
evt( dc
, this );
2066 mpLayout
->FirePluginEvent( evt
);
2069 void cbDockPane::PaintPane( wxDC
& dc
)
2071 PaintPaneBackground( dc
);
2075 // first decorations
2076 for( i
= 0; i
!= mRows
.Count(); ++i
)
2078 PaintRowBackground( mRows
[i
], dc
);
2079 PaintRowDecorations( mRows
[i
], dc
);
2083 for( i
= 0; i
!= mRows
.Count(); ++i
)
2085 PaintRowHandles( mRows
[i
], dc
);
2088 PaintPaneDecorations( dc
);
2091 void cbDockPane::SizeBar( cbBarInfo
* pBar
)
2093 cbSizeBarWndEvent
evt( pBar
, this );
2095 mpLayout
->FirePluginEvent( evt
);
2099 void cbDockPane::SizeRowObjects( cbRowInfo
* pRow
)
2101 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2103 SizeBar( pRow
->mBars
[i
] );
2106 void cbDockPane::SizePaneObjects()
2108 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2110 SizeRowObjects( mRows
[i
] );
2113 wxDC
* cbDockPane::StartDrawInArea( const wxRect
& area
)
2117 cbStartDrawInAreaEvent
evt( area
, &pDc
, this );
2119 mpLayout
->FirePluginEvent( evt
);
2124 void cbDockPane::FinishDrawInArea( const wxRect
& area
)
2126 cbFinishDrawInAreaEvent
evt( area
, this );
2128 mpLayout
->FirePluginEvent( evt
);
2131 bool cbDockPane::IsFixedSize( cbBarInfo
* pInfo
)
2133 return ( pInfo
->mDimInfo
.mIsFixed
);
2136 int cbDockPane::GetNotFixedBarsCount( cbRowInfo
* pRow
)
2140 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2142 if ( !pRow
->mBars
[i
]->IsFixed() ) ++cnt
;
2147 void cbDockPane::RemoveBar( cbBarInfo
* pBar
)
2149 bool needsRestoring
= mProps
.mNonDestructFirctionOn
&&
2150 mpStoredRow
== pBar
->mpRow
;
2152 cbRemoveBarEvent
evt( pBar
, this );
2154 mpLayout
->FirePluginEvent( evt
);
2156 if ( needsRestoring
)
2158 SetRowShapeData( mpStoredRow
, &mRowShapeData
);
2164 void cbDockPane::SyncRowFlags( cbRowInfo
* pRow
)
2166 // setup mHasOnlyFixedBars flag for the row information
2167 pRow
->mHasOnlyFixedBars
= TRUE
;
2169 pRow
->mNotFixedBarsCnt
= 0;
2171 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2173 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2177 if ( !bar
.IsFixed() )
2179 pRow
->mHasOnlyFixedBars
= FALSE
;
2180 ++pRow
->mNotFixedBarsCnt
;
2185 void cbDockPane::FrameToPane( long* x
, long* y
)
2190 if ( mAlignment
== wxTOP
||
2191 mAlignment
== wxBOTTOM
2194 *x
-= mBoundsInParent
.x
;
2195 *y
-= mBoundsInParent
.y
;
2199 int rx
= *x
, ry
= *y
;
2201 *x
= ry
- mBoundsInParent
.y
;
2203 *y
= rx
- mBoundsInParent
.x
;
2207 void cbDockPane::PaneToFrame( long* x
, long* y
)
2209 if ( mAlignment
== wxTOP
||
2210 mAlignment
== wxBOTTOM
2213 *x
+= mBoundsInParent
.x
;
2214 *y
+= mBoundsInParent
.y
;
2218 int rx
= *x
, ry
= *y
;
2220 *x
= ry
+ mBoundsInParent
.x
;
2222 *y
= mBoundsInParent
.y
+ rx
;
2229 void cbDockPane::FrameToPane( wxRect
* pRect
)
2231 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2232 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2233 pRect
->y
+ pRect
->height
);
2235 FrameToPane( &upperLeft
.x
, &upperLeft
.y
);
2236 FrameToPane( &lowerRight
.x
, &lowerRight
.y
);
2238 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2239 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2241 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2242 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2245 void cbDockPane::PaneToFrame( wxRect
* pRect
)
2247 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2248 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2249 pRect
->y
+ pRect
->height
);
2251 PaneToFrame( &upperLeft
.x
, &upperLeft
.y
);
2252 PaneToFrame( &lowerRight
.x
, &lowerRight
.y
);
2254 //wxRect newRect = wxRect( upperLeft, lowerRight );
2256 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2257 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2259 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2260 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2263 int cbDockPane::GetRowAt( int paneY
)
2265 if ( paneY
< 0 ) return -1;
2271 for( ; i
!= mRows
.Count(); ++i
)
2273 int rowHeight
= mRows
[i
]->mRowHeight
;
2275 int third
= rowHeight
/3;
2277 if ( paneY
>= curY
&& paneY
< curY
+ third
)
2280 if ( paneY
>= curY
+ third
&& paneY
< curY
+ rowHeight
- third
)
2289 int cbDockPane::GetRowAt( int upperY
, int lowerY
)
2293 int range = lowerY - upperY;
2294 int oneThird = range / 3;
2296 wxNode* pRow = mRows.First();
2300 if ( lowerY <= 0 ) return -1;
2304 int rowHeight = GetRowHeight( (wxList*)pRow->Data() );
2306 if ( upperY >= curY &&
2307 lowerY < curY ) return row;
2309 if ( upperY <= curY &&
2311 curY - upperY >= oneThird ) return row-1;
2313 if ( ( upperY < curY + rowHeight &&
2314 lowerY >= curY + rowHeight &&
2315 curY + rowHeight - lowerY >= oneThird )
2319 if ( lowerY <= curY + rowHeight ) return row;
2323 pRow = pRow->Next();
2327 int mid
= upperY
+ (lowerY
- upperY
)/2;
2329 if ( mid
< 0 ) return -1;
2334 for( ; i
!= mRows
.Count(); ++i
)
2336 int rowHeight
= mRows
[i
]->mRowHeight
;
2338 if ( mid
>= curY
&& mid
< curY
+ rowHeight
) return i
;
2346 int cbDockPane::GetRowY( cbRowInfo
* pRow
)
2350 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2352 if ( mRows
[i
] == pRow
) break;
2354 curY
+= mRows
[i
]->mRowHeight
;
2360 bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo
* pRow
)
2362 while ( pRow
->mpPrev
)
2364 pRow
= pRow
->mpPrev
;
2366 if ( pRow
->mHasOnlyFixedBars
)
2374 bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo
* pRow
)
2376 while( pRow
->mpNext
)
2378 pRow
= pRow
->mpNext
;
2380 if ( pRow
->mHasOnlyFixedBars
)
2388 bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo
* pBar
)
2390 while( pBar
->mpPrev
)
2392 pBar
= pBar
->mpPrev
;
2394 if ( pBar
->IsFixed() )
2402 bool cbDockPane::HasNotFixedBarsRight( cbBarInfo
* pBar
)
2404 while( pBar
->mpNext
)
2406 pBar
= pBar
->mpNext
;
2408 if ( pBar
->IsFixed() )
2416 void cbDockPane::CalcLenghtRatios( cbRowInfo
* pInRow
)
2422 // clac current-maximal-total-length of all maximized bars
2424 for( i
= 0; i
!= pInRow
->mBars
.GetCount(); ++i
)
2426 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2428 if ( !bar
.IsFixed() )
2430 totalWidth
+= bar
.mBounds
.width
;
2433 // set up persentages of occupied space for each maximized bar
2435 for( i
= 0; i
!= pInRow
->mBars
.Count(); ++i
)
2437 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2439 if ( !bar
.IsFixed() )
2441 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalWidth
);
2445 void cbDockPane::RecalcRowLayout( cbRowInfo
* pRow
)
2447 cbLayoutRowEvent
evt( pRow
, this );
2449 mpLayout
->FirePluginEvent( evt
);
2452 void cbDockPane::ExpandBar( cbBarInfo
* pBar
)
2454 mpLayout
->GetUpdatesManager().OnStartChanges();
2456 if ( !pBar
->mpRow
->mpExpandedBar
)
2458 // save ratios only when there arent any bars expanded yet
2460 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2463 ratios
.Alloc( pBar
->mpRow
->mNotFixedBarsCnt
);
2465 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2469 if ( !pCur
->IsFixed() )
2472 ratios
[ ratios
.GetCount() - 1 ] = pCur
->mLenRatio
;
2475 pCur
= pCur
->mpNext
;
2479 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2483 pCur
->mLenRatio
= 0.0; // minimize the rest
2485 pCur
= pCur
->mpNext
;
2488 pBar
->mLenRatio
= 1.0; // 100%
2489 pBar
->mBounds
.width
= 0;
2491 pBar
->mpRow
->mpExpandedBar
= pBar
;
2493 mpLayout
->RecalcLayout( FALSE
);
2495 mpLayout
->GetUpdatesManager().OnFinishChanges();
2496 mpLayout
->GetUpdatesManager().UpdateNow();
2499 void cbDockPane::ContractBar( cbBarInfo
* pBar
)
2501 mpLayout
->GetUpdatesManager().OnStartChanges();
2503 double ratio
= 1.0/ double( pBar
->mpRow
->mNotFixedBarsCnt
);
2505 // restore ratios which were present before expansion
2507 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2509 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2515 if ( !pCur
->IsFixed() )
2517 pCur
->mLenRatio
= ratios
[i
];
2521 pCur
= pCur
->mpNext
;
2527 pBar
->mpRow
->mpExpandedBar
= NULL
;
2529 mpLayout
->RecalcLayout( FALSE
);
2531 mpLayout
->GetUpdatesManager().OnFinishChanges();
2532 mpLayout
->GetUpdatesManager().UpdateNow();
2535 void cbDockPane::InitLinksForRow( cbRowInfo
* pRow
)
2537 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2539 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2545 bar
.mpPrev
= pRow
->mBars
[i
-1];
2547 if ( i
== pRow
->mBars
.Count() - 1 )
2551 bar
.mpNext
= pRow
->mBars
[i
+1];
2555 void cbDockPane::InitLinksForRows()
2557 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2559 cbRowInfo
& row
= *mRows
[i
];
2565 row
.mpPrev
= mRows
[i
-1];
2567 if ( i
== mRows
.Count() - 1 )
2571 row
.mpNext
= mRows
[i
+1];
2575 void cbDockPane::DoInsertBar( cbBarInfo
* pBar
, int rowNo
)
2577 cbRowInfo
* pRow
= NULL
;
2579 if ( rowNo
== -1 || rowNo
>= (int)mRows
.Count() )
2581 pRow
= new cbRowInfo();
2583 if ( rowNo
== -1 && mRows
.Count() )
2585 mRows
.Insert( pRow
, 0 );
2593 pRow
= mRows
[rowNo
];
2595 if ( mProps
.mNonDestructFirctionOn
== TRUE
)
2597 // store original shape of the row (before the bar is inserted)
2601 GetRowShapeData( mpStoredRow
, &mRowShapeData
);
2605 if ( pRow
->mBars
.Count() )
2607 pRow
->mpExpandedBar
= NULL
;
2609 cbInsertBarEvent
insEvt( pBar
, pRow
, this );
2611 mpLayout
->FirePluginEvent( insEvt
);
2613 mpLayout
->GetUpdatesManager().OnRowWillChange( pRow
, this );
2616 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
, const wxRect
& atRect
)
2618 wxRect rect
= atRect
;
2619 FrameToPane( &rect
);
2621 pBarInfo
->mBounds
.x
= rect
.x
;
2622 pBarInfo
->mBounds
.width
= rect
.width
;
2623 pBarInfo
->mBounds
.height
= rect
.height
;
2625 int row
= GetRowAt( rect
.y
, rect
.y
+ rect
.height
);
2627 DoInsertBar( pBarInfo
, row
);
2630 void cbDockPane::InsertBar( cbBarInfo
* pBar
, cbRowInfo
* pIntoRow
)
2632 cbInsertBarEvent
insEvt( pBar
, pIntoRow
, this );
2634 mpLayout
->FirePluginEvent( insEvt
);
2636 mpLayout
->GetUpdatesManager().OnRowWillChange( pIntoRow
, this );
2639 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
)
2641 // set transient properties
2643 pBarInfo
->mpRow
= NULL
;
2644 pBarInfo
->mHasLeftHandle
= FALSE
;
2645 pBarInfo
->mHasRightHandle
= FALSE
;
2646 pBarInfo
->mLenRatio
= 0.0;
2648 // set preferred bar demensions, according to the state in which
2649 // the bar is being inserted
2651 pBarInfo
->mBounds
.width
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].x
;
2652 pBarInfo
->mBounds
.height
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].y
;
2654 DoInsertBar( pBarInfo
, pBarInfo
->mRowNo
);
2657 void cbDockPane::RemoveRow( cbRowInfo
* pRow
)
2659 // first, hide all bar-windows in the removed row
2660 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2662 if ( pRow
->mBars
[i
]->mpBarWnd
)
2664 pRow
->mBars
[i
]->mpBarWnd
->Show( FALSE
);
2666 mRows
.Remove( pRow
);
2668 pRow
->mUMgrData
.SetDirty(TRUE
);
2671 void cbDockPane::InsertRow( cbRowInfo
* pRow
, cbRowInfo
* pBeforeRow
)
2677 mRows
.Insert( pRow
, mRows
.Index( pBeforeRow
) );
2681 pRow
->mUMgrData
.SetDirty(TRUE
);
2683 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2685 pRow
->mBars
[i
]->mUMgrData
.SetDirty( TRUE
);
2687 SyncRowFlags( pRow
);
2690 void cbDockPane::SetPaneWidth(int width
)
2692 if ( IsHorizontal() )
2694 mPaneWidth
= width
- mLeftMargin
- mRightMargin
;
2696 mPaneWidth
= width
- mTopMargin
- mBottomMargin
;
2700 void cbDockPane::SetBoundsInParent( const wxRect
& rect
)
2703 mBoundsInParent
= rect
;
2705 // set pane dimensions in local coordinates
2707 if ( IsHorizontal() )
2709 mPaneWidth
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2710 mPaneHeight
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2714 mPaneWidth
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2715 mPaneHeight
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2718 // convert bounding rectangles of all pane items into parent frame's coordinates
2720 wxBarIterator
i( mRows
);
2722 wxRect noMarginsRect
= mBoundsInParent
;
2724 noMarginsRect
.x
+= mLeftMargin
;
2725 noMarginsRect
.y
+= mTopMargin
;
2726 noMarginsRect
.width
-= ( mLeftMargin
+ mRightMargin
);
2727 noMarginsRect
.height
-= ( mTopMargin
+ mBottomMargin
);
2729 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2731 if ( mBoundsInParent
.width
< 0 ||
2732 mBoundsInParent
.height
< 0 )
2734 hide_rect( mBoundsInParent
);
2736 if ( noMarginsRect
.width
< 0 ||
2737 noMarginsRect
.height
< 0 )
2739 hide_rect( noMarginsRect
);
2741 // calculate mBoundsInParent for each item in the pane
2745 cbBarInfo
& bar
= i
.BarInfo();
2747 cbRowInfo
* pRowInfo
= bar
.mpRow
;
2749 // set up row info, if this is first bar in the row
2751 if ( pRowInfo
&& bar
.mpPrev
== NULL
)
2753 pRowInfo
->mBoundsInParent
.y
= pRowInfo
->mRowY
;
2754 pRowInfo
->mBoundsInParent
.x
= 0;
2755 pRowInfo
->mBoundsInParent
.width
= mPaneWidth
;
2756 pRowInfo
->mBoundsInParent
.height
= pRowInfo
->mRowHeight
;
2758 PaneToFrame( &pRowInfo
->mBoundsInParent
);
2760 clip_rect_against_rect( pRowInfo
->mBoundsInParent
, noMarginsRect
);
2763 wxRect bounds
= bar
.mBounds
;
2765 // exclude dimensions of handles, when calculating
2766 // bar's bounds in parent (i.e. "visual bounds")
2768 if ( bar
.mHasLeftHandle
)
2770 bounds
.x
+= mProps
.mResizeHandleSize
;
2771 bounds
.width
-= mProps
.mResizeHandleSize
;
2774 if ( bar
.mHasRightHandle
)
2776 bounds
.width
-= mProps
.mResizeHandleSize
;
2778 PaneToFrame( &bounds
);
2780 clip_rect_against_rect( bounds
, noMarginsRect
);
2782 bar
.mBoundsInParent
= bounds
;
2786 bool cbDockPane::BarPresent( cbBarInfo
* pBar
)
2788 wxBarIterator
iter( mRows
);
2790 while( iter
.Next() )
2792 if ( &iter
.BarInfo() == pBar
) return TRUE
;
2797 cbRowInfo
* cbDockPane::GetRow( int row
)
2799 if ( row
>= (int)mRows
.Count() ) return NULL
;
2801 return mRows
[ row
];
2804 int cbDockPane::GetRowIndex( cbRowInfo
* pRow
)
2806 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2808 if ( mRows
[i
] == pRow
) return i
;
2810 wxASSERT(0); // DBG:: row should be present
2815 int cbDockPane::GetPaneHeight()
2817 // first, recalculate row heights and the Y-positions
2819 cbLayoutRowsEvent
evt( this );
2820 mpLayout
->FirePluginEvent( evt
);
2824 if ( IsHorizontal() )
2826 height
+= mTopMargin
+ mBottomMargin
;
2828 height
+= mLeftMargin
+ mRightMargin
;
2830 int count
= mRows
.Count();
2834 height
+= mRows
[count
-1]->mRowY
+ mRows
[count
-1]->mRowHeight
;
2839 int cbDockPane::GetAlignment()
2844 bool cbDockPane::MatchesMask( int paneMask
)
2848 // FIXME:: use array instead of switch()
2852 case wxTOP
: thisMask
= wxTOP_PANE
; break;
2853 case wxBOTTOM
: thisMask
= wxBOTTOM_PANE
;break;
2854 case wxLEFT
: thisMask
= wxLEFT_PANE
; break;
2855 case wxRIGHT
: thisMask
= wxRIGHT_PANE
; break;
2857 default: wxASSERT(0); // DBG:: bogous alignment type
2860 return ( thisMask
& paneMask
);
2863 void cbDockPane::RecalcLayout()
2865 // first, reposition rows and items vertically
2867 cbLayoutRowsEvent
evt( this );
2868 mpLayout
->FirePluginEvent( evt
);
2870 // then horizontally in each row
2872 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2874 RecalcRowLayout( mRows
[i
] );
2877 int cbDockPane::GetDockingState()
2879 if ( mAlignment
== wxTOP
||
2880 mAlignment
== wxBOTTOM
)
2882 return wxCBAR_DOCKED_HORIZONTALLY
;
2885 return wxCBAR_DOCKED_VERTICALLY
;
2888 inline bool cbDockPane::HasPoint( const wxPoint
& pos
, int x
, int y
,
2889 int width
, int height
)
2891 return ( pos
.x
>= x
&&
2893 pos
.x
< x
+ width
&&
2894 pos
.y
< y
+ height
);
2897 int cbDockPane::HitTestPaneItems( const wxPoint
& pos
,
2905 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2907 cbRowInfo
& row
= *mRows
[i
];
2911 // hit-test handles of the row, if present
2913 if ( row
.mHasUpperHandle
)
2915 if ( HasPoint( pos
, 0, row
.mRowY
,
2916 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
2918 return CB_UPPER_ROW_HANDLE_HITTED
;
2921 if ( row
.mHasLowerHandle
)
2923 if ( HasPoint( pos
, 0, row
.mRowY
+ row
.mRowHeight
- mProps
.mResizeHandleSize
,
2924 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
2926 return CB_LOWER_ROW_HANDLE_HITTED
;
2929 // hit-test bar handles and bar content
2931 for( size_t k
= 0; k
!= row
.mBars
.Count(); ++k
)
2933 cbBarInfo
& bar
= *row
.mBars
[k
];
2934 wxRect
& bounds
= bar
.mBounds
;
2938 if ( bar
.mHasLeftHandle
)
2940 if ( HasPoint( pos
, bounds
.x
, bounds
.y
,
2941 mProps
.mResizeHandleSize
, bounds
.height
) )
2943 return CB_LEFT_BAR_HANDLE_HITTED
;
2946 if ( bar
.mHasRightHandle
)
2948 if ( HasPoint( pos
, bounds
.x
+ bounds
.width
- mProps
.mResizeHandleSize
, bounds
.y
,
2949 mProps
.mResizeHandleSize
, bounds
.height
) )
2951 return CB_RIGHT_BAR_HANDLE_HITTED
;
2954 if ( HasPoint( pos
, bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
) )
2956 return CB_BAR_CONTENT_HITTED
;
2958 } // hit-test next bar
2962 return CB_NO_ITEMS_HITTED
;
2965 void cbDockPane::GetBarResizeRange( cbBarInfo
* pBar
, int* from
, int *till
,
2966 bool forLeftHandle
)
2968 cbBarInfo
* pGivenBar
= pBar
;
2972 // calc unavailable space from the left
2974 while( pBar
->mpPrev
)
2976 pBar
= pBar
->mpPrev
;
2978 if ( !pBar
->IsFixed() ) notFree
+= mProps
.mMinCBarDim
.x
;
2979 else notFree
+= pBar
->mBounds
.width
;
2988 // calc unavailable space from the right
2990 while( pBar
->mpNext
)
2992 pBar
= pBar
->mpNext
;
2994 if ( pBar
->mBounds
.x
>= mPaneWidth
) break;
2996 // treat not-fixed bars as minimized
2998 if ( !pBar
->IsFixed() )
3000 notFree
+= mProps
.mMinCBarDim
.x
;
3003 if ( pBar
->mBounds
.x
+ pBar
->mBounds
.width
>= mPaneWidth
)
3005 notFree
+= mPaneWidth
- pBar
->mBounds
.x
;
3009 notFree
+= pBar
->mBounds
.width
;
3014 *till
= mPaneWidth
- notFree
;
3016 // do not let resizing totally deform the bar itself
3018 if ( forLeftHandle
)
3020 (*till
) -= mProps
.mMinCBarDim
.x
;
3023 (*from
) += mProps
.mMinCBarDim
.x
;
3026 int cbDockPane::GetMinimalRowHeight( cbRowInfo
* pRow
)
3028 int height
= mProps
.mMinCBarDim
.y
;
3030 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3032 if ( pRow
->mBars
[i
]->IsFixed() )
3034 height
= wxMax( height
, pRow
->mBars
[i
]->mBounds
.height
);
3036 if ( pRow
->mHasUpperHandle
)
3038 height
+= mProps
.mResizeHandleSize
;
3040 if ( pRow
->mHasLowerHandle
)
3042 height
+= mProps
.mResizeHandleSize
;
3047 void cbDockPane::SetRowHeight( cbRowInfo
* pRow
, int newHeight
)
3049 if ( pRow
->mHasUpperHandle
)
3051 newHeight
-= mProps
.mResizeHandleSize
;
3053 if ( pRow
->mHasLowerHandle
)
3055 newHeight
-= mProps
.mResizeHandleSize
;
3057 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3059 if ( !pRow
->mBars
[i
]->IsFixed() )
3061 pRow
->mBars
[i
]->mBounds
.height
= newHeight
;
3064 void cbDockPane::GetRowResizeRange( cbRowInfo
* pRow
, int* from
, int* till
,
3065 bool forUpperHandle
)
3067 cbRowInfo
* pGivenRow
= pRow
;
3069 // calc unavailable space from above
3073 while( pRow
->mpPrev
)
3075 pRow
= pRow
->mpPrev
;
3077 notFree
+= GetMinimalRowHeight( pRow
);
3083 // allow accupy the client window space by resizing pane rows
3084 if ( mAlignment
== wxBOTTOM
)
3086 *from
-= mpLayout
->GetClientHeight();
3088 if ( mAlignment
== wxRIGHT
)
3090 *from
-= mpLayout
->GetClientWidth();
3092 // calc unavailable space from below
3098 while( pRow
->mpNext
)
3100 pRow
= pRow
->mpNext
;
3102 notFree
+= GetMinimalRowHeight( pRow
);
3106 *till
= mPaneHeight
- notFree
;
3108 // allow adjustinig pane space vs. client window space by resizing pane row heights
3110 if ( mAlignment
== wxTOP
)
3112 *till
+= mpLayout
->GetClientHeight();
3114 if ( mAlignment
== wxLEFT
)
3116 *till
+= mpLayout
->GetClientWidth();
3118 // do not let the resizing of the row totally squeeze the row itself
3120 cbRowInfo
& row
= *pGivenRow
;
3122 if ( forUpperHandle
)
3124 *till
= row
.mRowY
+ row
.mRowHeight
- GetMinimalRowHeight( pGivenRow
);
3126 if ( row
.mHasUpperHandle
)
3128 *till
-= mProps
.mResizeHandleSize
;
3132 *from
+= GetMinimalRowHeight( pGivenRow
);
3134 if ( row
.mHasLowerHandle
)
3136 *from
-= mProps
.mResizeHandleSize
;
3140 void cbDockPane::ResizeRow( cbRowInfo
* pRow
, int ofs
,
3141 bool forUpperHandle
)
3143 cbResizeRowEvent
evt( pRow
, ofs
, forUpperHandle
, this );
3145 mpLayout
->FirePluginEvent( evt
);
3148 void cbDockPane::ResizeBar( cbBarInfo
* pBar
, int ofs
,
3149 bool forLeftHandle
)
3151 pBar
->mpRow
->mpExpandedBar
= NULL
;
3153 mpLayout
->GetUpdatesManager().OnStartChanges();
3155 wxRect
& bounds
= pBar
->mBounds
;
3157 if ( forLeftHandle
)
3159 // do not allow bar width become less then minimal
3160 if ( bounds
.x
+ ofs
> bounds
.x
+ bounds
.width
- mProps
.mMinCBarDim
.x
)
3162 bounds
.width
= mProps
.mMinCBarDim
.x
;
3168 bounds
.width
-= ofs
;
3173 // move bar left if necessary
3174 if ( bounds
.width
+ ofs
< mProps
.mMinCBarDim
.x
)
3176 bounds
.x
= bounds
.x
+ bounds
.width
+ ofs
- mProps
.mMinCBarDim
.x
;
3177 bounds
.width
= mProps
.mMinCBarDim
.x
;
3180 // resize right border only
3181 bounds
.width
+= ofs
;
3185 cbRowInfo
* pToRow
= pBar
->mpRow
;
3187 this->RemoveBar( pBar
);
3189 InsertBar( pBar
, pToRow
);
3191 mpLayout
->RecalcLayout(FALSE
);
3193 mpLayout
->GetUpdatesManager().OnFinishChanges();
3194 mpLayout
->GetUpdatesManager().UpdateNow();
3198 /*** row/bar resizing related methods ***/
3200 void cbDockPane::DrawVertHandle( wxDC
& dc
, int x
, int y
, int height
)
3202 int lower
= y
+ height
;
3204 dc
.SetPen( mpLayout
->mLightPen
);
3205 dc
.DrawLine( x
,y
, x
, lower
);
3207 dc
.SetPen( mpLayout
->mGrayPen
);
3208 for( int i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3211 dc
.DrawLine( x
,y
, x
, lower
);
3214 dc
.SetPen( mpLayout
->mDarkPen
);
3216 dc
.DrawLine( x
,y
, x
, lower
);
3218 dc
.SetPen( mpLayout
->mBlackPen
);
3220 dc
.DrawLine( x
,y
, x
, lower
);
3223 void cbDockPane::DrawHorizHandle( wxDC
& dc
, int x
, int y
, int width
)
3225 int right
= x
+ width
;
3227 dc
.SetPen( mpLayout
->mLightPen
);
3228 dc
.DrawLine( x
,y
, right
, y
);
3230 dc
.SetPen( mpLayout
->mGrayPen
);
3232 for( int i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3235 dc
.DrawLine( x
,y
, right
, y
);
3238 dc
.SetPen( mpLayout
->mDarkPen
);
3239 dc
.DrawLine( x
,y
, right
, ++y
);
3241 dc
.SetPen( mpLayout
->mBlackPen
);
3242 dc
.DrawLine( x
,y
, right
, ++y
);
3245 cbBarInfo
* cbDockPane::GetBarInfoByWindow( wxWindow
* pBarWnd
)
3247 wxBarIterator
i( mRows
);
3251 if ( i
.BarInfo().mpBarWnd
== pBarWnd
)
3253 return &i
.BarInfo();
3258 void cbDockPane::GetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3260 pLst
->DeleteContents( TRUE
);
3263 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3265 cbBarInfo
& bar
= *pRow
->mBars
[i
];
3267 cbBarShapeData
* pData
= new cbBarShapeData();
3269 pLst
->Append( (wxObject
*)pData
);
3271 pData
->mBounds
= bar
.mBounds
;
3272 pData
->mLenRatio
= bar
.mLenRatio
;
3276 void cbDockPane::SetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3278 if ( pLst
->First() == NULL
) return;
3280 wxNode
* pData
= pLst
->First();
3282 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3284 wxASSERT( pData
); // DBG::
3286 cbBarInfo
& bar
= *pRow
->mBars
[i
];;
3288 cbBarShapeData
& data
= *((cbBarShapeData
*)pData
->Data());
3290 bar
.mBounds
= data
.mBounds
;
3291 bar
.mLenRatio
= data
.mLenRatio
;
3293 pData
= pData
->Next();
3297 /***** Implementation for class cbUpdatesManagerBase *****/
3299 IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase
, wxObject
)
3301 /***** Implementation for class cbPluginBase *****/
3303 IMPLEMENT_ABSTRACT_CLASS( cbPluginBase
, wxEvtHandler
)
3305 cbPluginBase::~cbPluginBase()
3310 bool cbPluginBase::ProcessEvent(wxEvent
& event
)
3312 if ( mPaneMask
== wxALL_PANES
)
3314 return wxEvtHandler::ProcessEvent( event
);
3316 // extract mask info. from received event
3318 cbPluginEvent
& evt
= *( (cbPluginEvent
*)&event
);
3320 if ( evt
.mpPane
== 0 &&
3321 mPaneMask
== wxALL_PANES
)
3323 return wxEvtHandler::ProcessEvent( event
);
3327 switch ( evt
.mpPane
->mAlignment
)
3329 case wxTOP
: mask
= wxTOP_PANE
; break;
3330 case wxBOTTOM
: mask
= wxBOTTOM_PANE
;break;
3331 case wxLEFT
: mask
= wxLEFT_PANE
; break;
3332 case wxRIGHT
: mask
= wxRIGHT_PANE
; break;
3335 // if event's pane maks matches the plugin's mask
3337 if ( mPaneMask
& mask
)
3339 return wxEvtHandler::ProcessEvent( event
);
3341 // otherwise pass to the next handler if present
3343 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event
) )