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
)
336 if ( pChild
->GetParent() )
338 bool success
= pChild
->GetParent()->GetChildren().DeleteObject( pChild
);
340 wxASSERT( success
); // DBG::
343 ::SetParent( (HWND
)pChild
->m_hWnd
, (HWND
)pNewParent
->m_hWnd
);
345 pNewParent
->GetChildren().Append( pChild
);
347 pChild
->SetParent( pNewParent
);
349 pChild
->Reparent(pNewParent
);
354 // FOR NOW:: floating with wxGtk still very buggy
360 //pChild->ReParent( pNewParent );
365 wxMessageBox( "Sorry, docking is not supported for ports other than MSW and wxGTK" );
368 void wxFrameLayout::DestroyBarWindows()
370 wxNode
* pSpy
= mBarSpyList
.First();
374 cbBarSpy
& spy
= *((cbBarSpy
*)pSpy
->Data());
376 if ( spy
.mpBarWnd
->GetEventHandler() == &spy
)
378 spy
.mpBarWnd
->PopEventHandler();
387 for( size_t i
= 0; i
!= mAllBars
.Count(); ++i
)
389 if ( mAllBars
[i
]->mpBarWnd
)
391 mAllBars
[i
]->mpBarWnd
->Destroy();
392 mAllBars
[i
]->mpBarWnd
= NULL
;
397 void wxFrameLayout::ShowFloatedWindows( bool show
)
399 wxNode
* pNode
= mFloatedFrames
.First();
403 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
407 pNode
= pNode
->Next();
411 wxFrameLayout::~wxFrameLayout()
415 if ( mpUpdatesMgr
) delete mpUpdatesMgr
;
417 // destoy the chain of plugins from left to right
419 wxEvtHandler
* pCur
= mpTopPlugin
;
423 while ( pCur
->GetPreviousHandler() )
425 pCur
= pCur
->GetPreviousHandler();
429 wxEvtHandler
* pNext
= pCur
->GetNextHandler();
436 // destroy contents of arrays and lists
440 for( i
= 0; i
!= MAX_PANES
; ++i
)
442 if ( mPanes
[i
] ) delete mPanes
[i
];
444 if ( mpHorizCursor
) delete mpHorizCursor
;
445 if ( mpVertCursor
) delete mpVertCursor
;
446 if ( mpNormalCursor
) delete mpNormalCursor
;
447 if ( mpDragCursor
) delete mpDragCursor
;
448 if ( mpDragCursor
) delete mpNECursor
;
450 wxNode
* pSpy
= mBarSpyList
.First();
454 cbBarSpy
& spy
= *((cbBarSpy
*)pSpy
->Data());
456 if ( spy
.mpBarWnd
->GetEventHandler() == &spy
)
458 spy
.mpBarWnd
->PopEventHandler();
465 for( i
= 0; i
!= mAllBars
.Count(); ++i
)
470 void wxFrameLayout::EnableFloating( bool enable
)
472 mFloatingOn
= enable
&& CanReparent();
475 void wxFrameLayout::Activate()
481 ShowFloatedWindows( TRUE
);
484 void wxFrameLayout::Deactivate()
486 ShowFloatedWindows( FALSE
);
493 void wxFrameLayout::SetFrameClient( wxWindow
* pFrameClient
)
495 mpFrameClient
= pFrameClient
;
498 wxWindow
* wxFrameLayout::GetFrameClient()
500 return mpFrameClient
;
503 cbUpdatesManagerBase
& wxFrameLayout::GetUpdatesManager()
505 if ( !mpUpdatesMgr
) mpUpdatesMgr
= CreateUpdatesManager();
507 return *mpUpdatesMgr
;
510 void wxFrameLayout::SetUpdatesManager( cbUpdatesManagerBase
* pUMgr
)
512 if ( mpUpdatesMgr
) delete mpUpdatesMgr
;
514 mpUpdatesMgr
= pUMgr
;
516 mpUpdatesMgr
->SetLayout( this );
519 cbUpdatesManagerBase
* wxFrameLayout::CreateUpdatesManager()
521 return new cbGCUpdatesMgr( this );
522 //return new cbSimpleUpdatesMgr( this );
525 void wxFrameLayout::AddBar( wxWindow
* pBarWnd
,
531 const wxString
& name
,
536 if ( pBarWnd
&& spyEvents
)
538 // hook up spy to bar window
539 cbBarSpy
* pSpy
= new cbBarSpy( this );
541 pSpy
->SetBarWindow( pBarWnd
);
542 pBarWnd
->PushEventHandler( pSpy
);
544 mBarSpyList
.Append( pSpy
);
547 cbBarInfo
* pInfo
= new cbBarInfo();
550 pInfo
->mpBarWnd
= pBarWnd
;
551 pInfo
->mDimInfo
= dimInfo
;
552 pInfo
->mState
= state
;
553 pInfo
->mAlignment
= alignment
;
554 pInfo
->mRowNo
= rowNo
;
555 pInfo
->mBounds
.x
= columnPos
;
557 mAllBars
.Add( pInfo
);
559 DoSetBarState( pInfo
);
562 bool wxFrameLayout::RedockBar( cbBarInfo
* pBar
,
563 const wxRect
& shapeInParent
,
569 pToPane
= HitTestPanes( shapeInParent
, NULL
);
573 return FALSE
; // bar's shape does not hit any pane
574 // - redocking is NOT posssible
576 cbDockPane
* pBarPane
= GetBarPane( pBar
);
580 GetUpdatesManager().OnStartChanges();
582 pBarPane
->RemoveBar( pBar
);
584 // FIXME FIXME:: the below recalc. may be a *huge* performance
585 // hit, it could be eliminated though...
586 // but first the "pane-postion-changed" problem
589 RecalcLayout( FALSE
);
591 pToPane
->InsertBar( pBar
, shapeInParent
);
593 RecalcLayout( FALSE
);
595 // finish update "transaction"
599 GetUpdatesManager().OnFinishChanges();
600 GetUpdatesManager().UpdateNow();
606 cbBarInfo
* wxFrameLayout::FindBarByName( const wxString
& name
)
608 for( size_t i
= 0; i
!= mAllBars
.Count(); ++i
)
610 if ( mAllBars
[i
]->mName
== name
)
617 BarArrayT
& wxFrameLayout::GetBars()
622 void wxFrameLayout::SetBarState( cbBarInfo
* pBar
, int newState
, bool updateNow
)
624 if ( newState
== wxCBAR_FLOATING
&& !mFloatingOn
)
630 GetUpdatesManager().OnStartChanges();
632 pBar
->mUMgrData
.SetDirty(TRUE
);
634 // check bar's previous state
636 if ( pBar
->mState
!= wxCBAR_HIDDEN
&& pBar
->mState
!= wxCBAR_FLOATING
)
641 bool success
= LocateBar( pBar
, &pRow
, &pPane
);
643 wxASSERT( success
); // DBG::
645 // save LRU-dim info before removing bar
647 pBar
->mDimInfo
.mLRUPane
= pPane
->GetAlignment();
648 pBar
->mDimInfo
.mBounds
[ pPane
->GetAlignment() ] = pBar
->mBounds
;
650 // remove it from the pane it was docked on
652 pPane
->RemoveBar( pBar
);
656 if ( pBar
->mState
== wxCBAR_FLOATING
&& newState
!= wxCBAR_FLOATING
)
658 // remove bar's window form the containing mini-frame
659 // and set it's parent to be layout's parent frame
661 if ( pBar
->mpBarWnd
)
663 pBar
->mpBarWnd
->Show(FALSE
); // to avoid flicker upon reparenting
665 wxNode
* pNode
= mFloatedFrames
.First();
669 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
671 if ( pFFrm
->GetBar() == pBar
)
673 pFFrm
->Show( FALSE
); // reduces flicker sligthly
675 ReparentWindow( pBar
->mpBarWnd
, &GetParentFrame() );
677 pBar
->mBounds
= pBar
->mDimInfo
.mBounds
[ pBar
->mDimInfo
.mLRUPane
];
679 if ( newState
!= wxCBAR_HIDDEN
)
681 pBar
->mAlignment
= pBar
->mDimInfo
.mLRUPane
;
683 mFloatedFrames
.DeleteNode( pNode
);
685 pFFrm
->Show( FALSE
);
686 pFFrm
->Destroy(); break;
689 pNode
= pNode
->Next();
692 // FOR NOW:: excessive!
693 //if ( mpFrameClient ) mpFrameClient->Refresh();
694 if ( mpFrameClient
) mClientWndRefreshPending
= TRUE
;
698 pBar
->mState
= newState
;
700 DoSetBarState( pBar
);
706 GetUpdatesManager().OnFinishChanges();
707 GetUpdatesManager().UpdateNow();
711 void wxFrameLayout::ApplyBarProperties( cbBarInfo
* pBar
)
713 if ( pBar
->mState
== wxCBAR_FLOATING
)
715 RepositionFloatedBar( pBar
);
718 if ( pBar
->mState
== wxCBAR_DOCKED_HORIZONTALLY
||
719 pBar
->mState
== wxCBAR_DOCKED_VERTICALLY
727 void wxFrameLayout::RepositionFloatedBar( cbBarInfo
* pBar
)
729 if ( !mFloatingOn
) return;
731 wxNode
* pNode
= mFloatedFrames
.First();
735 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
737 if ( pFFrm
->GetBar() == pBar
)
739 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
744 GetParentFrame().ClientToScreen( &x
, &y
);
746 pFFrm
->PositionFloatedWnd( x
,y
,
753 pNode
= pNode
->Next();
757 void wxFrameLayout::DoSetBarState( cbBarInfo
* pBar
)
759 if ( pBar
->mState
!= wxCBAR_FLOATING
&&
760 pBar
->mState
!= wxCBAR_HIDDEN
)
764 mPanes
[pBar
->mAlignment
]->InsertBar( pBar
);
766 if ( pBar
->mState
== wxCBAR_HIDDEN
)
770 if ( pBar
->mpBarWnd
)
772 pBar
->mpBarWnd
->Show( FALSE
);
776 if ( !mFloatingOn
) return;
780 if ( pBar
->mpBarWnd
== NULL
|| !CanReparent() )
782 // FOR NOW:: just hide it
784 if ( pBar
->mpBarWnd
)
786 pBar
->mpBarWnd
->Show( FALSE
);
788 pBar
->mState
== wxCBAR_HIDDEN
;
793 cbFloatedBarWindow
* pMiniFrm
= new cbFloatedBarWindow();
795 pMiniFrm
->SetBar( pBar
);
796 pMiniFrm
->SetLayout( this );
798 pMiniFrm
->Create( &GetParentFrame(), -1, pBar
->mName
,
801 wxFRAME_FLOAT_ON_PARENT
| wxFRAME_TOOL_WINDOW
804 pMiniFrm
->SetClient( pBar
->mpBarWnd
);
806 ReparentWindow( pBar
->mpBarWnd
, pMiniFrm
);
808 mFloatedFrames
.Append( pMiniFrm
);
810 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
812 // check if it wasn't floated anytime before
814 if ( bounds
.width
== -1 )
816 wxRect
& clntRect
= GetClientRect();
818 // adjust position into which the next floated bar will be placed
820 if ( mNextFloatedWndPos
.x
+ bounds
.width
> clntRect
.width
)
822 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
824 if ( mNextFloatedWndPos
.y
+ bounds
.height
> clntRect
.height
)
826 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
828 bounds
.x
= mNextFloatedWndPos
.x
+ clntRect
.x
;
829 bounds
.y
= mNextFloatedWndPos
.y
+ clntRect
.y
;
831 bounds
.width
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].x
;
832 bounds
.height
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].y
;
834 mNextFloatedWndPos
.x
+= mFloatingPosStep
.x
;
835 mNextFloatedWndPos
.y
+= mFloatingPosStep
.y
;
838 pMiniFrm
->Show( TRUE
);
840 // FIXME:: this is excessive
841 pBar
->mpBarWnd
->Show(TRUE
);
845 void wxFrameLayout::RemoveBar( cbBarInfo
* pBarInfo
)
847 // first, try to "guess" what was the perviouse state of the bar
852 if ( LocateBar( pBarInfo
, &pRow
, &pPane
) )
854 // ...aha, bar was docked into one of the panes,
855 // remove it from there
857 pPane
->RemoveBar( pBarInfo
);
860 for( size_t i
= 0; i
!= mAllBars
.Count(); ++i
)
862 if ( mAllBars
[i
] == pBarInfo
)
864 mAllBars
.Remove( i
);
866 if ( pBarInfo
->mpBarWnd
) // hides it's window
868 pBarInfo
->mpBarWnd
->Show( FALSE
);
875 wxASSERT(0); // DBG:: bar info should be present in the list of all bars of all panes
879 bool wxFrameLayout::LocateBar( cbBarInfo
* pBarInfo
,
881 cbDockPane
** ppPane
)
886 for( int n
= 0; n
!= MAX_PANES
; ++n
)
888 wxBarIterator
i( mPanes
[n
]->GetRowList() );
892 if ( &i
.BarInfo() == pBarInfo
)
894 (*ppPane
) = mPanes
[n
];
895 (*ppRow
) = &i
.RowInfo();
904 void wxFrameLayout::RecalcLayout( bool repositionBarsNow
)
906 mRecalcPending
= FALSE
;
908 int frmWidth
, frmHeight
;
909 mpFrame
->GetClientSize( &frmWidth
, &frmHeight
);
916 // pane positioning priorities in decreasing order:
917 // top, bottom, left, right
921 cbDockPane
* pPane
= mPanes
[ wxTOP
];
924 pPane
->SetPaneWidth( frmWidth
);
925 pPane
->RecalcLayout();
927 paneHeight
= pPane
->GetPaneHeight();
931 rect
.width
= frmWidth
;
932 rect
.height
= wxMin( paneHeight
, frmHeight
- curY
);
934 pPane
->SetBoundsInParent( rect
);
940 pPane
= mPanes
[ wxBOTTOM
];
942 pPane
->SetPaneWidth( frmWidth
);
943 pPane
->RecalcLayout();
945 paneHeight
= pPane
->GetPaneHeight();
948 rect
.y
= wxMax( frmHeight
- paneHeight
, curY
);
949 rect
.width
= frmWidth
;
950 rect
.height
= frmHeight
- rect
.y
;
952 pPane
->SetBoundsInParent( rect
);
956 pPane
= mPanes
[ wxLEFT
];
959 pPane
->SetPaneWidth( rect
.y
- curY
);
961 pPane
->RecalcLayout();
962 paneHeight
= pPane
->GetPaneHeight();
965 rect
.height
= rect
.y
- curY
;
968 rect
.width
= wxMin( paneHeight
, frmWidth
);
970 pPane
->SetBoundsInParent( rect
);
976 pPane
= mPanes
[ wxRIGHT
];
978 // left pane's height
979 pPane
->SetPaneWidth( rect
.height
);
981 pPane
->RecalcLayout();
982 paneHeight
= pPane
->GetPaneHeight();
984 // left pane's height
985 rect
.height
= rect
.height
;
986 rect
.x
= wxMax( frmWidth
- paneHeight
, curX
);
988 rect
.width
= frmWidth
- rect
.x
;
990 pPane
->SetBoundsInParent( rect
);
992 // recalc bounds of the client-window
994 mClntWndBounds
.x
= mPanes
[wxLEFT
]->mBoundsInParent
.x
+
995 mPanes
[wxLEFT
]->mBoundsInParent
.width
;
996 mClntWndBounds
.y
= mPanes
[wxTOP
]->mBoundsInParent
.y
+
997 mPanes
[wxTOP
]->mBoundsInParent
.height
;
999 mClntWndBounds
.width
= mPanes
[wxRIGHT
]->mBoundsInParent
.x
-
1001 mClntWndBounds
.height
= mPanes
[wxBOTTOM
]->mBoundsInParent
.y
-
1004 if ( repositionBarsNow
)
1009 int wxFrameLayout::GetClientHeight()
1011 // for better portablility wxWindow::GetSzie() is not used here
1013 return mClntWndBounds
.height
;
1016 int wxFrameLayout::GetClientWidth()
1018 // for better portablility wxWindow::GetSzie() is not used here
1020 return mClntWndBounds
.width
;
1023 void wxFrameLayout::PositionClientWindow()
1025 if ( mpFrameClient
)
1027 if ( mClntWndBounds
.width
>= 1 && mClntWndBounds
.height
>= 1 )
1029 mpFrameClient
->SetSize( mClntWndBounds
.x
, mClntWndBounds
.y
,
1030 mClntWndBounds
.width
, mClntWndBounds
.height
, 0 );
1032 if ( !mpFrameClient
->IsShown() )
1034 mpFrameClient
->Show( TRUE
);
1037 mpFrameClient
->Show( FALSE
);
1041 void wxFrameLayout::PositionPanes()
1043 PositionClientWindow();
1045 // FOR NOW:: excessive updates!
1046 // reposition bars within all panes
1048 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1050 mPanes
[i
]->SizePaneObjects();
1053 void wxFrameLayout::OnSize( wxSizeEvent
& event
)
1055 if ( event
.GetEventObject() == (wxObject
*) mpFrame
)
1060 /*** protected members ***/
1062 void wxFrameLayout::HideBarWindows()
1064 for( size_t i
= 0; i
!= mAllBars
.Count(); ++i
)
1066 if ( mAllBars
[i
]->mpBarWnd
&& mAllBars
[i
]->mState
!= wxCBAR_FLOATING
)
1068 mAllBars
[i
]->mpBarWnd
->Show( FALSE
);
1070 // then floated frames
1072 ShowFloatedWindows( FALSE
);
1074 if ( mpFrameClient
)
1076 mpFrameClient
->Show( FALSE
);
1079 void wxFrameLayout::UnhookFromFrame()
1081 // NOTE:: the SetEvtHandlerEnabled() method is not used
1082 // here, since it is assumed, that unhooking layout
1083 // from window may result destroying of the layout itself
1085 // BUG BUG BUG (wx):: this would not be a problem if
1086 // wxEvtHandler's destructor would check if
1087 // this handler is currently the top-most
1088 // handler of some window, and additionally
1089 // to the reconnecting itself from the chain
1090 // it would also re-setup current event handler
1091 // of the window using wxWindow::SetEventHandler()
1095 if ( mpFrame
->GetEventHandler() == this )
1097 mpFrame
->PopEventHandler();
1103 if ( this == mpFrame
->GetEventHandler() )
1105 mpFrame
->SetEventHandler( this->GetNextHandler() );
1108 wxEvtHandler
* pCur
= mpFrame
->GetEventHandler();
1112 if ( pCur
== this ); break;
1114 pCur
= pCur
->GetNextHandler();
1117 // do not try to unhook ourselves if we're not hooked yet
1118 if ( !pCur
) return;
1121 if ( GetPreviousHandler() )
1123 GetPreviousHandler()->SetNextHandler( GetNextHandler() );
1126 mpFrame
->PopEventHandler();
1131 if ( GetNextHandler() )
1133 GetNextHandler()->SetPreviousHandler( GetPreviousHandler() );
1135 SetNextHandler( NULL
);
1136 SetPreviousHandler( NULL
);
1140 void wxFrameLayout::HookUpToFrame()
1142 // unhook us first, we're already hooked up
1146 // put ourselves on top
1148 mpFrame
->PushEventHandler( this );
1151 cbDockPane
* wxFrameLayout::GetBarPane( cbBarInfo
* pBar
)
1153 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1155 if ( mPanes
[i
]->BarPresent( pBar
) ) return mPanes
[i
];
1160 void wxFrameLayout::CreateCursors()
1163 // FIXME:: the below code somehow doesn't work - curosors ramain unchaged
1166 set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
1168 mpHorizCursor = new wxCursor( bits, 32, 16 );
1170 set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
1172 mpVertCursor = new wxCursor( bits, 32, 16 );
1175 // FOR NOW:: use standard ones
1177 mpHorizCursor
= new wxCursor(wxCURSOR_SIZEWE
);
1178 mpVertCursor
= new wxCursor(wxCURSOR_SIZENS
);
1179 mpNormalCursor
= new wxCursor(wxCURSOR_ARROW
);
1180 mpDragCursor
= new wxCursor(wxCURSOR_CROSS
);
1181 mpNECursor
= new wxCursor(wxCURSOR_NO_ENTRY
);
1183 mFloatingPosStep
.x
= 25;
1184 mFloatingPosStep
.y
= 25;
1186 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
1187 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
1190 bool wxFrameLayout::HitTestPane( cbDockPane
* pPane
, int x
, int y
)
1192 return rect_contains_point( pPane
->GetRealRect(), x
, y
);
1195 cbDockPane
* wxFrameLayout::HitTestPanes( const wxRect
& rect
,
1196 cbDockPane
* pCurPane
)
1198 // first, give the privilege to the current pane
1200 if ( pCurPane
&& rect_hits_rect( pCurPane
->GetRealRect(), rect
) )
1204 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1206 if ( pCurPane
!= mPanes
[i
] &&
1207 rect_hits_rect( mPanes
[i
]->GetRealRect(), rect
) )
1214 void wxFrameLayout::ForwardMouseEvent( wxMouseEvent
& event
,
1215 cbDockPane
* pToPane
,
1218 wxPoint
pos( event
.m_x
, event
.m_y
);
1219 pToPane
->FrameToPane( &pos
.x
, &pos
.y
);
1221 switch ( eventType
)
1223 case cbEVT_PL_LEFT_DOWN
: { cbLeftDownEvent
evt( pos
, pToPane
);
1224 FirePluginEvent( evt
); break;
1227 case cbEVT_PL_LEFT_DCLICK
:{ cbLeftDClickEvent
evt( pos
, pToPane
);
1228 FirePluginEvent( evt
); break;
1231 case cbEVT_PL_LEFT_UP
: { cbLeftUpEvent
evt( pos
, pToPane
);
1232 FirePluginEvent( evt
); break;
1235 case cbEVT_PL_RIGHT_DOWN
: { cbRightDownEvent
evt( pos
, pToPane
);
1236 FirePluginEvent( evt
); break;
1239 case cbEVT_PL_RIGHT_UP
: { cbRightUpEvent
evt( pos
, pToPane
);
1240 FirePluginEvent( evt
); break;
1243 case cbEVT_PL_MOTION
: { cbMotionEvent
evt( pos
, pToPane
);
1244 FirePluginEvent( evt
); break;
1247 default : wxASSERT(0); // DBG::
1252 void wxFrameLayout::RouteMouseEvent( wxMouseEvent
& event
, int pluginEvtType
)
1254 if ( mpPaneInFocus
)
1256 ForwardMouseEvent( event
, mpPaneInFocus
, pluginEvtType
);
1258 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1260 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1262 ForwardMouseEvent( event
, mPanes
[i
], pluginEvtType
);
1268 /*** event handlers ***/
1270 void wxFrameLayout::OnRButtonDown( wxMouseEvent
& event
)
1272 RouteMouseEvent( event
, cbEVT_PL_RIGHT_DOWN
);
1275 void wxFrameLayout::OnRButtonUp( wxMouseEvent
& event
)
1277 RouteMouseEvent( event
, cbEVT_PL_RIGHT_UP
);
1280 void wxFrameLayout::OnLButtonDown( wxMouseEvent
& event
)
1282 RouteMouseEvent( event
, cbEVT_PL_LEFT_DOWN
);
1285 void wxFrameLayout::OnLDblClick( wxMouseEvent
& event
)
1287 RouteMouseEvent( event
, cbEVT_PL_LEFT_DCLICK
);
1290 void wxFrameLayout::OnLButtonUp( wxMouseEvent
& event
)
1292 RouteMouseEvent( event
, cbEVT_PL_LEFT_UP
);
1295 void wxFrameLayout::OnMouseMove( wxMouseEvent
& event
)
1297 if ( mpPaneInFocus
)
1299 ForwardMouseEvent( event
, mpPaneInFocus
, cbEVT_PL_MOTION
);
1301 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1303 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1305 if ( mpLRUPane
&& mpLRUPane
!= mPanes
[i
] )
1307 // simulate "mouse-leave" event
1308 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1311 ForwardMouseEvent( event
, mPanes
[i
], cbEVT_PL_MOTION
);
1313 mpLRUPane
= mPanes
[i
];
1320 // simulate "mouse-leave" event
1321 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1326 void wxFrameLayout::OnPaint( wxPaintEvent
& event
)
1328 if ( mRecalcPending
)
1330 RecalcLayout( TRUE
);
1332 wxPaintDC
dc(mpFrame
);
1334 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1336 wxRect
& rect
= mPanes
[i
]->mBoundsInParent
;
1338 dc
.SetClippingRegion( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1340 mPanes
[i
]->PaintPane(dc
);
1342 dc
.DestroyClippingRegion();
1348 void wxFrameLayout::OnEraseBackground( wxEraseEvent
& event
)
1353 void wxFrameLayout::OnIdle( wxIdleEvent
& event
)
1355 wxWindow
* focus
= wxWindow::FindFocus();
1357 if ( !focus
&& mCheckFocusWhenIdle
)
1359 wxMessageBox( "Hi, no more focus in this app!" );
1361 mCheckFocusWhenIdle
= FALSE
;
1362 //ShowFloatedWindows( FALSE );
1365 mCheckFocusWhenIdle
= FALSE
;
1371 void wxFrameLayout::OnKillFocus( wxFocusEvent
& event
)
1373 //wxMessageBox( "wxFrameLayoutGot Kill Focus!" );
1374 //ShowFloatedWindows( FALSE );
1377 void wxFrameLayout::OnSetFocus( wxFocusEvent
& event
)
1379 //ShowFloatedWindows( TRUE );
1382 void wxFrameLayout::OnActivate( wxActivateEvent
& event
)
1385 if ( event
.GetActive() == FALSE
)
1387 wxWindow
* focus
= wxWindow::FindFocus();
1389 if ( !focus
|| focus
== &GetParentFrame() )
1391 mCheckFocusWhenIdle
= TRUE
;
1395 wxMessageBox("Deactivated!" );
1402 void wxFrameLayout::GetPaneProperties( cbCommonPaneProperties
& props
, int alignment
)
1404 props
= mPanes
[alignment
]->mProps
;
1407 void wxFrameLayout::SetPaneProperties( const cbCommonPaneProperties
& props
, int paneMask
)
1409 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1411 if ( mPanes
[i
]->MatchesMask( paneMask
) )
1413 mPanes
[i
]->mProps
= props
;
1416 void wxFrameLayout::SetMargins( int top
, int bottom
, int left
, int right
,
1419 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1421 cbDockPane
& pane
= *mPanes
[i
];
1423 if ( pane
.MatchesMask( paneMask
) )
1425 pane
.mTopMargin
= top
;
1426 pane
.mBottomMargin
= bottom
;
1427 pane
.mLeftMargin
= left
;
1428 pane
.mRightMargin
= right
;
1433 void wxFrameLayout::SetPaneBackground( const wxColour
& colour
)
1435 mBorderPen
.SetColour( colour
);
1438 void wxFrameLayout::RefreshNow( bool recalcLayout
)
1440 if ( recalcLayout
) RecalcLayout( TRUE
);
1442 if ( mpFrame
) mpFrame
->Refresh();
1445 /*** plugin-related methods ***/
1447 void wxFrameLayout::FirePluginEvent( cbPluginEvent
& event
)
1449 // check state of input capture, before processing the event
1451 if ( mpCaputesInput
)
1453 bool isInputEvt
= TRUE
;
1455 switch ( event
.m_eventType
)
1457 case cbEVT_PL_LEFT_DOWN
: break;
1458 case cbEVT_PL_LEFT_UP
: break;
1459 case cbEVT_PL_RIGHT_DOWN
: break;
1460 case cbEVT_PL_RIGHT_UP
: break;
1461 case cbEVT_PL_MOTION
: break;
1463 default : isInputEvt
= FALSE
; break;
1468 mpCaputesInput
->ProcessEvent( event
);
1473 GetTopPlugin().ProcessEvent( event
);
1476 void wxFrameLayout::CaptureEventsForPlugin ( cbPluginBase
* pPlugin
)
1478 // cannot capture events for more than one plugin at a time
1479 wxASSERT( mpCaputesInput
== NULL
);
1481 mpCaputesInput
= pPlugin
;
1485 void wxFrameLayout::ReleaseEventsFromPlugin( cbPluginBase
* pPlugin
)
1487 // events should be captured first
1488 wxASSERT( mpCaputesInput
!= NULL
);
1490 mpCaputesInput
= NULL
;
1493 void wxFrameLayout::CaptureEventsForPane( cbDockPane
* toPane
)
1495 // cannot capture events twice (without releasing)
1496 wxASSERT( mpPaneInFocus
== NULL
);
1498 mpFrame
->CaptureMouse();
1500 mpPaneInFocus
= toPane
;
1503 void wxFrameLayout::ReleaseEventsFromPane( cbDockPane
* fromPane
)
1505 // cannot release events without capturing them
1506 wxASSERT( mpPaneInFocus
!= NULL
);
1508 mpFrame
->ReleaseMouse();
1510 mpPaneInFocus
= NULL
;
1513 cbPluginBase
& wxFrameLayout::GetTopPlugin()
1517 PushDefaultPlugins(); // automatic configuration
1519 return *mpTopPlugin
;
1522 void wxFrameLayout::SetTopPlugin( cbPluginBase
* pPlugin
)
1524 mpTopPlugin
= pPlugin
;
1527 bool wxFrameLayout::HasTopPlugin()
1529 return ( mpTopPlugin
!= NULL
);
1532 void wxFrameLayout::PushPlugin( cbPluginBase
* pPlugin
)
1536 mpTopPlugin
= pPlugin
;
1539 pPlugin
->SetNextHandler( mpTopPlugin
);
1541 mpTopPlugin
->SetPreviousHandler( pPlugin
);
1543 mpTopPlugin
= pPlugin
;
1546 mpTopPlugin
->OnInitPlugin(); // notification
1549 void wxFrameLayout::PopPlugin()
1551 wxASSERT( mpTopPlugin
); // DBG:: at least one plugin should be present
1553 cbPluginBase
* pPopped
= mpTopPlugin
;
1555 mpTopPlugin
= (cbPluginBase
*)mpTopPlugin
->GetNextHandler();
1560 void wxFrameLayout::PopAllPlugins()
1562 while( mpTopPlugin
) PopPlugin();
1565 void wxFrameLayout::PushDefaultPlugins()
1567 // FIXME:: to much of the stuff for the default...
1569 AddPlugin( CLASSINFO( cbRowLayoutPlugin
) );
1570 AddPlugin( CLASSINFO( cbBarDragPlugin
) );
1571 AddPlugin( CLASSINFO( cbPaneDrawPlugin
) );
1574 void wxFrameLayout::AddPlugin( wxClassInfo
* pPlInfo
, int paneMask
)
1576 if ( FindPlugin ( pPlInfo
) ) return; // same type of plugin cannot be added twice
1578 cbPluginBase
* pObj
= (cbPluginBase
*)pPlInfo
->CreateObject();
1580 wxASSERT(pObj
); // DBG:: plugin's class should be dynamic
1582 pObj
->mPaneMask
= paneMask
;
1583 pObj
->mpLayout
= this;
1588 void wxFrameLayout::AddPluginBefore( wxClassInfo
* pNextPlInfo
, wxClassInfo
* pPlInfo
,
1591 wxASSERT( pNextPlInfo
!= pPlInfo
); // DBG:: no sence
1593 cbPluginBase
* pNextPl
= FindPlugin( pNextPlInfo
);
1597 AddPlugin( pPlInfo
, paneMask
);
1602 // remove existing one if present
1604 cbPluginBase
* pExistingPl
= FindPlugin( pPlInfo
);
1606 if ( pExistingPl
) RemovePlugin( pPlInfo
);
1608 // create an instance
1610 cbPluginBase
* pNewPl
= (cbPluginBase
*)pPlInfo
->CreateObject();
1612 wxASSERT(pNewPl
); // DBG:: plugin's class should be dynamic
1614 // insert it to the chain
1616 if ( pNextPl
->GetPreviousHandler() )
1618 pNextPl
->GetPreviousHandler()->SetNextHandler( pNewPl
);
1620 mpTopPlugin
= pNewPl
;
1622 pNewPl
->SetNextHandler( pNextPl
);
1624 pNewPl
->SetPreviousHandler( pNextPl
->GetPreviousHandler() );
1626 pNextPl
->SetPreviousHandler( pNewPl
);
1630 pNewPl
->mPaneMask
= paneMask
;
1631 pNewPl
->mpLayout
= this;
1633 pNewPl
->OnInitPlugin();
1636 void wxFrameLayout::RemovePlugin( wxClassInfo
* pPlInfo
)
1638 cbPluginBase
* pPlugin
= FindPlugin( pPlInfo
);
1640 if ( !pPlugin
) return; // it's OK to remove not-existing plugin ;-)
1642 if ( pPlugin
->GetPreviousHandler() == NULL
)
1644 mpTopPlugin
= (cbPluginBase
*)pPlugin
->GetNextHandler();
1649 cbPluginBase
* wxFrameLayout::FindPlugin( wxClassInfo
* pPlInfo
)
1651 cbPluginBase
*pCur
= mpTopPlugin
;
1655 // NOTE:: it might appear usefull matching plugin
1656 // classes "polymorphically":
1658 if ( pCur
->GetClassInfo()->IsKindOf( pPlInfo
) )
1662 pCur
= (cbPluginBase
*)pCur
->GetNextHandler();
1668 /***** Implementation for class cbUpdateMgrData *****/
1670 IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData
, wxObject
)
1672 cbUpdateMgrData::cbUpdateMgrData()
1674 : mPrevBounds( -1,-1,0,0 ),
1675 mIsDirty( TRUE
) // inidicate initial change
1678 void cbUpdateMgrData::StoreItemState( const wxRect
& boundsInParent
)
1680 mPrevBounds
= boundsInParent
;
1683 void cbUpdateMgrData::SetDirty( bool isDirty
)
1688 void cbUpdateMgrData::SetCustomData( wxObject
* pCustomData
)
1690 mpCustomData
= pCustomData
;
1693 /***** Implementation for class cbDockPane *****/
1695 void wxBarIterator::Reset()
1697 mpRow
= ( mpRows
->Count() ) ? (*mpRows
)[0] : NULL
;
1701 wxBarIterator::wxBarIterator( RowArrayT
& rows
)
1710 bool wxBarIterator::Next()
1715 mpBar
= mpBar
->mpNext
;
1718 if ( mpRow
->mBars
.GetCount() == 0 )
1723 mpBar
= mpRow
->mBars
[0];
1728 // skip to the next row
1730 mpRow
= mpRow
->mpNext
;
1734 mpBar
= mpRow
->mBars
[0];
1745 cbBarInfo
& wxBarIterator::BarInfo()
1750 cbRowInfo
& wxBarIterator::RowInfo()
1755 /***** Implementation for class cbBarDimHandlerBase *****/
1757 IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase
, wxObject
)
1759 cbBarDimHandlerBase::cbBarDimHandlerBase()
1763 void cbBarDimHandlerBase::AddRef()
1768 void cbBarDimHandlerBase::RemoveRef()
1770 if ( --mRefCount
<= 0 ) delete this;
1773 /***** Implementation for class cbDimInfo *****/
1775 IMPLEMENT_DYNAMIC_CLASS( cbDimInfo
, wxObject
)
1777 cbDimInfo::cbDimInfo()
1785 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1790 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1794 cbDimInfo::cbDimInfo( cbBarDimHandlerBase
* pDimHandler
,
1799 mIsFixed ( isFixed
),
1801 mpHandler( pDimHandler
)
1805 int vtad
= *((int*)mpHandler
);
1806 mpHandler
->AddRef();
1809 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1814 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1818 cbDimInfo::cbDimInfo( int dh_x
, int dh_y
,
1826 cbBarDimHandlerBase
* pDimHandler
1828 : mHorizGap ( horizGap
),
1829 mVertGap ( vertGap
),
1830 mIsFixed ( isFixed
),
1831 mpHandler( pDimHandler
)
1835 int vtad
= *((int*)mpHandler
);
1836 mpHandler
->AddRef();
1840 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= dh_x
;
1841 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= dh_y
;
1842 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= dv_x
;
1843 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= dv_y
;
1844 mSizes
[wxCBAR_FLOATING
].x
= f_x
;
1845 mSizes
[wxCBAR_FLOATING
].y
= f_y
;
1848 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1850 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1853 cbDimInfo::~cbDimInfo()
1857 mpHandler
->RemoveRef();
1860 const cbDimInfo
& cbDimInfo::operator=( cbDimInfo
& other
)
1862 if ( this == &other
) return *this;
1864 for( int i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1866 mSizes
[i
] = other
.mSizes
[i
];
1868 mIsFixed
= other
.mIsFixed
;
1869 mpHandler
= other
.mpHandler
;
1871 mVertGap
= other
.mVertGap
;
1872 mHorizGap
= other
.mHorizGap
;
1876 mpHandler
->AddRef();
1881 /***** Implementation for structure cbCommonPaneProperties *****/
1883 IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties
, wxObject
)
1885 cbCommonPaneProperties::cbCommonPaneProperties(void)
1887 : mRealTimeUpdatesOn ( TRUE
),
1888 mOutOfPaneDragOn ( TRUE
),
1889 mExactDockPredictionOn( FALSE
),
1890 mNonDestructFirctionOn( FALSE
),
1891 mShow3DPaneBorderOn ( TRUE
),
1892 mBarFloatingOn ( FALSE
),
1893 mRowProportionsOn ( FALSE
),
1894 mColProportionsOn ( TRUE
),
1895 mBarCollapseIconsOn ( FALSE
),
1896 mBarDragHintsOn ( FALSE
),
1898 mMinCBarDim( 16, 16 ),
1899 mResizeHandleSize( 4 )
1902 /***** Implementation for class cbRowInfo *****/
1904 IMPLEMENT_DYNAMIC_CLASS( cbRowInfo
, wxObject
)
1906 cbRowInfo::cbRowInfo(void)
1910 mNotFixedBarsCnt( FALSE
),
1911 mpExpandedBar ( NULL
)
1914 cbRowInfo::~cbRowInfo()
1916 // nothing! all bars are removed using global bar
1917 // list in wxFrameLayout class
1920 /***** Implementation for class cbBarInfo *****/
1922 IMPLEMENT_DYNAMIC_CLASS( cbBarInfo
, wxObject
)
1924 cbBarInfo::cbBarInfo(void)
1932 cbBarInfo::~cbBarInfo()
1937 /***** Implementation for class cbDockPane *****/
1939 IMPLEMENT_DYNAMIC_CLASS( cbDockPane
, wxObject
)
1941 // FIXME:: how to eliminate these cut&pasted constructors?
1943 cbDockPane::cbDockPane(void)
1946 mPaneWidth ( 32768 ), // fake-up very large pane dims,
1947 // since the real dimensions of the pane may not
1948 // be known, while inserting bars initially
1949 mPaneHeight( 32768 ),
1951 mpStoredRow( NULL
),
1958 cbDockPane::cbDockPane( int alignment
, wxFrameLayout
* pPanel
)
1960 : mpLayout ( pPanel
),
1961 mPaneWidth ( 32768 ), // fake-up very large pane dims,
1962 // since the real dimensions of the pane may not
1963 // be known, while inserting bars initially
1964 mPaneHeight( 32768 ),
1965 mAlignment ( alignment
),
1966 mpStoredRow( NULL
),
1974 cbDockPane::~cbDockPane()
1976 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
1980 mRowShapeData
.DeleteContents( TRUE
);
1982 // NOTE:: control bar infromation structures are cleaned-up
1983 // in wxFrameLayout's destructor, using global control-bar list
1986 void cbDockPane::SetMargins( int top
, int bottom
, int left
, int right
)
1989 mBottomMargin
= bottom
;
1991 mRightMargin
= right
;
1994 /*** helpers of cbDockPane ***/
1996 void cbDockPane::PaintBarDecorations( cbBarInfo
* pBar
, wxDC
& dc
)
1998 cbDrawBarDecorEvent
evt( pBar
, dc
, this );
2000 mpLayout
->FirePluginEvent( evt
);
2003 void cbDockPane::PaintBarHandles( cbBarInfo
* pBar
, wxDC
& dc
)
2005 cbDrawBarHandlesEvent
evt( pBar
, dc
, this );
2007 mpLayout
->FirePluginEvent( evt
);
2010 void cbDockPane::PaintBar( cbBarInfo
* pBar
, wxDC
& dc
)
2012 PaintBarDecorations( pBar
, dc
);
2013 PaintBarHandles( pBar
, dc
);
2016 void cbDockPane::PaintRowHandles( cbRowInfo
* pRow
, wxDC
& dc
)
2018 cbDrawRowHandlesEvent
evt( pRow
, dc
, this );
2020 mpLayout
->FirePluginEvent( evt
);
2022 cbDrawRowDecorEvent
evt1( pRow
, dc
, this );
2024 mpLayout
->FirePluginEvent( evt1
);
2027 void cbDockPane::PaintRowBackground ( cbRowInfo
* pRow
, wxDC
& dc
)
2029 cbDrawRowBkGroundEvent
evt( pRow
, dc
, this );
2031 mpLayout
->FirePluginEvent( evt
);
2034 void cbDockPane::PaintRowDecorations( cbRowInfo
* pRow
, wxDC
& dc
)
2038 // decorations first
2039 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2041 PaintBarDecorations( pRow
->mBars
[i
], dc
);
2043 // then handles if present
2044 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2046 PaintBarHandles( pRow
->mBars
[i
], dc
);
2049 void cbDockPane::PaintRow( cbRowInfo
* pRow
, wxDC
& dc
)
2051 PaintRowBackground ( pRow
, dc
);
2052 PaintRowDecorations( pRow
, dc
);
2053 PaintRowHandles ( pRow
, dc
);
2056 void cbDockPane::PaintPaneBackground( wxDC
& dc
)
2058 cbDrawPaneBkGroundEvent
evt( dc
, this );
2060 mpLayout
->FirePluginEvent( evt
);
2063 void cbDockPane::PaintPaneDecorations( wxDC
& dc
)
2065 cbDrawPaneDecorEvent
evt( dc
, this );
2067 mpLayout
->FirePluginEvent( evt
);
2070 void cbDockPane::PaintPane( wxDC
& dc
)
2072 PaintPaneBackground( dc
);
2076 // first decorations
2077 for( i
= 0; i
!= mRows
.Count(); ++i
)
2079 PaintRowBackground( mRows
[i
], dc
);
2080 PaintRowDecorations( mRows
[i
], dc
);
2084 for( i
= 0; i
!= mRows
.Count(); ++i
)
2086 PaintRowHandles( mRows
[i
], dc
);
2089 PaintPaneDecorations( dc
);
2092 void cbDockPane::SizeBar( cbBarInfo
* pBar
)
2094 cbSizeBarWndEvent
evt( pBar
, this );
2096 mpLayout
->FirePluginEvent( evt
);
2100 void cbDockPane::SizeRowObjects( cbRowInfo
* pRow
)
2102 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2104 SizeBar( pRow
->mBars
[i
] );
2107 void cbDockPane::SizePaneObjects()
2109 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2111 SizeRowObjects( mRows
[i
] );
2114 wxDC
* cbDockPane::StartDrawInArea( const wxRect
& area
)
2118 cbStartDrawInAreaEvent
evt( area
, &pDc
, this );
2120 mpLayout
->FirePluginEvent( evt
);
2125 void cbDockPane::FinishDrawInArea( const wxRect
& area
)
2127 cbFinishDrawInAreaEvent
evt( area
, this );
2129 mpLayout
->FirePluginEvent( evt
);
2132 bool cbDockPane::IsFixedSize( cbBarInfo
* pInfo
)
2134 return ( pInfo
->mDimInfo
.mIsFixed
);
2137 int cbDockPane::GetNotFixedBarsCount( cbRowInfo
* pRow
)
2141 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2143 if ( !pRow
->mBars
[i
]->IsFixed() ) ++cnt
;
2148 void cbDockPane::RemoveBar( cbBarInfo
* pBar
)
2150 bool needsRestoring
= mProps
.mNonDestructFirctionOn
&&
2151 mpStoredRow
== pBar
->mpRow
;
2153 cbRemoveBarEvent
evt( pBar
, this );
2155 mpLayout
->FirePluginEvent( evt
);
2157 if ( needsRestoring
)
2159 SetRowShapeData( mpStoredRow
, &mRowShapeData
);
2165 void cbDockPane::SyncRowFlags( cbRowInfo
* pRow
)
2167 // setup mHasOnlyFixedBars flag for the row information
2168 pRow
->mHasOnlyFixedBars
= TRUE
;
2170 pRow
->mNotFixedBarsCnt
= 0;
2172 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2174 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2178 if ( !bar
.IsFixed() )
2180 pRow
->mHasOnlyFixedBars
= FALSE
;
2181 ++pRow
->mNotFixedBarsCnt
;
2186 void cbDockPane::FrameToPane( long* x
, long* y
)
2191 if ( mAlignment
== wxTOP
||
2192 mAlignment
== wxBOTTOM
2195 *x
-= mBoundsInParent
.x
;
2196 *y
-= mBoundsInParent
.y
;
2200 int rx
= *x
, ry
= *y
;
2202 *x
= ry
- mBoundsInParent
.y
;
2204 *y
= rx
- mBoundsInParent
.x
;
2208 void cbDockPane::PaneToFrame( long* x
, long* y
)
2210 if ( mAlignment
== wxTOP
||
2211 mAlignment
== wxBOTTOM
2214 *x
+= mBoundsInParent
.x
;
2215 *y
+= mBoundsInParent
.y
;
2219 int rx
= *x
, ry
= *y
;
2221 *x
= ry
+ mBoundsInParent
.x
;
2223 *y
= mBoundsInParent
.y
+ rx
;
2230 void cbDockPane::FrameToPane( wxRect
* pRect
)
2232 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2233 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2234 pRect
->y
+ pRect
->height
);
2236 FrameToPane( &upperLeft
.x
, &upperLeft
.y
);
2237 FrameToPane( &lowerRight
.x
, &lowerRight
.y
);
2239 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2240 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2242 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2243 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2246 void cbDockPane::PaneToFrame( wxRect
* pRect
)
2248 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2249 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2250 pRect
->y
+ pRect
->height
);
2252 PaneToFrame( &upperLeft
.x
, &upperLeft
.y
);
2253 PaneToFrame( &lowerRight
.x
, &lowerRight
.y
);
2255 //wxRect newRect = wxRect( upperLeft, lowerRight );
2257 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2258 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2260 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2261 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2264 int cbDockPane::GetRowAt( int paneY
)
2266 if ( paneY
< 0 ) return -1;
2272 for( ; i
!= mRows
.Count(); ++i
)
2274 int rowHeight
= mRows
[i
]->mRowHeight
;
2276 int third
= rowHeight
/3;
2278 if ( paneY
>= curY
&& paneY
< curY
+ third
)
2281 if ( paneY
>= curY
+ third
&& paneY
< curY
+ rowHeight
- third
)
2290 int cbDockPane::GetRowAt( int upperY
, int lowerY
)
2294 int range = lowerY - upperY;
2295 int oneThird = range / 3;
2297 wxNode* pRow = mRows.First();
2301 if ( lowerY <= 0 ) return -1;
2305 int rowHeight = GetRowHeight( (wxList*)pRow->Data() );
2307 if ( upperY >= curY &&
2308 lowerY < curY ) return row;
2310 if ( upperY <= curY &&
2312 curY - upperY >= oneThird ) return row-1;
2314 if ( ( upperY < curY + rowHeight &&
2315 lowerY >= curY + rowHeight &&
2316 curY + rowHeight - lowerY >= oneThird )
2320 if ( lowerY <= curY + rowHeight ) return row;
2324 pRow = pRow->Next();
2328 int mid
= upperY
+ (lowerY
- upperY
)/2;
2330 if ( mid
< 0 ) return -1;
2335 for( ; i
!= mRows
.Count(); ++i
)
2337 int rowHeight
= mRows
[i
]->mRowHeight
;
2339 if ( mid
>= curY
&& mid
< curY
+ rowHeight
) return i
;
2347 int cbDockPane::GetRowY( cbRowInfo
* pRow
)
2351 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2353 if ( mRows
[i
] == pRow
) break;
2355 curY
+= mRows
[i
]->mRowHeight
;
2361 bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo
* pRow
)
2363 while ( pRow
->mpPrev
)
2365 pRow
= pRow
->mpPrev
;
2367 if ( pRow
->mHasOnlyFixedBars
)
2375 bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo
* pRow
)
2377 while( pRow
->mpNext
)
2379 pRow
= pRow
->mpNext
;
2381 if ( pRow
->mHasOnlyFixedBars
)
2389 bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo
* pBar
)
2391 while( pBar
->mpPrev
)
2393 pBar
= pBar
->mpPrev
;
2395 if ( pBar
->IsFixed() )
2403 bool cbDockPane::HasNotFixedBarsRight( cbBarInfo
* pBar
)
2405 while( pBar
->mpNext
)
2407 pBar
= pBar
->mpNext
;
2409 if ( pBar
->IsFixed() )
2417 void cbDockPane::CalcLenghtRatios( cbRowInfo
* pInRow
)
2423 // clac current-maximal-total-length of all maximized bars
2425 for( i
= 0; i
!= pInRow
->mBars
.GetCount(); ++i
)
2427 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2429 if ( !bar
.IsFixed() )
2431 totalWidth
+= bar
.mBounds
.width
;
2434 // set up persentages of occupied space for each maximized bar
2436 for( i
= 0; i
!= pInRow
->mBars
.Count(); ++i
)
2438 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2440 if ( !bar
.IsFixed() )
2442 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalWidth
);
2446 void cbDockPane::RecalcRowLayout( cbRowInfo
* pRow
)
2448 cbLayoutRowEvent
evt( pRow
, this );
2450 mpLayout
->FirePluginEvent( evt
);
2453 void cbDockPane::ExpandBar( cbBarInfo
* pBar
)
2455 mpLayout
->GetUpdatesManager().OnStartChanges();
2457 if ( !pBar
->mpRow
->mpExpandedBar
)
2459 // save ratios only when there arent any bars expanded yet
2461 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2464 ratios
.Alloc( pBar
->mpRow
->mNotFixedBarsCnt
);
2466 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2470 if ( !pCur
->IsFixed() )
2473 ratios
[ ratios
.GetCount() - 1 ] = pCur
->mLenRatio
;
2476 pCur
= pCur
->mpNext
;
2480 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2484 pCur
->mLenRatio
= 0.0; // minimize the rest
2486 pCur
= pCur
->mpNext
;
2489 pBar
->mLenRatio
= 1.0; // 100%
2490 pBar
->mBounds
.width
= 0;
2492 pBar
->mpRow
->mpExpandedBar
= pBar
;
2494 mpLayout
->RecalcLayout( FALSE
);
2496 mpLayout
->GetUpdatesManager().OnFinishChanges();
2497 mpLayout
->GetUpdatesManager().UpdateNow();
2500 void cbDockPane::ContractBar( cbBarInfo
* pBar
)
2502 mpLayout
->GetUpdatesManager().OnStartChanges();
2504 double ratio
= 1.0/ double( pBar
->mpRow
->mNotFixedBarsCnt
);
2506 // restore ratios which were present before expansion
2508 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2510 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2516 if ( !pCur
->IsFixed() )
2518 pCur
->mLenRatio
= ratios
[i
];
2522 pCur
= pCur
->mpNext
;
2528 pBar
->mpRow
->mpExpandedBar
= NULL
;
2530 mpLayout
->RecalcLayout( FALSE
);
2532 mpLayout
->GetUpdatesManager().OnFinishChanges();
2533 mpLayout
->GetUpdatesManager().UpdateNow();
2536 void cbDockPane::InitLinksForRow( cbRowInfo
* pRow
)
2538 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2540 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2546 bar
.mpPrev
= pRow
->mBars
[i
-1];
2548 if ( i
== pRow
->mBars
.Count() - 1 )
2552 bar
.mpNext
= pRow
->mBars
[i
+1];
2556 void cbDockPane::InitLinksForRows()
2558 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2560 cbRowInfo
& row
= *mRows
[i
];
2566 row
.mpPrev
= mRows
[i
-1];
2568 if ( i
== mRows
.Count() - 1 )
2572 row
.mpNext
= mRows
[i
+1];
2576 void cbDockPane::DoInsertBar( cbBarInfo
* pBar
, int rowNo
)
2578 cbRowInfo
* pRow
= NULL
;
2580 if ( rowNo
== -1 || rowNo
>= (int)mRows
.Count() )
2582 pRow
= new cbRowInfo();
2584 if ( rowNo
== -1 && mRows
.Count() )
2586 mRows
.Insert( pRow
, 0 );
2594 pRow
= mRows
[rowNo
];
2596 if ( mProps
.mNonDestructFirctionOn
== TRUE
)
2598 // store original shape of the row (before the bar is inserted)
2602 GetRowShapeData( mpStoredRow
, &mRowShapeData
);
2606 if ( pRow
->mBars
.Count() )
2608 pRow
->mpExpandedBar
= NULL
;
2610 cbInsertBarEvent
insEvt( pBar
, pRow
, this );
2612 mpLayout
->FirePluginEvent( insEvt
);
2614 mpLayout
->GetUpdatesManager().OnRowWillChange( pRow
, this );
2617 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
, const wxRect
& atRect
)
2619 wxRect rect
= atRect
;
2620 FrameToPane( &rect
);
2622 pBarInfo
->mBounds
.x
= rect
.x
;
2623 pBarInfo
->mBounds
.width
= rect
.width
;
2624 pBarInfo
->mBounds
.height
= rect
.height
;
2626 int row
= GetRowAt( rect
.y
, rect
.y
+ rect
.height
);
2628 DoInsertBar( pBarInfo
, row
);
2631 void cbDockPane::InsertBar( cbBarInfo
* pBar
, cbRowInfo
* pIntoRow
)
2633 cbInsertBarEvent
insEvt( pBar
, pIntoRow
, this );
2635 mpLayout
->FirePluginEvent( insEvt
);
2637 mpLayout
->GetUpdatesManager().OnRowWillChange( pIntoRow
, this );
2640 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
)
2642 // set transient properties
2644 pBarInfo
->mpRow
= NULL
;
2645 pBarInfo
->mHasLeftHandle
= FALSE
;
2646 pBarInfo
->mHasRightHandle
= FALSE
;
2647 pBarInfo
->mLenRatio
= 0.0;
2649 // set preferred bar demensions, according to the state in which
2650 // the bar is being inserted
2652 pBarInfo
->mBounds
.width
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].x
;
2653 pBarInfo
->mBounds
.height
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].y
;
2655 DoInsertBar( pBarInfo
, pBarInfo
->mRowNo
);
2658 void cbDockPane::RemoveRow( cbRowInfo
* pRow
)
2660 // first, hide all bar-windows in the removed row
2661 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2663 if ( pRow
->mBars
[i
]->mpBarWnd
)
2665 pRow
->mBars
[i
]->mpBarWnd
->Show( FALSE
);
2667 mRows
.Remove( pRow
);
2669 pRow
->mUMgrData
.SetDirty(TRUE
);
2672 void cbDockPane::InsertRow( cbRowInfo
* pRow
, cbRowInfo
* pBeforeRow
)
2678 mRows
.Insert( pRow
, mRows
.Index( pBeforeRow
) );
2682 pRow
->mUMgrData
.SetDirty(TRUE
);
2684 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2686 pRow
->mBars
[i
]->mUMgrData
.SetDirty( TRUE
);
2688 SyncRowFlags( pRow
);
2691 void cbDockPane::SetPaneWidth(int width
)
2693 if ( IsHorizontal() )
2695 mPaneWidth
= width
- mLeftMargin
- mRightMargin
;
2697 mPaneWidth
= width
- mTopMargin
- mBottomMargin
;
2701 void cbDockPane::SetBoundsInParent( const wxRect
& rect
)
2704 mBoundsInParent
= rect
;
2706 // set pane dimensions in local coordinates
2708 if ( IsHorizontal() )
2710 mPaneWidth
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2711 mPaneHeight
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2715 mPaneWidth
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2716 mPaneHeight
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2719 // convert bounding rectangles of all pane items into parent frame's coordinates
2721 wxBarIterator
i( mRows
);
2723 wxRect noMarginsRect
= mBoundsInParent
;
2725 noMarginsRect
.x
+= mLeftMargin
;
2726 noMarginsRect
.y
+= mTopMargin
;
2727 noMarginsRect
.width
-= ( mLeftMargin
+ mRightMargin
);
2728 noMarginsRect
.height
-= ( mTopMargin
+ mBottomMargin
);
2730 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2732 if ( mBoundsInParent
.width
< 0 ||
2733 mBoundsInParent
.height
< 0 )
2735 hide_rect( mBoundsInParent
);
2737 if ( noMarginsRect
.width
< 0 ||
2738 noMarginsRect
.height
< 0 )
2740 hide_rect( noMarginsRect
);
2742 // calculate mBoundsInParent for each item in the pane
2746 cbBarInfo
& bar
= i
.BarInfo();
2748 cbRowInfo
* pRowInfo
= bar
.mpRow
;
2750 // set up row info, if this is first bar in the row
2752 if ( pRowInfo
&& bar
.mpPrev
== NULL
)
2754 pRowInfo
->mBoundsInParent
.y
= pRowInfo
->mRowY
;
2755 pRowInfo
->mBoundsInParent
.x
= 0;
2756 pRowInfo
->mBoundsInParent
.width
= mPaneWidth
;
2757 pRowInfo
->mBoundsInParent
.height
= pRowInfo
->mRowHeight
;
2759 PaneToFrame( &pRowInfo
->mBoundsInParent
);
2761 clip_rect_against_rect( pRowInfo
->mBoundsInParent
, noMarginsRect
);
2764 wxRect bounds
= bar
.mBounds
;
2766 // exclude dimensions of handles, when calculating
2767 // bar's bounds in parent (i.e. "visual bounds")
2769 if ( bar
.mHasLeftHandle
)
2771 bounds
.x
+= mProps
.mResizeHandleSize
;
2772 bounds
.width
-= mProps
.mResizeHandleSize
;
2775 if ( bar
.mHasRightHandle
)
2777 bounds
.width
-= mProps
.mResizeHandleSize
;
2779 PaneToFrame( &bounds
);
2781 clip_rect_against_rect( bounds
, noMarginsRect
);
2783 bar
.mBoundsInParent
= bounds
;
2787 bool cbDockPane::BarPresent( cbBarInfo
* pBar
)
2789 wxBarIterator
iter( mRows
);
2791 while( iter
.Next() )
2793 if ( &iter
.BarInfo() == pBar
) return TRUE
;
2798 cbRowInfo
* cbDockPane::GetRow( int row
)
2800 if ( row
>= (int)mRows
.Count() ) return NULL
;
2802 return mRows
[ row
];
2805 int cbDockPane::GetRowIndex( cbRowInfo
* pRow
)
2807 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2809 if ( mRows
[i
] == pRow
) return i
;
2811 wxASSERT(0); // DBG:: row should be present
2816 int cbDockPane::GetPaneHeight()
2818 // first, recalculate row heights and the Y-positions
2820 cbLayoutRowsEvent
evt( this );
2821 mpLayout
->FirePluginEvent( evt
);
2825 if ( IsHorizontal() )
2827 height
+= mTopMargin
+ mBottomMargin
;
2829 height
+= mLeftMargin
+ mRightMargin
;
2831 int count
= mRows
.Count();
2835 height
+= mRows
[count
-1]->mRowY
+ mRows
[count
-1]->mRowHeight
;
2840 int cbDockPane::GetAlignment()
2845 bool cbDockPane::MatchesMask( int paneMask
)
2849 // FIXME:: use array instead of switch()
2853 case wxTOP
: thisMask
= wxTOP_PANE
; break;
2854 case wxBOTTOM
: thisMask
= wxBOTTOM_PANE
;break;
2855 case wxLEFT
: thisMask
= wxLEFT_PANE
; break;
2856 case wxRIGHT
: thisMask
= wxRIGHT_PANE
; break;
2858 default: wxASSERT(0); // DBG:: bogous alignment type
2861 return ( thisMask
& paneMask
);
2864 void cbDockPane::RecalcLayout()
2866 // first, reposition rows and items vertically
2868 cbLayoutRowsEvent
evt( this );
2869 mpLayout
->FirePluginEvent( evt
);
2871 // then horizontally in each row
2873 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2875 RecalcRowLayout( mRows
[i
] );
2878 int cbDockPane::GetDockingState()
2880 if ( mAlignment
== wxTOP
||
2881 mAlignment
== wxBOTTOM
)
2883 return wxCBAR_DOCKED_HORIZONTALLY
;
2886 return wxCBAR_DOCKED_VERTICALLY
;
2889 inline bool cbDockPane::HasPoint( const wxPoint
& pos
, int x
, int y
,
2890 int width
, int height
)
2892 return ( pos
.x
>= x
&&
2894 pos
.x
< x
+ width
&&
2895 pos
.y
< y
+ height
);
2898 int cbDockPane::HitTestPaneItems( const wxPoint
& pos
,
2906 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2908 cbRowInfo
& row
= *mRows
[i
];
2912 // hit-test handles of the row, if present
2914 if ( row
.mHasUpperHandle
)
2916 if ( HasPoint( pos
, 0, row
.mRowY
,
2917 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
2919 return CB_UPPER_ROW_HANDLE_HITTED
;
2922 if ( row
.mHasLowerHandle
)
2924 if ( HasPoint( pos
, 0, row
.mRowY
+ row
.mRowHeight
- mProps
.mResizeHandleSize
,
2925 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
2927 return CB_LOWER_ROW_HANDLE_HITTED
;
2930 // hit-test bar handles and bar content
2932 for( size_t k
= 0; k
!= row
.mBars
.Count(); ++k
)
2934 cbBarInfo
& bar
= *row
.mBars
[k
];
2935 wxRect
& bounds
= bar
.mBounds
;
2939 if ( bar
.mHasLeftHandle
)
2941 if ( HasPoint( pos
, bounds
.x
, bounds
.y
,
2942 mProps
.mResizeHandleSize
, bounds
.height
) )
2944 return CB_LEFT_BAR_HANDLE_HITTED
;
2947 if ( bar
.mHasRightHandle
)
2949 if ( HasPoint( pos
, bounds
.x
+ bounds
.width
- mProps
.mResizeHandleSize
, bounds
.y
,
2950 mProps
.mResizeHandleSize
, bounds
.height
) )
2952 return CB_RIGHT_BAR_HANDLE_HITTED
;
2955 if ( HasPoint( pos
, bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
) )
2957 return CB_BAR_CONTENT_HITTED
;
2959 } // hit-test next bar
2963 return CB_NO_ITEMS_HITTED
;
2966 void cbDockPane::GetBarResizeRange( cbBarInfo
* pBar
, int* from
, int *till
,
2967 bool forLeftHandle
)
2969 cbBarInfo
* pGivenBar
= pBar
;
2973 // calc unavailable space from the left
2975 while( pBar
->mpPrev
)
2977 pBar
= pBar
->mpPrev
;
2979 if ( !pBar
->IsFixed() ) notFree
+= mProps
.mMinCBarDim
.x
;
2980 else notFree
+= pBar
->mBounds
.width
;
2989 // calc unavailable space from the right
2991 while( pBar
->mpNext
)
2993 pBar
= pBar
->mpNext
;
2995 if ( pBar
->mBounds
.x
>= mPaneWidth
) break;
2997 // treat not-fixed bars as minimized
2999 if ( !pBar
->IsFixed() )
3001 notFree
+= mProps
.mMinCBarDim
.x
;
3004 if ( pBar
->mBounds
.x
+ pBar
->mBounds
.width
>= mPaneWidth
)
3006 notFree
+= mPaneWidth
- pBar
->mBounds
.x
;
3010 notFree
+= pBar
->mBounds
.width
;
3015 *till
= mPaneWidth
- notFree
;
3017 // do not let resizing totally deform the bar itself
3019 if ( forLeftHandle
)
3021 (*till
) -= mProps
.mMinCBarDim
.x
;
3024 (*from
) += mProps
.mMinCBarDim
.x
;
3027 int cbDockPane::GetMinimalRowHeight( cbRowInfo
* pRow
)
3029 int height
= mProps
.mMinCBarDim
.y
;
3031 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3033 if ( pRow
->mBars
[i
]->IsFixed() )
3035 height
= wxMax( height
, pRow
->mBars
[i
]->mBounds
.height
);
3037 if ( pRow
->mHasUpperHandle
)
3039 height
+= mProps
.mResizeHandleSize
;
3041 if ( pRow
->mHasLowerHandle
)
3043 height
+= mProps
.mResizeHandleSize
;
3048 void cbDockPane::SetRowHeight( cbRowInfo
* pRow
, int newHeight
)
3050 if ( pRow
->mHasUpperHandle
)
3052 newHeight
-= mProps
.mResizeHandleSize
;
3054 if ( pRow
->mHasLowerHandle
)
3056 newHeight
-= mProps
.mResizeHandleSize
;
3058 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3060 if ( !pRow
->mBars
[i
]->IsFixed() )
3062 pRow
->mBars
[i
]->mBounds
.height
= newHeight
;
3065 void cbDockPane::GetRowResizeRange( cbRowInfo
* pRow
, int* from
, int* till
,
3066 bool forUpperHandle
)
3068 cbRowInfo
* pGivenRow
= pRow
;
3070 // calc unavailable space from above
3074 while( pRow
->mpPrev
)
3076 pRow
= pRow
->mpPrev
;
3078 notFree
+= GetMinimalRowHeight( pRow
);
3084 // allow accupy the client window space by resizing pane rows
3085 if ( mAlignment
== wxBOTTOM
)
3087 *from
-= mpLayout
->GetClientHeight();
3089 if ( mAlignment
== wxRIGHT
)
3091 *from
-= mpLayout
->GetClientWidth();
3093 // calc unavailable space from below
3099 while( pRow
->mpNext
)
3101 pRow
= pRow
->mpNext
;
3103 notFree
+= GetMinimalRowHeight( pRow
);
3107 *till
= mPaneHeight
- notFree
;
3109 // allow adjustinig pane space vs. client window space by resizing pane row heights
3111 if ( mAlignment
== wxTOP
)
3113 *till
+= mpLayout
->GetClientHeight();
3115 if ( mAlignment
== wxLEFT
)
3117 *till
+= mpLayout
->GetClientWidth();
3119 // do not let the resizing of the row totally squeeze the row itself
3121 cbRowInfo
& row
= *pGivenRow
;
3123 if ( forUpperHandle
)
3125 *till
= row
.mRowY
+ row
.mRowHeight
- GetMinimalRowHeight( pGivenRow
);
3127 if ( row
.mHasUpperHandle
)
3129 *till
-= mProps
.mResizeHandleSize
;
3133 *from
+= GetMinimalRowHeight( pGivenRow
);
3135 if ( row
.mHasLowerHandle
)
3137 *from
-= mProps
.mResizeHandleSize
;
3141 void cbDockPane::ResizeRow( cbRowInfo
* pRow
, int ofs
,
3142 bool forUpperHandle
)
3144 cbResizeRowEvent
evt( pRow
, ofs
, forUpperHandle
, this );
3146 mpLayout
->FirePluginEvent( evt
);
3149 void cbDockPane::ResizeBar( cbBarInfo
* pBar
, int ofs
,
3150 bool forLeftHandle
)
3152 pBar
->mpRow
->mpExpandedBar
= NULL
;
3154 mpLayout
->GetUpdatesManager().OnStartChanges();
3156 wxRect
& bounds
= pBar
->mBounds
;
3158 if ( forLeftHandle
)
3160 // do not allow bar width become less then minimal
3161 if ( bounds
.x
+ ofs
> bounds
.x
+ bounds
.width
- mProps
.mMinCBarDim
.x
)
3163 bounds
.width
= mProps
.mMinCBarDim
.x
;
3169 bounds
.width
-= ofs
;
3174 // move bar left if necessary
3175 if ( bounds
.width
+ ofs
< mProps
.mMinCBarDim
.x
)
3177 bounds
.x
= bounds
.x
+ bounds
.width
+ ofs
- mProps
.mMinCBarDim
.x
;
3178 bounds
.width
= mProps
.mMinCBarDim
.x
;
3181 // resize right border only
3182 bounds
.width
+= ofs
;
3186 cbRowInfo
* pToRow
= pBar
->mpRow
;
3188 this->RemoveBar( pBar
);
3190 InsertBar( pBar
, pToRow
);
3192 mpLayout
->RecalcLayout(FALSE
);
3194 mpLayout
->GetUpdatesManager().OnFinishChanges();
3195 mpLayout
->GetUpdatesManager().UpdateNow();
3199 /*** row/bar resizing related methods ***/
3201 void cbDockPane::DrawVertHandle( wxDC
& dc
, int x
, int y
, int height
)
3203 int lower
= y
+ height
;
3205 dc
.SetPen( mpLayout
->mLightPen
);
3206 dc
.DrawLine( x
,y
, x
, lower
);
3208 dc
.SetPen( mpLayout
->mGrayPen
);
3209 for( int i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3212 dc
.DrawLine( x
,y
, x
, lower
);
3215 dc
.SetPen( mpLayout
->mDarkPen
);
3217 dc
.DrawLine( x
,y
, x
, lower
);
3219 dc
.SetPen( mpLayout
->mBlackPen
);
3221 dc
.DrawLine( x
,y
, x
, lower
);
3224 void cbDockPane::DrawHorizHandle( wxDC
& dc
, int x
, int y
, int width
)
3226 int right
= x
+ width
;
3228 dc
.SetPen( mpLayout
->mLightPen
);
3229 dc
.DrawLine( x
,y
, right
, y
);
3231 dc
.SetPen( mpLayout
->mGrayPen
);
3233 for( int i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3236 dc
.DrawLine( x
,y
, right
, y
);
3239 dc
.SetPen( mpLayout
->mDarkPen
);
3240 dc
.DrawLine( x
,y
, right
, ++y
);
3242 dc
.SetPen( mpLayout
->mBlackPen
);
3243 dc
.DrawLine( x
,y
, right
, ++y
);
3246 cbBarInfo
* cbDockPane::GetBarInfoByWindow( wxWindow
* pBarWnd
)
3248 wxBarIterator
i( mRows
);
3252 if ( i
.BarInfo().mpBarWnd
== pBarWnd
)
3254 return &i
.BarInfo();
3259 void cbDockPane::GetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3261 pLst
->DeleteContents( TRUE
);
3264 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3266 cbBarInfo
& bar
= *pRow
->mBars
[i
];
3268 cbBarShapeData
* pData
= new cbBarShapeData();
3270 pLst
->Append( (wxObject
*)pData
);
3272 pData
->mBounds
= bar
.mBounds
;
3273 pData
->mLenRatio
= bar
.mLenRatio
;
3277 void cbDockPane::SetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3279 if ( pLst
->First() == NULL
) return;
3281 wxNode
* pData
= pLst
->First();
3283 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3285 wxASSERT( pData
); // DBG::
3287 cbBarInfo
& bar
= *pRow
->mBars
[i
];;
3289 cbBarShapeData
& data
= *((cbBarShapeData
*)pData
->Data());
3291 bar
.mBounds
= data
.mBounds
;
3292 bar
.mLenRatio
= data
.mLenRatio
;
3294 pData
= pData
->Next();
3298 /***** Implementation for class cbUpdatesManagerBase *****/
3300 IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase
, wxObject
)
3302 /***** Implementation for class cbPluginBase *****/
3304 IMPLEMENT_ABSTRACT_CLASS( cbPluginBase
, wxEvtHandler
)
3306 cbPluginBase::~cbPluginBase()
3311 bool cbPluginBase::ProcessEvent(wxEvent
& event
)
3313 if ( mPaneMask
== wxALL_PANES
)
3315 return wxEvtHandler::ProcessEvent( event
);
3317 // extract mask info. from received event
3319 cbPluginEvent
& evt
= *( (cbPluginEvent
*)&event
);
3321 if ( evt
.mpPane
== 0 &&
3322 mPaneMask
== wxALL_PANES
)
3324 return wxEvtHandler::ProcessEvent( event
);
3328 switch ( evt
.mpPane
->mAlignment
)
3330 case wxTOP
: mask
= wxTOP_PANE
; break;
3331 case wxBOTTOM
: mask
= wxBOTTOM_PANE
;break;
3332 case wxLEFT
: mask
= wxLEFT_PANE
; break;
3333 case wxRIGHT
: mask
= wxRIGHT_PANE
; break;
3336 // if event's pane maks matches the plugin's mask
3338 if ( mPaneMask
& mask
)
3340 return wxEvtHandler::ProcessEvent( event
);
3342 // otherwise pass to the next handler if present
3344 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event
) )