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 ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
236 mLightPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHILIGHT
), 1, wxSOLID
),
237 mGrayPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
238 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID
),
239 mBorderPen( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
241 mpPaneInFocus( NULL
),
244 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT
),
246 mpTopPlugin ( NULL
),
247 mpCaputesInput( NULL
),
249 mCheckFocusWhenIdle( FALSE
),
250 mRecalcPending( TRUE
),
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 ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
268 mLightPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHILIGHT
), 1, wxSOLID
),
269 mGrayPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
270 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID
),
271 mBorderPen( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
), 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( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
) );
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( cbRowLayoutPlugin
) );
1567 AddPlugin( CLASSINFO( cbBarDragPlugin
) );
1568 AddPlugin( CLASSINFO( cbPaneDrawPlugin
) );
1571 void wxFrameLayout::AddPlugin( wxClassInfo
* pPlInfo
, int paneMask
)
1573 if ( FindPlugin ( pPlInfo
) ) return; // same type of plugin cannot be added twice
1575 cbPluginBase
* pObj
= (cbPluginBase
*)pPlInfo
->CreateObject();
1577 wxASSERT(pObj
); // DBG:: plugin's class should be dynamic
1579 pObj
->mPaneMask
= paneMask
;
1580 pObj
->mpLayout
= this;
1585 void wxFrameLayout::AddPluginBefore( wxClassInfo
* pNextPlInfo
, wxClassInfo
* pPlInfo
,
1588 wxASSERT( pNextPlInfo
!= pPlInfo
); // DBG:: no sence
1590 cbPluginBase
* pNextPl
= FindPlugin( pNextPlInfo
);
1594 AddPlugin( pPlInfo
, paneMask
);
1599 // remove existing one if present
1601 cbPluginBase
* pExistingPl
= FindPlugin( pPlInfo
);
1603 if ( pExistingPl
) RemovePlugin( pPlInfo
);
1605 // create an instance
1607 cbPluginBase
* pNewPl
= (cbPluginBase
*)pPlInfo
->CreateObject();
1609 wxASSERT(pNewPl
); // DBG:: plugin's class should be dynamic
1611 // insert it to the chain
1613 if ( pNextPl
->GetPreviousHandler() )
1615 pNextPl
->GetPreviousHandler()->SetNextHandler( pNewPl
);
1617 mpTopPlugin
= pNewPl
;
1619 pNewPl
->SetNextHandler( pNextPl
);
1621 pNewPl
->SetPreviousHandler( pNextPl
->GetPreviousHandler() );
1623 pNextPl
->SetPreviousHandler( pNewPl
);
1627 pNewPl
->mPaneMask
= paneMask
;
1628 pNewPl
->mpLayout
= this;
1630 pNewPl
->OnInitPlugin();
1633 void wxFrameLayout::RemovePlugin( wxClassInfo
* pPlInfo
)
1635 cbPluginBase
* pPlugin
= FindPlugin( pPlInfo
);
1637 if ( !pPlugin
) return; // it's OK to remove not-existing plugin ;-)
1639 if ( pPlugin
->GetPreviousHandler() == NULL
)
1641 mpTopPlugin
= (cbPluginBase
*)pPlugin
->GetNextHandler();
1646 cbPluginBase
* wxFrameLayout::FindPlugin( wxClassInfo
* pPlInfo
)
1648 cbPluginBase
*pCur
= mpTopPlugin
;
1652 // NOTE:: it might appear usefull matching plugin
1653 // classes "polymorphically":
1655 if ( pCur
->GetClassInfo()->IsKindOf( pPlInfo
) )
1659 pCur
= (cbPluginBase
*)pCur
->GetNextHandler();
1665 /***** Implementation for class cbUpdateMgrData *****/
1667 IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData
, wxObject
)
1669 cbUpdateMgrData::cbUpdateMgrData()
1671 : mPrevBounds( -1,-1,0,0 ),
1672 mIsDirty( TRUE
) // inidicate initial change
1675 void cbUpdateMgrData::StoreItemState( const wxRect
& boundsInParent
)
1677 mPrevBounds
= boundsInParent
;
1680 void cbUpdateMgrData::SetDirty( bool isDirty
)
1685 void cbUpdateMgrData::SetCustomData( wxObject
* pCustomData
)
1687 mpCustomData
= pCustomData
;
1690 /***** Implementation for class cbDockPane *****/
1692 void wxBarIterator::Reset()
1694 mpRow
= ( mpRows
->Count() ) ? (*mpRows
)[0] : NULL
;
1698 wxBarIterator::wxBarIterator( RowArrayT
& rows
)
1707 bool wxBarIterator::Next()
1712 mpBar
= mpBar
->mpNext
;
1715 if ( mpRow
->mBars
.GetCount() == 0 )
1720 mpBar
= mpRow
->mBars
[0];
1725 // skip to the next row
1727 mpRow
= mpRow
->mpNext
;
1731 mpBar
= mpRow
->mBars
[0];
1742 cbBarInfo
& wxBarIterator::BarInfo()
1747 cbRowInfo
& wxBarIterator::RowInfo()
1752 /***** Implementation for class cbBarDimHandlerBase *****/
1754 IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase
, wxObject
)
1756 cbBarDimHandlerBase::cbBarDimHandlerBase()
1760 void cbBarDimHandlerBase::AddRef()
1765 void cbBarDimHandlerBase::RemoveRef()
1767 if ( --mRefCount
<= 0 ) delete this;
1770 /***** Implementation for class cbDimInfo *****/
1772 IMPLEMENT_DYNAMIC_CLASS( cbDimInfo
, wxObject
)
1774 cbDimInfo::cbDimInfo()
1782 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1787 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1791 cbDimInfo::cbDimInfo( cbBarDimHandlerBase
* pDimHandler
,
1796 mIsFixed ( isFixed
),
1798 mpHandler( pDimHandler
)
1802 int vtad
= *((int*)mpHandler
);
1803 mpHandler
->AddRef();
1806 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1811 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1815 cbDimInfo::cbDimInfo( int dh_x
, int dh_y
,
1823 cbBarDimHandlerBase
* pDimHandler
1825 : mHorizGap ( horizGap
),
1826 mVertGap ( vertGap
),
1827 mIsFixed ( isFixed
),
1828 mpHandler( pDimHandler
)
1832 int vtad
= *((int*)mpHandler
);
1833 mpHandler
->AddRef();
1837 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= dh_x
;
1838 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= dh_y
;
1839 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= dv_x
;
1840 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= dv_y
;
1841 mSizes
[wxCBAR_FLOATING
].x
= f_x
;
1842 mSizes
[wxCBAR_FLOATING
].y
= f_y
;
1845 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1847 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1850 cbDimInfo::~cbDimInfo()
1854 mpHandler
->RemoveRef();
1857 const cbDimInfo
& cbDimInfo::operator=( cbDimInfo
& other
)
1859 if ( this == &other
) return *this;
1861 for( int i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1863 mSizes
[i
] = other
.mSizes
[i
];
1865 mIsFixed
= other
.mIsFixed
;
1866 mpHandler
= other
.mpHandler
;
1868 mVertGap
= other
.mVertGap
;
1869 mHorizGap
= other
.mHorizGap
;
1873 mpHandler
->AddRef();
1878 /***** Implementation for structure cbCommonPaneProperties *****/
1880 IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties
, wxObject
)
1882 cbCommonPaneProperties::cbCommonPaneProperties(void)
1884 : mRealTimeUpdatesOn ( TRUE
),
1885 mOutOfPaneDragOn ( TRUE
),
1886 mExactDockPredictionOn( FALSE
),
1887 mNonDestructFirctionOn( FALSE
),
1888 mShow3DPaneBorderOn ( TRUE
),
1889 mBarFloatingOn ( FALSE
),
1890 mRowProportionsOn ( FALSE
),
1891 mColProportionsOn ( TRUE
),
1892 mBarCollapseIconsOn ( FALSE
),
1893 mBarDragHintsOn ( FALSE
),
1895 mMinCBarDim( 16, 16 ),
1896 mResizeHandleSize( 4 )
1899 /***** Implementation for class cbRowInfo *****/
1901 IMPLEMENT_DYNAMIC_CLASS( cbRowInfo
, wxObject
)
1903 cbRowInfo::cbRowInfo(void)
1907 mNotFixedBarsCnt( FALSE
),
1908 mpExpandedBar ( NULL
)
1911 cbRowInfo::~cbRowInfo()
1913 // nothing! all bars are removed using global bar
1914 // list in wxFrameLayout class
1917 /***** Implementation for class cbBarInfo *****/
1919 IMPLEMENT_DYNAMIC_CLASS( cbBarInfo
, wxObject
)
1921 cbBarInfo::cbBarInfo(void)
1929 cbBarInfo::~cbBarInfo()
1934 /***** Implementation for class cbDockPane *****/
1936 IMPLEMENT_DYNAMIC_CLASS( cbDockPane
, wxObject
)
1938 // FIXME:: how to eliminate these cut&pasted constructors?
1940 cbDockPane::cbDockPane(void)
1943 mPaneWidth ( 32768 ), // fake-up very large pane dims,
1944 // since the real dimensions of the pane may not
1945 // be known, while inserting bars initially
1946 mPaneHeight( 32768 ),
1948 mpStoredRow( NULL
),
1955 cbDockPane::cbDockPane( int alignment
, wxFrameLayout
* pPanel
)
1957 : mpLayout ( pPanel
),
1958 mPaneWidth ( 32768 ), // fake-up very large pane dims,
1959 // since the real dimensions of the pane may not
1960 // be known, while inserting bars initially
1961 mPaneHeight( 32768 ),
1962 mAlignment ( alignment
),
1963 mpStoredRow( NULL
),
1971 cbDockPane::~cbDockPane()
1973 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
1977 mRowShapeData
.DeleteContents( TRUE
);
1979 // NOTE:: control bar infromation structures are cleaned-up
1980 // in wxFrameLayout's destructor, using global control-bar list
1983 void cbDockPane::SetMargins( int top
, int bottom
, int left
, int right
)
1986 mBottomMargin
= bottom
;
1988 mRightMargin
= right
;
1991 /*** helpers of cbDockPane ***/
1993 void cbDockPane::PaintBarDecorations( cbBarInfo
* pBar
, wxDC
& dc
)
1995 cbDrawBarDecorEvent
evt( pBar
, dc
, this );
1997 mpLayout
->FirePluginEvent( evt
);
2000 void cbDockPane::PaintBarHandles( cbBarInfo
* pBar
, wxDC
& dc
)
2002 cbDrawBarHandlesEvent
evt( pBar
, dc
, this );
2004 mpLayout
->FirePluginEvent( evt
);
2007 void cbDockPane::PaintBar( cbBarInfo
* pBar
, wxDC
& dc
)
2009 PaintBarDecorations( pBar
, dc
);
2010 PaintBarHandles( pBar
, dc
);
2013 void cbDockPane::PaintRowHandles( cbRowInfo
* pRow
, wxDC
& dc
)
2015 cbDrawRowHandlesEvent
evt( pRow
, dc
, this );
2017 mpLayout
->FirePluginEvent( evt
);
2019 cbDrawRowDecorEvent
evt1( pRow
, dc
, this );
2021 mpLayout
->FirePluginEvent( evt1
);
2024 void cbDockPane::PaintRowBackground ( cbRowInfo
* pRow
, wxDC
& dc
)
2026 cbDrawRowBkGroundEvent
evt( pRow
, dc
, this );
2028 mpLayout
->FirePluginEvent( evt
);
2031 void cbDockPane::PaintRowDecorations( cbRowInfo
* pRow
, wxDC
& dc
)
2035 // decorations first
2036 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2038 PaintBarDecorations( pRow
->mBars
[i
], dc
);
2040 // then handles if present
2041 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2043 PaintBarHandles( pRow
->mBars
[i
], dc
);
2046 void cbDockPane::PaintRow( cbRowInfo
* pRow
, wxDC
& dc
)
2048 PaintRowBackground ( pRow
, dc
);
2049 PaintRowDecorations( pRow
, dc
);
2050 PaintRowHandles ( pRow
, dc
);
2053 void cbDockPane::PaintPaneBackground( wxDC
& dc
)
2055 cbDrawPaneBkGroundEvent
evt( dc
, this );
2057 mpLayout
->FirePluginEvent( evt
);
2060 void cbDockPane::PaintPaneDecorations( wxDC
& dc
)
2062 cbDrawPaneDecorEvent
evt( dc
, this );
2064 mpLayout
->FirePluginEvent( evt
);
2067 void cbDockPane::PaintPane( wxDC
& dc
)
2069 PaintPaneBackground( dc
);
2073 // first decorations
2074 for( i
= 0; i
!= mRows
.Count(); ++i
)
2076 PaintRowBackground( mRows
[i
], dc
);
2077 PaintRowDecorations( mRows
[i
], dc
);
2081 for( i
= 0; i
!= mRows
.Count(); ++i
)
2083 PaintRowHandles( mRows
[i
], dc
);
2086 PaintPaneDecorations( dc
);
2089 void cbDockPane::SizeBar( cbBarInfo
* pBar
)
2091 cbSizeBarWndEvent
evt( pBar
, this );
2093 mpLayout
->FirePluginEvent( evt
);
2097 void cbDockPane::SizeRowObjects( cbRowInfo
* pRow
)
2099 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2101 SizeBar( pRow
->mBars
[i
] );
2104 void cbDockPane::SizePaneObjects()
2106 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2108 SizeRowObjects( mRows
[i
] );
2111 wxDC
* cbDockPane::StartDrawInArea( const wxRect
& area
)
2115 cbStartDrawInAreaEvent
evt( area
, &pDc
, this );
2117 mpLayout
->FirePluginEvent( evt
);
2122 void cbDockPane::FinishDrawInArea( const wxRect
& area
)
2124 cbFinishDrawInAreaEvent
evt( area
, this );
2126 mpLayout
->FirePluginEvent( evt
);
2129 bool cbDockPane::IsFixedSize( cbBarInfo
* pInfo
)
2131 return ( pInfo
->mDimInfo
.mIsFixed
);
2134 int cbDockPane::GetNotFixedBarsCount( cbRowInfo
* pRow
)
2138 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2140 if ( !pRow
->mBars
[i
]->IsFixed() ) ++cnt
;
2145 void cbDockPane::RemoveBar( cbBarInfo
* pBar
)
2147 bool needsRestoring
= mProps
.mNonDestructFirctionOn
&&
2148 mpStoredRow
== pBar
->mpRow
;
2150 cbRemoveBarEvent
evt( pBar
, this );
2152 mpLayout
->FirePluginEvent( evt
);
2154 if ( needsRestoring
)
2156 SetRowShapeData( mpStoredRow
, &mRowShapeData
);
2162 void cbDockPane::SyncRowFlags( cbRowInfo
* pRow
)
2164 // setup mHasOnlyFixedBars flag for the row information
2165 pRow
->mHasOnlyFixedBars
= TRUE
;
2167 pRow
->mNotFixedBarsCnt
= 0;
2169 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2171 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2175 if ( !bar
.IsFixed() )
2177 pRow
->mHasOnlyFixedBars
= FALSE
;
2178 ++pRow
->mNotFixedBarsCnt
;
2183 void cbDockPane::FrameToPane( long* x
, long* y
)
2188 if ( mAlignment
== wxTOP
||
2189 mAlignment
== wxBOTTOM
2192 *x
-= mBoundsInParent
.x
;
2193 *y
-= mBoundsInParent
.y
;
2197 int rx
= *x
, ry
= *y
;
2199 *x
= ry
- mBoundsInParent
.y
;
2201 *y
= rx
- mBoundsInParent
.x
;
2205 void cbDockPane::PaneToFrame( long* x
, long* y
)
2207 if ( mAlignment
== wxTOP
||
2208 mAlignment
== wxBOTTOM
2211 *x
+= mBoundsInParent
.x
;
2212 *y
+= mBoundsInParent
.y
;
2216 int rx
= *x
, ry
= *y
;
2218 *x
= ry
+ mBoundsInParent
.x
;
2220 *y
= mBoundsInParent
.y
+ rx
;
2227 void cbDockPane::FrameToPane( wxRect
* pRect
)
2229 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2230 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2231 pRect
->y
+ pRect
->height
);
2233 FrameToPane( &upperLeft
.x
, &upperLeft
.y
);
2234 FrameToPane( &lowerRight
.x
, &lowerRight
.y
);
2236 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2237 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2239 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2240 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2243 void cbDockPane::PaneToFrame( wxRect
* pRect
)
2245 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2246 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2247 pRect
->y
+ pRect
->height
);
2249 PaneToFrame( &upperLeft
.x
, &upperLeft
.y
);
2250 PaneToFrame( &lowerRight
.x
, &lowerRight
.y
);
2252 //wxRect newRect = wxRect( upperLeft, lowerRight );
2254 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2255 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2257 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2258 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2261 int cbDockPane::GetRowAt( int paneY
)
2263 if ( paneY
< 0 ) return -1;
2269 for( ; i
!= mRows
.Count(); ++i
)
2271 int rowHeight
= mRows
[i
]->mRowHeight
;
2273 int third
= rowHeight
/3;
2275 if ( paneY
>= curY
&& paneY
< curY
+ third
)
2278 if ( paneY
>= curY
+ third
&& paneY
< curY
+ rowHeight
- third
)
2287 int cbDockPane::GetRowAt( int upperY
, int lowerY
)
2291 int range = lowerY - upperY;
2292 int oneThird = range / 3;
2294 wxNode* pRow = mRows.First();
2298 if ( lowerY <= 0 ) return -1;
2302 int rowHeight = GetRowHeight( (wxList*)pRow->Data() );
2304 if ( upperY >= curY &&
2305 lowerY < curY ) return row;
2307 if ( upperY <= curY &&
2309 curY - upperY >= oneThird ) return row-1;
2311 if ( ( upperY < curY + rowHeight &&
2312 lowerY >= curY + rowHeight &&
2313 curY + rowHeight - lowerY >= oneThird )
2317 if ( lowerY <= curY + rowHeight ) return row;
2321 pRow = pRow->Next();
2325 int mid
= upperY
+ (lowerY
- upperY
)/2;
2327 if ( mid
< 0 ) return -1;
2332 for( ; i
!= mRows
.Count(); ++i
)
2334 int rowHeight
= mRows
[i
]->mRowHeight
;
2336 if ( mid
>= curY
&& mid
< curY
+ rowHeight
) return i
;
2344 int cbDockPane::GetRowY( cbRowInfo
* pRow
)
2348 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2350 if ( mRows
[i
] == pRow
) break;
2352 curY
+= mRows
[i
]->mRowHeight
;
2358 bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo
* pRow
)
2360 while ( pRow
->mpPrev
)
2362 pRow
= pRow
->mpPrev
;
2364 if ( pRow
->mHasOnlyFixedBars
)
2372 bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo
* pRow
)
2374 while( pRow
->mpNext
)
2376 pRow
= pRow
->mpNext
;
2378 if ( pRow
->mHasOnlyFixedBars
)
2386 bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo
* pBar
)
2388 while( pBar
->mpPrev
)
2390 pBar
= pBar
->mpPrev
;
2392 if ( pBar
->IsFixed() )
2400 bool cbDockPane::HasNotFixedBarsRight( cbBarInfo
* pBar
)
2402 while( pBar
->mpNext
)
2404 pBar
= pBar
->mpNext
;
2406 if ( pBar
->IsFixed() )
2414 void cbDockPane::CalcLenghtRatios( cbRowInfo
* pInRow
)
2420 // clac current-maximal-total-length of all maximized bars
2422 for( i
= 0; i
!= pInRow
->mBars
.GetCount(); ++i
)
2424 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2426 if ( !bar
.IsFixed() )
2428 totalWidth
+= bar
.mBounds
.width
;
2431 // set up persentages of occupied space for each maximized bar
2433 for( i
= 0; i
!= pInRow
->mBars
.Count(); ++i
)
2435 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2437 if ( !bar
.IsFixed() )
2439 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalWidth
);
2443 void cbDockPane::RecalcRowLayout( cbRowInfo
* pRow
)
2445 cbLayoutRowEvent
evt( pRow
, this );
2447 mpLayout
->FirePluginEvent( evt
);
2450 void cbDockPane::ExpandBar( cbBarInfo
* pBar
)
2452 mpLayout
->GetUpdatesManager().OnStartChanges();
2454 if ( !pBar
->mpRow
->mpExpandedBar
)
2456 // save ratios only when there arent any bars expanded yet
2458 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2461 ratios
.Alloc( pBar
->mpRow
->mNotFixedBarsCnt
);
2463 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2467 if ( !pCur
->IsFixed() )
2470 ratios
[ ratios
.GetCount() - 1 ] = pCur
->mLenRatio
;
2473 pCur
= pCur
->mpNext
;
2477 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2481 pCur
->mLenRatio
= 0.0; // minimize the rest
2483 pCur
= pCur
->mpNext
;
2486 pBar
->mLenRatio
= 1.0; // 100%
2487 pBar
->mBounds
.width
= 0;
2489 pBar
->mpRow
->mpExpandedBar
= pBar
;
2491 mpLayout
->RecalcLayout( FALSE
);
2493 mpLayout
->GetUpdatesManager().OnFinishChanges();
2494 mpLayout
->GetUpdatesManager().UpdateNow();
2497 void cbDockPane::ContractBar( cbBarInfo
* pBar
)
2499 mpLayout
->GetUpdatesManager().OnStartChanges();
2501 double ratio
= 1.0/ double( pBar
->mpRow
->mNotFixedBarsCnt
);
2503 // restore ratios which were present before expansion
2505 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2507 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2513 if ( !pCur
->IsFixed() )
2515 pCur
->mLenRatio
= ratios
[i
];
2519 pCur
= pCur
->mpNext
;
2525 pBar
->mpRow
->mpExpandedBar
= NULL
;
2527 mpLayout
->RecalcLayout( FALSE
);
2529 mpLayout
->GetUpdatesManager().OnFinishChanges();
2530 mpLayout
->GetUpdatesManager().UpdateNow();
2533 void cbDockPane::InitLinksForRow( cbRowInfo
* pRow
)
2535 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2537 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2543 bar
.mpPrev
= pRow
->mBars
[i
-1];
2545 if ( i
== pRow
->mBars
.Count() - 1 )
2549 bar
.mpNext
= pRow
->mBars
[i
+1];
2553 void cbDockPane::InitLinksForRows()
2555 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2557 cbRowInfo
& row
= *mRows
[i
];
2563 row
.mpPrev
= mRows
[i
-1];
2565 if ( i
== mRows
.Count() - 1 )
2569 row
.mpNext
= mRows
[i
+1];
2573 void cbDockPane::DoInsertBar( cbBarInfo
* pBar
, int rowNo
)
2575 cbRowInfo
* pRow
= NULL
;
2577 if ( rowNo
== -1 || rowNo
>= (int)mRows
.Count() )
2579 pRow
= new cbRowInfo();
2581 if ( rowNo
== -1 && mRows
.Count() )
2583 mRows
.Insert( pRow
, 0 );
2591 pRow
= mRows
[rowNo
];
2593 if ( mProps
.mNonDestructFirctionOn
== TRUE
)
2595 // store original shape of the row (before the bar is inserted)
2599 GetRowShapeData( mpStoredRow
, &mRowShapeData
);
2603 if ( pRow
->mBars
.Count() )
2605 pRow
->mpExpandedBar
= NULL
;
2607 cbInsertBarEvent
insEvt( pBar
, pRow
, this );
2609 mpLayout
->FirePluginEvent( insEvt
);
2611 mpLayout
->GetUpdatesManager().OnRowWillChange( pRow
, this );
2614 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
, const wxRect
& atRect
)
2616 wxRect rect
= atRect
;
2617 FrameToPane( &rect
);
2619 pBarInfo
->mBounds
.x
= rect
.x
;
2620 pBarInfo
->mBounds
.width
= rect
.width
;
2621 pBarInfo
->mBounds
.height
= rect
.height
;
2623 int row
= GetRowAt( rect
.y
, rect
.y
+ rect
.height
);
2625 DoInsertBar( pBarInfo
, row
);
2628 void cbDockPane::InsertBar( cbBarInfo
* pBar
, cbRowInfo
* pIntoRow
)
2630 cbInsertBarEvent
insEvt( pBar
, pIntoRow
, this );
2632 mpLayout
->FirePluginEvent( insEvt
);
2634 mpLayout
->GetUpdatesManager().OnRowWillChange( pIntoRow
, this );
2637 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
)
2639 // set transient properties
2641 pBarInfo
->mpRow
= NULL
;
2642 pBarInfo
->mHasLeftHandle
= FALSE
;
2643 pBarInfo
->mHasRightHandle
= FALSE
;
2644 pBarInfo
->mLenRatio
= 0.0;
2646 // set preferred bar demensions, according to the state in which
2647 // the bar is being inserted
2649 pBarInfo
->mBounds
.width
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].x
;
2650 pBarInfo
->mBounds
.height
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].y
;
2652 DoInsertBar( pBarInfo
, pBarInfo
->mRowNo
);
2655 void cbDockPane::RemoveRow( cbRowInfo
* pRow
)
2657 // first, hide all bar-windows in the removed row
2658 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2660 if ( pRow
->mBars
[i
]->mpBarWnd
)
2662 pRow
->mBars
[i
]->mpBarWnd
->Show( FALSE
);
2664 mRows
.Remove( pRow
);
2666 pRow
->mUMgrData
.SetDirty(TRUE
);
2669 void cbDockPane::InsertRow( cbRowInfo
* pRow
, cbRowInfo
* pBeforeRow
)
2675 mRows
.Insert( pRow
, mRows
.Index( pBeforeRow
) );
2679 pRow
->mUMgrData
.SetDirty(TRUE
);
2681 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2683 pRow
->mBars
[i
]->mUMgrData
.SetDirty( TRUE
);
2685 SyncRowFlags( pRow
);
2688 void cbDockPane::SetPaneWidth(int width
)
2690 if ( IsHorizontal() )
2692 mPaneWidth
= width
- mLeftMargin
- mRightMargin
;
2694 mPaneWidth
= width
- mTopMargin
- mBottomMargin
;
2698 void cbDockPane::SetBoundsInParent( const wxRect
& rect
)
2701 mBoundsInParent
= rect
;
2703 // set pane dimensions in local coordinates
2705 if ( IsHorizontal() )
2707 mPaneWidth
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2708 mPaneHeight
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2712 mPaneWidth
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2713 mPaneHeight
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2716 // convert bounding rectangles of all pane items into parent frame's coordinates
2718 wxBarIterator
i( mRows
);
2720 wxRect noMarginsRect
= mBoundsInParent
;
2722 noMarginsRect
.x
+= mLeftMargin
;
2723 noMarginsRect
.y
+= mTopMargin
;
2724 noMarginsRect
.width
-= ( mLeftMargin
+ mRightMargin
);
2725 noMarginsRect
.height
-= ( mTopMargin
+ mBottomMargin
);
2727 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2729 if ( mBoundsInParent
.width
< 0 ||
2730 mBoundsInParent
.height
< 0 )
2732 hide_rect( mBoundsInParent
);
2734 if ( noMarginsRect
.width
< 0 ||
2735 noMarginsRect
.height
< 0 )
2737 hide_rect( noMarginsRect
);
2739 // calculate mBoundsInParent for each item in the pane
2743 cbBarInfo
& bar
= i
.BarInfo();
2745 cbRowInfo
* pRowInfo
= bar
.mpRow
;
2747 // set up row info, if this is first bar in the row
2749 if ( pRowInfo
&& bar
.mpPrev
== NULL
)
2751 pRowInfo
->mBoundsInParent
.y
= pRowInfo
->mRowY
;
2752 pRowInfo
->mBoundsInParent
.x
= 0;
2753 pRowInfo
->mBoundsInParent
.width
= mPaneWidth
;
2754 pRowInfo
->mBoundsInParent
.height
= pRowInfo
->mRowHeight
;
2756 PaneToFrame( &pRowInfo
->mBoundsInParent
);
2758 clip_rect_against_rect( pRowInfo
->mBoundsInParent
, noMarginsRect
);
2761 wxRect bounds
= bar
.mBounds
;
2763 // exclude dimensions of handles, when calculating
2764 // bar's bounds in parent (i.e. "visual bounds")
2766 if ( bar
.mHasLeftHandle
)
2768 bounds
.x
+= mProps
.mResizeHandleSize
;
2769 bounds
.width
-= mProps
.mResizeHandleSize
;
2772 if ( bar
.mHasRightHandle
)
2774 bounds
.width
-= mProps
.mResizeHandleSize
;
2776 PaneToFrame( &bounds
);
2778 clip_rect_against_rect( bounds
, noMarginsRect
);
2780 bar
.mBoundsInParent
= bounds
;
2784 bool cbDockPane::BarPresent( cbBarInfo
* pBar
)
2786 wxBarIterator
iter( mRows
);
2788 while( iter
.Next() )
2790 if ( &iter
.BarInfo() == pBar
) return TRUE
;
2795 cbRowInfo
* cbDockPane::GetRow( int row
)
2797 if ( row
>= (int)mRows
.Count() ) return NULL
;
2799 return mRows
[ row
];
2802 int cbDockPane::GetRowIndex( cbRowInfo
* pRow
)
2804 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2806 if ( mRows
[i
] == pRow
) return i
;
2808 wxASSERT(0); // DBG:: row should be present
2813 int cbDockPane::GetPaneHeight()
2815 // first, recalculate row heights and the Y-positions
2817 cbLayoutRowsEvent
evt( this );
2818 mpLayout
->FirePluginEvent( evt
);
2822 if ( IsHorizontal() )
2824 height
+= mTopMargin
+ mBottomMargin
;
2826 height
+= mLeftMargin
+ mRightMargin
;
2828 int count
= mRows
.Count();
2832 height
+= mRows
[count
-1]->mRowY
+ mRows
[count
-1]->mRowHeight
;
2837 int cbDockPane::GetAlignment()
2842 bool cbDockPane::MatchesMask( int paneMask
)
2846 // FIXME:: use array instead of switch()
2850 case wxTOP
: thisMask
= wxTOP_PANE
; break;
2851 case wxBOTTOM
: thisMask
= wxBOTTOM_PANE
;break;
2852 case wxLEFT
: thisMask
= wxLEFT_PANE
; break;
2853 case wxRIGHT
: thisMask
= wxRIGHT_PANE
; break;
2855 default: wxASSERT(0); // DBG:: bogous alignment type
2858 return ( thisMask
& paneMask
);
2861 void cbDockPane::RecalcLayout()
2863 // first, reposition rows and items vertically
2865 cbLayoutRowsEvent
evt( this );
2866 mpLayout
->FirePluginEvent( evt
);
2868 // then horizontally in each row
2870 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2872 RecalcRowLayout( mRows
[i
] );
2875 int cbDockPane::GetDockingState()
2877 if ( mAlignment
== wxTOP
||
2878 mAlignment
== wxBOTTOM
)
2880 return wxCBAR_DOCKED_HORIZONTALLY
;
2883 return wxCBAR_DOCKED_VERTICALLY
;
2886 inline bool cbDockPane::HasPoint( const wxPoint
& pos
, int x
, int y
,
2887 int width
, int height
)
2889 return ( pos
.x
>= x
&&
2891 pos
.x
< x
+ width
&&
2892 pos
.y
< y
+ height
);
2895 int cbDockPane::HitTestPaneItems( const wxPoint
& pos
,
2903 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2905 cbRowInfo
& row
= *mRows
[i
];
2909 // hit-test handles of the row, if present
2911 if ( row
.mHasUpperHandle
)
2913 if ( HasPoint( pos
, 0, row
.mRowY
,
2914 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
2916 return CB_UPPER_ROW_HANDLE_HITTED
;
2919 if ( row
.mHasLowerHandle
)
2921 if ( HasPoint( pos
, 0, row
.mRowY
+ row
.mRowHeight
- mProps
.mResizeHandleSize
,
2922 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
2924 return CB_LOWER_ROW_HANDLE_HITTED
;
2927 // hit-test bar handles and bar content
2929 for( size_t k
= 0; k
!= row
.mBars
.Count(); ++k
)
2931 cbBarInfo
& bar
= *row
.mBars
[k
];
2932 wxRect
& bounds
= bar
.mBounds
;
2936 if ( bar
.mHasLeftHandle
)
2938 if ( HasPoint( pos
, bounds
.x
, bounds
.y
,
2939 mProps
.mResizeHandleSize
, bounds
.height
) )
2941 return CB_LEFT_BAR_HANDLE_HITTED
;
2944 if ( bar
.mHasRightHandle
)
2946 if ( HasPoint( pos
, bounds
.x
+ bounds
.width
- mProps
.mResizeHandleSize
, bounds
.y
,
2947 mProps
.mResizeHandleSize
, bounds
.height
) )
2949 return CB_RIGHT_BAR_HANDLE_HITTED
;
2952 if ( HasPoint( pos
, bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
) )
2954 return CB_BAR_CONTENT_HITTED
;
2956 } // hit-test next bar
2960 return CB_NO_ITEMS_HITTED
;
2963 void cbDockPane::GetBarResizeRange( cbBarInfo
* pBar
, int* from
, int *till
,
2964 bool forLeftHandle
)
2966 cbBarInfo
* pGivenBar
= pBar
;
2970 // calc unavailable space from the left
2972 while( pBar
->mpPrev
)
2974 pBar
= pBar
->mpPrev
;
2976 if ( !pBar
->IsFixed() ) notFree
+= mProps
.mMinCBarDim
.x
;
2977 else notFree
+= pBar
->mBounds
.width
;
2986 // calc unavailable space from the right
2988 while( pBar
->mpNext
)
2990 pBar
= pBar
->mpNext
;
2992 if ( pBar
->mBounds
.x
>= mPaneWidth
) break;
2994 // treat not-fixed bars as minimized
2996 if ( !pBar
->IsFixed() )
2998 notFree
+= mProps
.mMinCBarDim
.x
;
3001 if ( pBar
->mBounds
.x
+ pBar
->mBounds
.width
>= mPaneWidth
)
3003 notFree
+= mPaneWidth
- pBar
->mBounds
.x
;
3007 notFree
+= pBar
->mBounds
.width
;
3012 *till
= mPaneWidth
- notFree
;
3014 // do not let resizing totally deform the bar itself
3016 if ( forLeftHandle
)
3018 (*till
) -= mProps
.mMinCBarDim
.x
;
3021 (*from
) += mProps
.mMinCBarDim
.x
;
3024 int cbDockPane::GetMinimalRowHeight( cbRowInfo
* pRow
)
3026 int height
= mProps
.mMinCBarDim
.y
;
3028 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3030 if ( pRow
->mBars
[i
]->IsFixed() )
3032 height
= wxMax( height
, pRow
->mBars
[i
]->mBounds
.height
);
3034 if ( pRow
->mHasUpperHandle
)
3036 height
+= mProps
.mResizeHandleSize
;
3038 if ( pRow
->mHasLowerHandle
)
3040 height
+= mProps
.mResizeHandleSize
;
3045 void cbDockPane::SetRowHeight( cbRowInfo
* pRow
, int newHeight
)
3047 if ( pRow
->mHasUpperHandle
)
3049 newHeight
-= mProps
.mResizeHandleSize
;
3051 if ( pRow
->mHasLowerHandle
)
3053 newHeight
-= mProps
.mResizeHandleSize
;
3055 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3057 if ( !pRow
->mBars
[i
]->IsFixed() )
3059 pRow
->mBars
[i
]->mBounds
.height
= newHeight
;
3062 void cbDockPane::GetRowResizeRange( cbRowInfo
* pRow
, int* from
, int* till
,
3063 bool forUpperHandle
)
3065 cbRowInfo
* pGivenRow
= pRow
;
3067 // calc unavailable space from above
3071 while( pRow
->mpPrev
)
3073 pRow
= pRow
->mpPrev
;
3075 notFree
+= GetMinimalRowHeight( pRow
);
3081 // allow accupy the client window space by resizing pane rows
3082 if ( mAlignment
== wxBOTTOM
)
3084 *from
-= mpLayout
->GetClientHeight();
3086 if ( mAlignment
== wxRIGHT
)
3088 *from
-= mpLayout
->GetClientWidth();
3090 // calc unavailable space from below
3096 while( pRow
->mpNext
)
3098 pRow
= pRow
->mpNext
;
3100 notFree
+= GetMinimalRowHeight( pRow
);
3104 *till
= mPaneHeight
- notFree
;
3106 // allow adjustinig pane space vs. client window space by resizing pane row heights
3108 if ( mAlignment
== wxTOP
)
3110 *till
+= mpLayout
->GetClientHeight();
3112 if ( mAlignment
== wxLEFT
)
3114 *till
+= mpLayout
->GetClientWidth();
3116 // do not let the resizing of the row totally squeeze the row itself
3118 cbRowInfo
& row
= *pGivenRow
;
3120 if ( forUpperHandle
)
3122 *till
= row
.mRowY
+ row
.mRowHeight
- GetMinimalRowHeight( pGivenRow
);
3124 if ( row
.mHasUpperHandle
)
3126 *till
-= mProps
.mResizeHandleSize
;
3130 *from
+= GetMinimalRowHeight( pGivenRow
);
3132 if ( row
.mHasLowerHandle
)
3134 *from
-= mProps
.mResizeHandleSize
;
3138 void cbDockPane::ResizeRow( cbRowInfo
* pRow
, int ofs
,
3139 bool forUpperHandle
)
3141 cbResizeRowEvent
evt( pRow
, ofs
, forUpperHandle
, this );
3143 mpLayout
->FirePluginEvent( evt
);
3146 void cbDockPane::ResizeBar( cbBarInfo
* pBar
, int ofs
,
3147 bool forLeftHandle
)
3149 pBar
->mpRow
->mpExpandedBar
= NULL
;
3151 mpLayout
->GetUpdatesManager().OnStartChanges();
3153 wxRect
& bounds
= pBar
->mBounds
;
3155 if ( forLeftHandle
)
3157 // do not allow bar width become less then minimal
3158 if ( bounds
.x
+ ofs
> bounds
.x
+ bounds
.width
- mProps
.mMinCBarDim
.x
)
3160 bounds
.width
= mProps
.mMinCBarDim
.x
;
3166 bounds
.width
-= ofs
;
3171 // move bar left if necessary
3172 if ( bounds
.width
+ ofs
< mProps
.mMinCBarDim
.x
)
3174 bounds
.x
= bounds
.x
+ bounds
.width
+ ofs
- mProps
.mMinCBarDim
.x
;
3175 bounds
.width
= mProps
.mMinCBarDim
.x
;
3178 // resize right border only
3179 bounds
.width
+= ofs
;
3183 cbRowInfo
* pToRow
= pBar
->mpRow
;
3185 this->RemoveBar( pBar
);
3187 InsertBar( pBar
, pToRow
);
3189 mpLayout
->RecalcLayout(FALSE
);
3191 mpLayout
->GetUpdatesManager().OnFinishChanges();
3192 mpLayout
->GetUpdatesManager().UpdateNow();
3196 /*** row/bar resizing related methods ***/
3198 void cbDockPane::DrawVertHandle( wxDC
& dc
, int x
, int y
, int height
)
3200 int lower
= y
+ height
;
3202 dc
.SetPen( mpLayout
->mLightPen
);
3203 dc
.DrawLine( x
,y
, x
, lower
);
3205 dc
.SetPen( mpLayout
->mGrayPen
);
3206 for( int i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3209 dc
.DrawLine( x
,y
, x
, lower
);
3212 dc
.SetPen( mpLayout
->mDarkPen
);
3214 dc
.DrawLine( x
,y
, x
, lower
);
3216 dc
.SetPen( mpLayout
->mBlackPen
);
3218 dc
.DrawLine( x
,y
, x
, lower
);
3221 void cbDockPane::DrawHorizHandle( wxDC
& dc
, int x
, int y
, int width
)
3223 int right
= x
+ width
;
3225 dc
.SetPen( mpLayout
->mLightPen
);
3226 dc
.DrawLine( x
,y
, right
, y
);
3228 dc
.SetPen( mpLayout
->mGrayPen
);
3230 for( int i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3233 dc
.DrawLine( x
,y
, right
, y
);
3236 dc
.SetPen( mpLayout
->mDarkPen
);
3237 dc
.DrawLine( x
,y
, right
, ++y
);
3239 dc
.SetPen( mpLayout
->mBlackPen
);
3240 dc
.DrawLine( x
,y
, right
, ++y
);
3243 cbBarInfo
* cbDockPane::GetBarInfoByWindow( wxWindow
* pBarWnd
)
3245 wxBarIterator
i( mRows
);
3249 if ( i
.BarInfo().mpBarWnd
== pBarWnd
)
3251 return &i
.BarInfo();
3256 void cbDockPane::GetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3258 pLst
->DeleteContents( TRUE
);
3261 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3263 cbBarInfo
& bar
= *pRow
->mBars
[i
];
3265 cbBarShapeData
* pData
= new cbBarShapeData();
3267 pLst
->Append( (wxObject
*)pData
);
3269 pData
->mBounds
= bar
.mBounds
;
3270 pData
->mLenRatio
= bar
.mLenRatio
;
3274 void cbDockPane::SetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3276 if ( pLst
->First() == NULL
) return;
3278 wxNode
* pData
= pLst
->First();
3280 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3282 wxASSERT( pData
); // DBG::
3284 cbBarInfo
& bar
= *pRow
->mBars
[i
];;
3286 cbBarShapeData
& data
= *((cbBarShapeData
*)pData
->Data());
3288 bar
.mBounds
= data
.mBounds
;
3289 bar
.mLenRatio
= data
.mLenRatio
;
3291 pData
= pData
->Next();
3295 /***** Implementation for class cbUpdatesManagerBase *****/
3297 IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase
, wxObject
)
3299 /***** Implementation for class cbPluginBase *****/
3301 IMPLEMENT_ABSTRACT_CLASS( cbPluginBase
, wxEvtHandler
)
3303 cbPluginBase::~cbPluginBase()
3308 bool cbPluginBase::ProcessEvent(wxEvent
& event
)
3310 if ( mPaneMask
== wxALL_PANES
)
3312 return wxEvtHandler::ProcessEvent( event
);
3314 // extract mask info. from received event
3316 cbPluginEvent
& evt
= *( (cbPluginEvent
*)&event
);
3318 if ( evt
.mpPane
== 0 &&
3319 mPaneMask
== wxALL_PANES
)
3321 return wxEvtHandler::ProcessEvent( event
);
3325 switch ( evt
.mpPane
->mAlignment
)
3327 case wxTOP
: mask
= wxTOP_PANE
; break;
3328 case wxBOTTOM
: mask
= wxBOTTOM_PANE
;break;
3329 case wxLEFT
: mask
= wxLEFT_PANE
; break;
3330 case wxRIGHT
: mask
= wxRIGHT_PANE
; break;
3333 // if event's pane maks matches the plugin's mask
3335 if ( mPaneMask
& mask
)
3337 return wxEvtHandler::ProcessEvent( event
);
3339 // otherwise pass to the next handler if present
3341 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event
) )