1 /////////////////////////////////////////////////////////////////////////////
2 // Name: controlbar.cpp
3 // Purpose: Implementation for main controlbar classes.
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "controlbar.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
30 #include "wx/string.h"
31 #include "wx/utils.h" // import wxMin,wxMax macros
32 #include "wx/minifram.h"
34 #include "wx/fl/controlbar.h"
36 // import classes of default plugins
38 #include "wx/fl/panedrawpl.h"
39 #include "wx/fl/rowlayoutpl.h"
40 #include "wx/fl/antiflickpl.h"
41 #include "wx/fl/bardragpl.h"
42 #include "wx/fl/cbcustom.h"
44 #include "wx/fl/gcupdatesmgr.h" // import default updates manager class ("garbage-collecting" one)
45 #include "wx/fl/updatesmgr.h"
47 #include "wx/fl/toolwnd.h"
49 // These are the event IDs being initialized to a value to
50 // meet the new event paradigm as of wx2.3.0. Probably we
51 // should find a way to make these be non-global, but this
52 // works for right now.
53 wxEventType cbEVT_PL_LEFT_DOWN
= wxNewEventType();
54 wxEventType cbEVT_PL_LEFT_UP
= wxNewEventType();
55 wxEventType cbEVT_PL_RIGHT_DOWN
= wxNewEventType();
56 wxEventType cbEVT_PL_RIGHT_UP
= wxNewEventType();
57 wxEventType cbEVT_PL_MOTION
= wxNewEventType();
59 wxEventType cbEVT_PL_LEFT_DCLICK
= wxNewEventType();
61 wxEventType cbEVT_PL_LAYOUT_ROW
= wxNewEventType();
62 wxEventType cbEVT_PL_RESIZE_ROW
= wxNewEventType();
63 wxEventType cbEVT_PL_LAYOUT_ROWS
= wxNewEventType();
64 wxEventType cbEVT_PL_INSERT_BAR
= wxNewEventType();
65 wxEventType cbEVT_PL_RESIZE_BAR
= wxNewEventType();
66 wxEventType cbEVT_PL_REMOVE_BAR
= wxNewEventType();
67 wxEventType cbEVT_PL_SIZE_BAR_WND
= wxNewEventType();
69 wxEventType cbEVT_PL_DRAW_BAR_DECOR
= wxNewEventType();
70 wxEventType cbEVT_PL_DRAW_ROW_DECOR
= wxNewEventType();
71 wxEventType cbEVT_PL_DRAW_PANE_DECOR
= wxNewEventType();
72 wxEventType cbEVT_PL_DRAW_BAR_HANDLES
= wxNewEventType();
73 wxEventType cbEVT_PL_DRAW_ROW_HANDLES
= wxNewEventType();
74 wxEventType cbEVT_PL_DRAW_ROW_BKGROUND
= wxNewEventType();
75 wxEventType cbEVT_PL_DRAW_PANE_BKGROUND
= wxNewEventType();
77 wxEventType cbEVT_PL_START_BAR_DRAGGING
= wxNewEventType();
78 wxEventType cbEVT_PL_DRAW_HINT_RECT
= wxNewEventType();
80 wxEventType cbEVT_PL_START_DRAW_IN_AREA
= wxNewEventType();
81 wxEventType cbEVT_PL_FINISH_DRAW_IN_AREA
= wxNewEventType();
83 wxEventType cbEVT_PL_CUSTOMIZE_BAR
= wxNewEventType();
84 wxEventType cbEVT_PL_CUSTOMIZE_LAYOUT
= wxNewEventType();
86 wxEventType wxCUSTOM_CB_PLUGIN_EVENTS_START_AT
= wxNewEventType();
88 // some ascii-art, still can't get these *nice* cursors working on wx... :-(
90 static const char* _gHorizCursorImg
[] =
92 "............XX....XX............",
93 "............XX....XX............",
94 "............XX....XX............",
95 "............XX....XX............",
96 "............XX....XX............",
97 "...X........XX....XX........X...",
98 "..XX........XX....XX........XX..",
99 ".XXX........XX....XX........XXX.",
100 "XXXXXXXXXXXXXX....XXXXXXXXXXXXXX",
101 ".XXX........XX....XX........XXX.",
102 "..XX........XX....XX........XX..",
103 "...X........XX....XX........X...",
104 "............XX....XX............",
105 "............XX....XX............",
106 "............XX....XX............",
107 "............XX....XX............"
110 static const char* _gVertCursorImg
[] =
112 "................X...............",
113 "...............XXX..............",
114 "..............XXXXX.............",
115 ".............XXXXXXX............",
116 "................X...............",
117 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
118 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
119 "................................",
120 "................................",
121 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
122 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
123 "................X...............",
124 ".............XXXXXXX............",
125 "..............XXXXX.............",
126 "...............XXX..............",
127 "................X..............."
130 // helper inline functions
132 static inline bool rect_contains_point( const wxRect
& rect
, int x
, int y
)
134 return ( x
>= rect
.x
&&
136 x
< rect
.x
+ rect
.width
&&
137 y
< rect
.y
+ rect
.height
);
140 static inline bool rect_hits_rect( const wxRect
& r1
, const wxRect
& r2
)
142 if ( ( r2
.x
>= r1
.x
&& r2
.x
<= r1
.x
+ r1
.width
) ||
143 ( r1
.x
>= r2
.x
&& r1
.x
<= r2
.x
+ r2
.width
) )
145 if ( ( r2
.y
>= r1
.y
&& r2
.y
<= r1
.y
+ r1
.height
) ||
146 ( r1
.y
>= r2
.y
&& r1
.y
<= r2
.y
+ r2
.height
) )
153 static inline void hide_rect( wxRect
& r
)
161 static inline void clip_rect_against_rect( wxRect
& r1
, const wxRect
& r2
)
165 r1
.x
>= r2
.x
+ r2
.width
||
166 r1
.y
>= r2
.y
+ r2
.height
174 if ( r1
.x
+ r1
.width
> r2
.x
+ r2
.width
)
176 r1
.width
= r2
.x
+ r2
.width
- r1
.x
;
178 if ( r1
.y
+ r1
.height
> r2
.y
+ r2
.height
)
180 r1
.height
= r2
.y
+ r2
.height
- r1
.y
;
184 /***** Implementation for class cbBarSpy *****/
186 IMPLEMENT_DYNAMIC_CLASS( cbBarSpy
, wxEvtHandler
)
188 cbBarSpy::cbBarSpy(void)
193 cbBarSpy::cbBarSpy( wxFrameLayout
* pPanel
)
199 void cbBarSpy::SetBarWindow( wxWindow
* pWnd
)
204 bool cbBarSpy::ProcessEvent(wxEvent
& event
)
206 bool handled
= wxEvtHandler::ProcessEvent( event
);
208 int type
= event
.GetEventType();
210 if ( !handled
&& ( type
== wxEVT_LEFT_DOWN
||
211 type
== wxEVT_LEFT_DCLICK
) )
213 wxMouseEvent
& mevent
= *((wxMouseEvent
*)&event
);
218 mpBarWnd
->ClientToScreen( &x
, &y
);
219 mpLayout
->GetParentFrame().ScreenToClient( &x
, &y
);
224 // forwared not-handled event to frame-layout
226 if ( type
== wxEVT_LEFT_DOWN
)
228 //mpLayout->OnLButtonDown( mevent );
232 mpLayout
->OnLDblClick( mevent
);
240 /***** Implementation for class wxFrameLayout *****/
242 IMPLEMENT_DYNAMIC_CLASS( wxFrameLayout
, wxEvtHandler
)
244 BEGIN_EVENT_TABLE( wxFrameLayout
, wxEvtHandler
)
246 EVT_PAINT ( wxFrameLayout::OnPaint
)
247 EVT_SIZE ( wxFrameLayout::OnSize
)
248 EVT_LEFT_DOWN ( wxFrameLayout::OnLButtonDown
)
249 EVT_LEFT_UP ( wxFrameLayout::OnLButtonUp
)
250 EVT_RIGHT_DOWN ( wxFrameLayout::OnRButtonDown
)
251 EVT_RIGHT_UP ( wxFrameLayout::OnRButtonUp
)
252 EVT_MOTION ( wxFrameLayout::OnMouseMove
)
254 EVT_LEFT_DCLICK( wxFrameLayout::OnLDblClick
)
256 EVT_IDLE ( wxFrameLayout::OnIdle
)
257 EVT_SET_FOCUS ( wxFrameLayout::OnSetFocus
)
258 EVT_KILL_FOCUS ( wxFrameLayout::OnKillFocus
)
260 EVT_ACTIVATE ( wxFrameLayout::OnActivate
)
262 EVT_ERASE_BACKGROUND( wxFrameLayout::OnEraseBackground
)
266 // FIXME:: how to eliminate these cut&pasted constructors?
268 wxFrameLayout::wxFrameLayout(void)
271 mpFrameClient( NULL
),
273 mDarkPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
274 mLightPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT
), 1, wxSOLID
),
275 mGrayPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
276 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID
),
277 mBorderPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
279 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT
),
281 mpPaneInFocus( NULL
),
285 mpTopPlugin ( NULL
),
286 mpCaputesInput( NULL
),
288 mClientWndRefreshPending( FALSE
),
289 mRecalcPending( TRUE
),
290 mCheckFocusWhenIdle( FALSE
)
295 for ( i
= 0; i
!= MAX_PANES
; ++i
)
298 mFloatingOn
= CanReparent();
301 wxFrameLayout::wxFrameLayout( wxWindow
* pParentFrame
, wxWindow
* pFrameClient
, bool activateNow
)
303 : mpFrame( pParentFrame
),
304 mpFrameClient(pFrameClient
),
306 mDarkPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
307 mLightPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT
), 1, wxSOLID
),
308 mGrayPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
309 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID
),
310 mBorderPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
312 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT
),
314 mpPaneInFocus( NULL
),
317 mFloatingOn ( TRUE
),
319 mpTopPlugin ( NULL
),
320 mpCaputesInput( NULL
),
322 mClientWndRefreshPending( FALSE
),
323 mRecalcPending( TRUE
),
324 mCheckFocusWhenIdle( FALSE
),
331 for ( i
= 0; i
!= MAX_PANES
; ++i
)
332 mPanes
[i
] = new cbDockPane( i
, this );
339 // DBG:: set RED color of frame's background for the
340 // prurpose of tracking engine bugs "visually"
342 GetParentFrame().SetBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
) );
345 mFloatingOn
= CanReparent();
348 // NOTE:: below are the only platform-check "ifdef"s in the docking system!
350 bool wxFrameLayout::CanReparent()
354 #elif defined (__WXGTK__)
359 return FALSE
; // reparenting is not yet supported by Motif and others
369 void wxFrameLayout::ReparentWindow( wxWindow
* pChild
, wxWindow
* pNewParent
)
374 if ( pChild
->GetParent() )
376 bool success
= pChild
->GetParent()->GetChildren().DeleteObject( pChild
);
378 wxASSERT( success
); // DBG::
381 ::SetParent( (HWND
)pChild
->m_hWnd
, (HWND
)pNewParent
->m_hWnd
);
383 pNewParent
->GetChildren().Append( pChild
);
385 pChild
->SetParent( pNewParent
);
387 pChild
->Reparent(pNewParent
);
390 #elif defined(__WXGTK__) || defined(__WXX11__)
391 // FOR NOW:: floating with wxGtk still very buggy
395 //pChild->ReParent( pNewParent );
399 wxMessageBox( "Sorry, docking is not supported for ports other than MSW and wxGTK" );
403 void wxFrameLayout::DestroyBarWindows()
405 wxNode
* pSpy
= mBarSpyList
.First();
409 cbBarSpy
& spy
= *((cbBarSpy
*)pSpy
->Data());
411 if ( spy
.mpBarWnd
->GetEventHandler() == &spy
)
413 spy
.mpBarWnd
->PopEventHandler();
423 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
425 if ( mAllBars
[i
]->mpBarWnd
)
427 mAllBars
[i
]->mpBarWnd
->Destroy();
428 mAllBars
[i
]->mpBarWnd
= NULL
;
433 void wxFrameLayout::ShowFloatedWindows( bool show
)
435 wxNode
* pNode
= mFloatedFrames
.First();
439 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
443 pNode
= pNode
->Next();
447 wxFrameLayout::~wxFrameLayout()
456 // destoy the chain of plugins from left to right
458 wxEvtHandler
* pCur
= mpTopPlugin
;
462 while ( pCur
->GetPreviousHandler() )
464 pCur
= pCur
->GetPreviousHandler();
468 wxEvtHandler
* pNext
= pCur
->GetNextHandler();
475 // destroy contents of arrays and lists
478 for ( i
= 0; i
!= MAX_PANES
; ++i
)
484 delete mpHorizCursor
;
487 if ( mpNormalCursor
)
488 delete mpNormalCursor
;
494 wxNode
* pSpy
= mBarSpyList
.First();
498 cbBarSpy
& spy
= *((cbBarSpy
*)pSpy
->Data());
500 if ( spy
.mpBarWnd
->GetEventHandler() == &spy
)
502 spy
.mpBarWnd
->PopEventHandler();
509 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
513 void wxFrameLayout::EnableFloating( bool enable
)
515 mFloatingOn
= enable
&& CanReparent();
518 void wxFrameLayout::Activate()
524 ShowFloatedWindows( TRUE
);
527 void wxFrameLayout::Deactivate()
529 ShowFloatedWindows( FALSE
);
536 void wxFrameLayout::SetFrameClient( wxWindow
* pFrameClient
)
538 mpFrameClient
= pFrameClient
;
541 wxWindow
* wxFrameLayout::GetFrameClient()
543 return mpFrameClient
;
546 cbUpdatesManagerBase
& wxFrameLayout::GetUpdatesManager()
549 mpUpdatesMgr
= CreateUpdatesManager();
551 return *mpUpdatesMgr
;
554 void wxFrameLayout::SetUpdatesManager( cbUpdatesManagerBase
* pUMgr
)
559 mpUpdatesMgr
= pUMgr
;
561 mpUpdatesMgr
->SetLayout( this );
564 cbUpdatesManagerBase
* wxFrameLayout::CreateUpdatesManager()
566 return new cbGCUpdatesMgr( this );
567 //return new cbSimpleUpdatesMgr( this );
570 void wxFrameLayout::AddBar( wxWindow
* pBarWnd
,
571 const cbDimInfo
& dimInfo
,
575 const wxString
& name
,
580 if ( pBarWnd
&& spyEvents
)
582 // hook up spy to bar window
583 cbBarSpy
* pSpy
= new cbBarSpy( this );
585 pSpy
->SetBarWindow( pBarWnd
);
586 pBarWnd
->PushEventHandler( pSpy
);
588 mBarSpyList
.Append( pSpy
);
591 cbBarInfo
* pInfo
= new cbBarInfo();
594 pInfo
->mpBarWnd
= pBarWnd
;
595 pInfo
->mDimInfo
= dimInfo
;
596 pInfo
->mState
= state
;
597 pInfo
->mAlignment
= alignment
;
598 pInfo
->mRowNo
= rowNo
;
599 pInfo
->mBounds
.x
= columnPos
;
601 mAllBars
.Add( pInfo
);
603 DoSetBarState( pInfo
);
606 bool wxFrameLayout::RedockBar( cbBarInfo
* pBar
,
607 const wxRect
& shapeInParent
,
613 pToPane
= HitTestPanes( shapeInParent
, NULL
);
617 return FALSE
; // bar's shape does not hit any pane
618 // - redocking is NOT possible
620 cbDockPane
* pBarPane
= GetBarPane( pBar
);
624 GetUpdatesManager().OnStartChanges();
626 pBarPane
->RemoveBar( pBar
);
628 // FIXME FIXME:: the recalculation below may be a *huge* performance
629 // hit, it could be eliminated though...
630 // but first the "pane-postion-changed" problem
633 RecalcLayout( FALSE
);
635 pToPane
->InsertBar( pBar
, shapeInParent
);
637 RecalcLayout( FALSE
);
639 // finish update "transaction"
643 GetUpdatesManager().OnFinishChanges();
644 GetUpdatesManager().UpdateNow();
650 cbBarInfo
* wxFrameLayout::FindBarByName( const wxString
& name
)
653 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
654 if ( mAllBars
[i
]->mName
== name
)
660 cbBarInfo
* wxFrameLayout::FindBarByWindow( const wxWindow
* pWnd
)
663 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
664 if ( mAllBars
[i
]->mpBarWnd
== pWnd
)
670 BarArrayT
& wxFrameLayout::GetBars()
675 void wxFrameLayout::SetBarState( cbBarInfo
* pBar
, int newState
, bool updateNow
)
677 if ( newState
== wxCBAR_FLOATING
&& !mFloatingOn
)
683 GetUpdatesManager().OnStartChanges();
685 pBar
->mUMgrData
.SetDirty(TRUE
);
687 // check bar's previous state
689 if ( pBar
->mState
!= wxCBAR_HIDDEN
&& pBar
->mState
!= wxCBAR_FLOATING
)
694 bool success
= LocateBar( pBar
, &pRow
, &pPane
);
696 wxASSERT( success
); // DBG::
698 // save LRU-dim info before removing bar
700 pBar
->mDimInfo
.mLRUPane
= pPane
->GetAlignment();
701 pBar
->mDimInfo
.mBounds
[ pPane
->GetAlignment() ] = pBar
->mBounds
;
703 // remove it from the pane it was docked on
705 pPane
->RemoveBar( pBar
);
709 if ( pBar
->mState
== wxCBAR_FLOATING
&& newState
!= wxCBAR_FLOATING
)
711 // remove bar's window from the containing mini-frame
712 // and set its parent to be layout's parent frame
714 if ( pBar
->mpBarWnd
)
716 pBar
->mpBarWnd
->Show(FALSE
); // to avoid flicker upon reparenting
718 wxNode
* pNode
= mFloatedFrames
.First();
722 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
724 if ( pFFrm
->GetBar() == pBar
)
726 pFFrm
->Show( FALSE
); // reduces flicker sligthly
728 ReparentWindow( pBar
->mpBarWnd
, &GetParentFrame() );
730 pBar
->mBounds
= pBar
->mDimInfo
.mBounds
[ pBar
->mDimInfo
.mLRUPane
];
732 if ( newState
!= wxCBAR_HIDDEN
)
734 pBar
->mAlignment
= pBar
->mDimInfo
.mLRUPane
;
736 mFloatedFrames
.DeleteNode( pNode
);
738 pFFrm
->Show( FALSE
);
739 pFFrm
->Destroy(); break;
742 pNode
= pNode
->Next();
745 // FOR NOW:: excessive!
746 //if ( mpFrameClient ) mpFrameClient->Refresh();
748 mClientWndRefreshPending
= TRUE
;
752 if ( pBar
->mDimInfo
.GetDimHandler() )
754 pBar
->mDimInfo
.GetDimHandler()->OnChangeBarState( pBar
, newState
);
757 pBar
->mState
= newState
;
759 DoSetBarState( pBar
);
765 GetUpdatesManager().OnFinishChanges();
766 GetUpdatesManager().UpdateNow();
770 void wxFrameLayout::InverseVisibility( cbBarInfo
* pBar
)
772 wxASSERT( pBar
); // DBG::
774 // "inverse" bar-visibility of the selected bar
778 if ( pBar
->mState
== wxCBAR_HIDDEN
)
780 if ( pBar
->mAlignment
== -1 )
782 pBar
->mAlignment
= 0; // just remove "-1" marking
783 newState
= wxCBAR_FLOATING
;
786 if ( pBar
->mAlignment
== FL_ALIGN_TOP
||
787 pBar
->mAlignment
== FL_ALIGN_BOTTOM
)
789 newState
= wxCBAR_DOCKED_HORIZONTALLY
;
791 newState
= wxCBAR_DOCKED_VERTICALLY
;
795 newState
= wxCBAR_HIDDEN
;
797 if ( pBar
->mState
== wxCBAR_FLOATING
)
799 pBar
->mAlignment
= -1;
802 this->SetBarState( pBar
, newState
, TRUE
);
804 if ( newState
== wxCBAR_FLOATING
)
806 this->RepositionFloatedBar( pBar
);
809 void wxFrameLayout::ApplyBarProperties( cbBarInfo
* pBar
)
811 if ( pBar
->mState
== wxCBAR_FLOATING
)
813 RepositionFloatedBar( pBar
);
816 if ( pBar
->mState
== wxCBAR_DOCKED_HORIZONTALLY
||
817 pBar
->mState
== wxCBAR_DOCKED_VERTICALLY
825 void wxFrameLayout::RepositionFloatedBar( cbBarInfo
* pBar
)
827 if ( !mFloatingOn
) return;
829 wxNode
* pNode
= mFloatedFrames
.First();
833 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
835 if ( pFFrm
->GetBar() == pBar
)
837 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
842 GetParentFrame().ClientToScreen( &x
, &y
);
844 pFFrm
->PositionFloatedWnd( x
,y
,
851 pNode
= pNode
->Next();
855 void wxFrameLayout::DoSetBarState( cbBarInfo
* pBar
)
857 if ( pBar
->mState
!= wxCBAR_FLOATING
&&
858 pBar
->mState
!= wxCBAR_HIDDEN
)
862 mPanes
[pBar
->mAlignment
]->InsertBar( pBar
);
864 if ( pBar
->mState
== wxCBAR_HIDDEN
)
868 if ( pBar
->mpBarWnd
)
870 pBar
->mpBarWnd
->Show( FALSE
);
874 if ( !mFloatingOn
) return;
878 if ( pBar
->mpBarWnd
== NULL
|| !CanReparent() )
880 // FOR NOW:: just hide it
882 if ( pBar
->mpBarWnd
)
884 pBar
->mpBarWnd
->Show( FALSE
);
886 pBar
->mState
= wxCBAR_HIDDEN
;
891 cbFloatedBarWindow
* pMiniFrm
= new cbFloatedBarWindow();
893 pMiniFrm
->SetBar( pBar
);
894 pMiniFrm
->SetLayout( this );
896 pMiniFrm
->Create( &GetParentFrame(), -1, pBar
->mName
,
899 wxFRAME_FLOAT_ON_PARENT
|
900 wxFRAME_TOOL_WINDOW
|
904 pMiniFrm
->SetClient( pBar
->mpBarWnd
);
906 ReparentWindow( pBar
->mpBarWnd
, pMiniFrm
);
908 mFloatedFrames
.Append( pMiniFrm
);
910 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
912 // check if it wasn't floated anytime before
914 if ( bounds
.width
== -1 )
916 wxRect
& clntRect
= GetClientRect();
918 // adjust position into which the next floated bar will be placed
920 if ( mNextFloatedWndPos
.x
+ bounds
.width
> clntRect
.width
)
922 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
924 if ( mNextFloatedWndPos
.y
+ bounds
.height
> clntRect
.height
)
926 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
928 bounds
.x
= mNextFloatedWndPos
.x
+ clntRect
.x
;
929 bounds
.y
= mNextFloatedWndPos
.y
+ clntRect
.y
;
931 bounds
.width
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].x
;
932 bounds
.height
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].y
;
934 mNextFloatedWndPos
.x
+= mFloatingPosStep
.x
;
935 mNextFloatedWndPos
.y
+= mFloatingPosStep
.y
;
938 pMiniFrm
->Show( TRUE
);
940 // FIXME:: this is excessive
941 pBar
->mpBarWnd
->Show(TRUE
);
945 void wxFrameLayout::RemoveBar( cbBarInfo
* pBarInfo
)
947 // first, try to "guess" what was the perviouse state of the bar
952 if ( LocateBar( pBarInfo
, &pRow
, &pPane
) )
954 // ...aha, bar was docked into one of the panes,
955 // remove it from there
957 pPane
->RemoveBar( pBarInfo
);
961 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
963 if ( mAllBars
[i
] == pBarInfo
)
965 #if wxCHECK_VERSION(2,3,2)
966 mAllBars
.RemoveAt(i
);
970 if ( pBarInfo
->mpBarWnd
) // hides it's window
972 pBarInfo
->mpBarWnd
->Show( FALSE
);
979 wxFAIL_MSG("bar info should be present in the list of all bars of all panes");
982 bool wxFrameLayout::LocateBar( cbBarInfo
* pBarInfo
,
984 cbDockPane
** ppPane
)
990 for ( n
= 0; n
!= MAX_PANES
; ++n
)
992 wxBarIterator
i( mPanes
[n
]->GetRowList() );
996 if ( &i
.BarInfo() == pBarInfo
)
998 (*ppPane
) = mPanes
[n
];
999 (*ppRow
) = &i
.RowInfo();
1008 void wxFrameLayout::RecalcLayout( bool repositionBarsNow
)
1010 mRecalcPending
= FALSE
;
1012 int frmWidth
, frmHeight
;
1013 mpFrame
->GetClientSize( &frmWidth
, &frmHeight
);
1020 // pane positioning priorities in decreasing order:
1021 // top, bottom, left, right
1025 cbDockPane
* pPane
= mPanes
[ FL_ALIGN_TOP
];
1027 pPane
->SetPaneWidth( frmWidth
);
1028 pPane
->RecalcLayout();
1030 paneHeight
= pPane
->GetPaneHeight();
1034 rect
.width
= frmWidth
;
1035 rect
.height
= wxMin( paneHeight
, frmHeight
- curY
);
1037 pPane
->SetBoundsInParent( rect
);
1041 // setup BOTTOM pane
1043 pPane
= mPanes
[ FL_ALIGN_BOTTOM
];
1045 pPane
->SetPaneWidth( frmWidth
);
1046 pPane
->RecalcLayout();
1048 paneHeight
= pPane
->GetPaneHeight();
1051 rect
.y
= wxMax( frmHeight
- paneHeight
, curY
);
1052 rect
.width
= frmWidth
;
1053 rect
.height
= frmHeight
- rect
.y
;
1055 pPane
->SetBoundsInParent( rect
);
1059 pPane
= mPanes
[ FL_ALIGN_LEFT
];
1062 pPane
->SetPaneWidth( rect
.y
- curY
);
1064 pPane
->RecalcLayout();
1065 paneHeight
= pPane
->GetPaneHeight();
1068 rect
.height
= rect
.y
- curY
;
1071 rect
.width
= wxMin( paneHeight
, frmWidth
);
1073 pPane
->SetBoundsInParent( rect
);
1079 pPane
= mPanes
[ FL_ALIGN_RIGHT
];
1081 // left pane's height
1082 pPane
->SetPaneWidth( rect
.height
);
1084 pPane
->RecalcLayout();
1085 paneHeight
= pPane
->GetPaneHeight();
1087 // left pane's height
1088 rect
.height
= rect
.height
;
1089 rect
.x
= wxMax( frmWidth
- paneHeight
, curX
);
1091 rect
.width
= frmWidth
- rect
.x
;
1093 pPane
->SetBoundsInParent( rect
);
1095 // recalc bounds of the client-window
1097 mClntWndBounds
.x
= mPanes
[FL_ALIGN_LEFT
]->mBoundsInParent
.x
+
1098 mPanes
[FL_ALIGN_LEFT
]->mBoundsInParent
.width
;
1099 mClntWndBounds
.y
= mPanes
[FL_ALIGN_TOP
]->mBoundsInParent
.y
+
1100 mPanes
[FL_ALIGN_TOP
]->mBoundsInParent
.height
;
1102 mClntWndBounds
.width
= mPanes
[FL_ALIGN_RIGHT
]->mBoundsInParent
.x
-
1104 mClntWndBounds
.height
= mPanes
[FL_ALIGN_BOTTOM
]->mBoundsInParent
.y
-
1107 if ( repositionBarsNow
)
1112 int wxFrameLayout::GetClientHeight()
1114 // for better portablility wxWindow::GetSzie() is not used here
1116 return mClntWndBounds
.height
;
1119 int wxFrameLayout::GetClientWidth()
1121 // for better portablility wxWindow::GetSzie() is not used here
1123 return mClntWndBounds
.width
;
1126 void wxFrameLayout::PositionClientWindow()
1128 if ( mpFrameClient
)
1130 if ( mClntWndBounds
.width
>= 1 && mClntWndBounds
.height
>= 1 )
1132 mpFrameClient
->SetSize( mClntWndBounds
.x
, mClntWndBounds
.y
,
1133 mClntWndBounds
.width
, mClntWndBounds
.height
, 0 );
1135 if ( !mpFrameClient
->IsShown() )
1137 mpFrameClient
->Show( TRUE
);
1140 mpFrameClient
->Show( FALSE
);
1144 void wxFrameLayout::PositionPanes()
1146 PositionClientWindow();
1148 // FOR NOW:: excessive updates!
1149 // reposition bars within all panes
1152 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1153 mPanes
[i
]->SizePaneObjects();
1156 void wxFrameLayout::OnSize( wxSizeEvent
& event
)
1158 if ( event
.GetEventObject() == (wxObject
*) mpFrame
)
1160 GetUpdatesManager().OnStartChanges();
1162 GetUpdatesManager().OnFinishChanges();
1163 GetUpdatesManager().UpdateNow();
1168 /*** protected members ***/
1170 void wxFrameLayout::HideBarWindows()
1173 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
1174 if ( mAllBars
[i
]->mpBarWnd
&& mAllBars
[i
]->mState
!= wxCBAR_FLOATING
)
1175 mAllBars
[i
]->mpBarWnd
->Show( FALSE
);
1177 // then floated frames
1179 ShowFloatedWindows( FALSE
);
1181 if ( mpFrameClient
)
1183 mpFrameClient
->Show( FALSE
);
1186 void wxFrameLayout::UnhookFromFrame()
1188 // NOTE:: the SetEvtHandlerEnabled() method is not used
1189 // here, since it is assumed that unhooking layout
1190 // from window may result destroying of the layout itself
1192 // BUG BUG BUG (wx):: this would not be a problem if
1193 // wxEvtHandler's destructor checked if
1194 // this handler is currently the top-most
1195 // handler of some window, and additionally
1196 // to the reconnecting itself from the chain.
1197 // It would also re-setup current event handler
1198 // of the window using wxWindow::SetEventHandler()
1202 if ( mpFrame
->GetEventHandler() == this )
1204 mpFrame
->PopEventHandler();
1210 if ( this == mpFrame
->GetEventHandler() )
1212 mpFrame
->SetEventHandler( this->GetNextHandler() );
1216 wxEvtHandler
* pCur
= mpFrame
->GetEventHandler();
1223 pCur
= pCur
->GetNextHandler();
1226 // do not try to unhook ourselves if we're not hooked yet
1231 if ( GetPreviousHandler() )
1232 GetPreviousHandler()->SetNextHandler( GetNextHandler() );
1235 mpFrame
->PopEventHandler();
1239 if ( GetNextHandler() )
1240 GetNextHandler()->SetPreviousHandler( GetPreviousHandler() );
1242 SetNextHandler( NULL
);
1243 SetPreviousHandler( NULL
);
1247 void wxFrameLayout::HookUpToFrame()
1249 // unhook us first, we're already hooked up
1253 // put ourselves on top
1255 mpFrame
->PushEventHandler( this );
1258 cbDockPane
* wxFrameLayout::GetBarPane( cbBarInfo
* pBar
)
1261 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1262 if ( mPanes
[i
]->BarPresent( pBar
) )
1268 void wxFrameLayout::CreateCursors()
1271 // FIXME:: The below code somehow doesn't work - cursors remain unchanged
1274 set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
1276 mpHorizCursor = new wxCursor( bits, 32, 16 );
1278 set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
1280 mpVertCursor = new wxCursor( bits, 32, 16 );
1283 // FOR NOW:: use standard ones
1285 mpHorizCursor
= new wxCursor(wxCURSOR_SIZEWE
);
1286 mpVertCursor
= new wxCursor(wxCURSOR_SIZENS
);
1287 mpNormalCursor
= new wxCursor(wxCURSOR_ARROW
);
1288 mpDragCursor
= new wxCursor(wxCURSOR_CROSS
);
1289 mpNECursor
= new wxCursor(wxCURSOR_NO_ENTRY
);
1291 mFloatingPosStep
.x
= 25;
1292 mFloatingPosStep
.y
= 25;
1294 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
1295 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
1298 bool wxFrameLayout::HitTestPane( cbDockPane
* pPane
, int x
, int y
)
1300 return rect_contains_point( pPane
->GetRealRect(), x
, y
);
1303 cbDockPane
* wxFrameLayout::HitTestPanes( const wxRect
& rect
,
1304 cbDockPane
* pCurPane
)
1306 // first, give the privilege to the current pane
1308 if ( pCurPane
&& rect_hits_rect( pCurPane
->GetRealRect(), rect
) )
1313 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1315 if ( pCurPane
!= mPanes
[i
] &&
1316 rect_hits_rect( mPanes
[i
]->GetRealRect(), rect
) )
1324 void wxFrameLayout::ForwardMouseEvent( wxMouseEvent
& event
,
1325 cbDockPane
* pToPane
,
1328 wxPoint
pos( event
.m_x
, event
.m_y
);
1329 pToPane
->FrameToPane( &pos
.x
, &pos
.y
);
1331 if ( eventType
== cbEVT_PL_LEFT_DOWN
)
1333 cbLeftDownEvent
evt( pos
, pToPane
);
1334 FirePluginEvent( evt
);
1336 else if ( eventType
== cbEVT_PL_LEFT_DCLICK
)
1338 cbLeftDClickEvent
evt( pos
, pToPane
);
1339 FirePluginEvent( evt
);
1341 else if ( eventType
== cbEVT_PL_LEFT_UP
)
1343 cbLeftUpEvent
evt( pos
, pToPane
);
1344 FirePluginEvent( evt
);
1346 else if ( eventType
== cbEVT_PL_RIGHT_DOWN
)
1348 cbRightDownEvent
evt( pos
, pToPane
);
1349 FirePluginEvent( evt
);
1351 else if ( eventType
== cbEVT_PL_RIGHT_UP
)
1353 cbRightUpEvent
evt( pos
, pToPane
);
1354 FirePluginEvent( evt
);
1356 else if ( eventType
== cbEVT_PL_MOTION
)
1358 cbMotionEvent
evt( pos
, pToPane
);
1359 FirePluginEvent( evt
);
1363 int avoidCompilerWarning
= 0;
1364 wxASSERT(avoidCompilerWarning
); // DBG::
1366 } // wxFrameLayout::ForwardMouseEvent()
1369 void wxFrameLayout::RouteMouseEvent( wxMouseEvent
& event
, int pluginEvtType
)
1371 if ( mpPaneInFocus
)
1373 ForwardMouseEvent( event
, mpPaneInFocus
, pluginEvtType
);
1377 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1379 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1381 ForwardMouseEvent( event
, mPanes
[i
], pluginEvtType
);
1388 /*** event handlers ***/
1390 void wxFrameLayout::OnRButtonDown( wxMouseEvent
& event
)
1392 RouteMouseEvent( event
, cbEVT_PL_RIGHT_DOWN
);
1395 void wxFrameLayout::OnRButtonUp( wxMouseEvent
& event
)
1397 RouteMouseEvent( event
, cbEVT_PL_RIGHT_UP
);
1400 void wxFrameLayout::OnLButtonDown( wxMouseEvent
& event
)
1402 RouteMouseEvent( event
, cbEVT_PL_LEFT_DOWN
);
1405 void wxFrameLayout::OnLDblClick( wxMouseEvent
& event
)
1407 RouteMouseEvent( event
, cbEVT_PL_LEFT_DCLICK
);
1410 void wxFrameLayout::OnLButtonUp( wxMouseEvent
& event
)
1412 RouteMouseEvent( event
, cbEVT_PL_LEFT_UP
);
1415 void wxFrameLayout::OnMouseMove( wxMouseEvent
& event
)
1417 if ( mpPaneInFocus
)
1419 ForwardMouseEvent( event
, mpPaneInFocus
, cbEVT_PL_MOTION
);
1423 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1425 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1427 if ( mpLRUPane
&& mpLRUPane
!= mPanes
[i
] )
1429 // simulate "mouse-leave" event
1430 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1433 ForwardMouseEvent( event
, mPanes
[i
], cbEVT_PL_MOTION
);
1435 mpLRUPane
= mPanes
[i
];
1444 // simulate "mouse-leave" event
1445 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1450 void wxFrameLayout::OnPaint( wxPaintEvent
& event
)
1452 if ( mRecalcPending
)
1453 RecalcLayout( TRUE
);
1455 wxPaintDC
dc(mpFrame
);
1458 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1460 wxRect
& rect
= mPanes
[i
]->mBoundsInParent
;
1462 dc
.SetClippingRegion( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1464 mPanes
[i
]->PaintPane(dc
);
1466 dc
.DestroyClippingRegion();
1472 void wxFrameLayout::OnEraseBackground( wxEraseEvent
& event
)
1477 void wxFrameLayout::OnIdle( wxIdleEvent
& event
)
1479 wxWindow
* focus
= wxWindow::FindFocus();
1481 if ( !focus
&& mCheckFocusWhenIdle
)
1483 wxMessageBox( "Hi, no more focus in this app!" );
1485 mCheckFocusWhenIdle
= FALSE
;
1486 //ShowFloatedWindows( FALSE );
1489 mCheckFocusWhenIdle
= FALSE
;
1495 void wxFrameLayout::OnKillFocus( wxFocusEvent
& event
)
1497 //wxMessageBox( "wxFrameLayoutGot Kill Focus!" );
1498 //ShowFloatedWindows( FALSE );
1501 void wxFrameLayout::OnSetFocus( wxFocusEvent
& event
)
1503 //ShowFloatedWindows( TRUE );
1506 void wxFrameLayout::OnActivate( wxActivateEvent
& event
)
1509 if ( event
.GetActive() == FALSE
)
1511 wxWindow
* focus
= wxWindow::FindFocus();
1513 if ( !focus
|| focus
== &GetParentFrame() )
1515 mCheckFocusWhenIdle
= TRUE
;
1519 wxMessageBox("Deactivated!" );
1526 void wxFrameLayout::GetPaneProperties( cbCommonPaneProperties
& props
, int alignment
)
1528 props
= mPanes
[alignment
]->mProps
;
1531 void wxFrameLayout::SetPaneProperties( const cbCommonPaneProperties
& props
, int paneMask
)
1534 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1536 if ( mPanes
[i
]->MatchesMask( paneMask
) )
1537 mPanes
[i
]->mProps
= props
;
1541 void wxFrameLayout::SetMargins( int top
, int bottom
, int left
, int right
,
1545 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1547 cbDockPane
& pane
= *mPanes
[i
];
1549 if ( pane
.MatchesMask( paneMask
) )
1551 pane
.mTopMargin
= top
;
1552 pane
.mBottomMargin
= bottom
;
1553 pane
.mLeftMargin
= left
;
1554 pane
.mRightMargin
= right
;
1559 void wxFrameLayout::SetPaneBackground( const wxColour
& colour
)
1561 mBorderPen
.SetColour( colour
);
1564 void wxFrameLayout::RefreshNow( bool recalcLayout
)
1567 RecalcLayout( TRUE
);
1573 /*** plugin-related methods ***/
1575 void wxFrameLayout::FirePluginEvent( cbPluginEvent
& event
)
1577 // check state of input capture, before processing the event
1579 if ( mpCaputesInput
)
1581 bool isInputEvt
= TRUE
;
1582 #if wxCHECK_VERSION(2,3,0)
1583 if ( event
.m_eventType
!= cbEVT_PL_LEFT_DOWN
&&
1584 event
.m_eventType
!= cbEVT_PL_LEFT_UP
&&
1585 event
.m_eventType
!= cbEVT_PL_RIGHT_DOWN
&&
1586 event
.m_eventType
!= cbEVT_PL_RIGHT_UP
&&
1587 event
.m_eventType
!= cbEVT_PL_MOTION
)
1590 switch ( event
.m_eventType
)
1592 case cbEVT_PL_LEFT_DOWN
: break;
1593 case cbEVT_PL_LEFT_UP
: break;
1594 case cbEVT_PL_RIGHT_DOWN
: break;
1595 case cbEVT_PL_RIGHT_UP
: break;
1596 case cbEVT_PL_MOTION
: break;
1598 default : isInputEvt
= FALSE
; break;
1600 #endif // #if wxCHECK_VERSION(2,3,0)
1604 mpCaputesInput
->ProcessEvent( event
);
1609 GetTopPlugin().ProcessEvent( event
);
1612 void wxFrameLayout::CaptureEventsForPlugin ( cbPluginBase
* pPlugin
)
1614 // cannot capture events for more than one plugin at a time
1615 wxASSERT( mpCaputesInput
== NULL
);
1617 mpCaputesInput
= pPlugin
;
1621 void wxFrameLayout::ReleaseEventsFromPlugin( cbPluginBase
* pPlugin
)
1623 // events should be captured first
1624 wxASSERT( mpCaputesInput
!= NULL
);
1626 mpCaputesInput
= NULL
;
1629 void wxFrameLayout::CaptureEventsForPane( cbDockPane
* toPane
)
1631 // cannot capture events twice (without releasing)
1632 wxASSERT( mpPaneInFocus
== NULL
);
1634 mpFrame
->CaptureMouse();
1636 mpPaneInFocus
= toPane
;
1639 void wxFrameLayout::ReleaseEventsFromPane( cbDockPane
* fromPane
)
1641 // cannot release events without capturing them
1642 wxASSERT( mpPaneInFocus
!= NULL
);
1644 mpFrame
->ReleaseMouse();
1646 mpPaneInFocus
= NULL
;
1649 cbPluginBase
& wxFrameLayout::GetTopPlugin()
1653 PushDefaultPlugins(); // automatic configuration
1655 return *mpTopPlugin
;
1658 void wxFrameLayout::SetTopPlugin( cbPluginBase
* pPlugin
)
1660 mpTopPlugin
= pPlugin
;
1663 bool wxFrameLayout::HasTopPlugin()
1665 return ( mpTopPlugin
!= NULL
);
1668 void wxFrameLayout::PushPlugin( cbPluginBase
* pPlugin
)
1672 mpTopPlugin
= pPlugin
;
1675 pPlugin
->SetNextHandler( mpTopPlugin
);
1677 mpTopPlugin
->SetPreviousHandler( pPlugin
);
1679 mpTopPlugin
= pPlugin
;
1682 mpTopPlugin
->OnInitPlugin(); // notification
1685 void wxFrameLayout::PopPlugin()
1687 wxASSERT( mpTopPlugin
); // DBG:: at least one plugin should be present
1689 cbPluginBase
* pPopped
= mpTopPlugin
;
1691 mpTopPlugin
= (cbPluginBase
*)mpTopPlugin
->GetNextHandler();
1696 void wxFrameLayout::PopAllPlugins()
1698 while( mpTopPlugin
) PopPlugin();
1701 void wxFrameLayout::PushDefaultPlugins()
1703 // FIXME:: to much of the stuff for the default...
1705 AddPlugin( CLASSINFO( cbRowLayoutPlugin
) );
1706 AddPlugin( CLASSINFO( cbBarDragPlugin
) );
1707 AddPlugin( CLASSINFO( cbPaneDrawPlugin
) );
1710 void wxFrameLayout::AddPlugin( wxClassInfo
* pPlInfo
, int paneMask
)
1712 if ( FindPlugin ( pPlInfo
) ) return; // same type of plugin cannot be added twice
1714 cbPluginBase
* pObj
= (cbPluginBase
*)pPlInfo
->CreateObject();
1716 wxASSERT(pObj
); // DBG:: plugin's class should be dynamic
1718 pObj
->mPaneMask
= paneMask
;
1719 pObj
->mpLayout
= this;
1724 void wxFrameLayout::AddPluginBefore( wxClassInfo
* pNextPlInfo
, wxClassInfo
* pPlInfo
,
1727 wxASSERT( pNextPlInfo
!= pPlInfo
); // DBG:: no sense
1729 cbPluginBase
* pNextPl
= FindPlugin( pNextPlInfo
);
1733 AddPlugin( pPlInfo
, paneMask
);
1738 // remove existing one if present
1740 cbPluginBase
* pExistingPl
= FindPlugin( pPlInfo
);
1742 if ( pExistingPl
) RemovePlugin( pPlInfo
);
1744 // create an instance
1746 cbPluginBase
* pNewPl
= (cbPluginBase
*)pPlInfo
->CreateObject();
1748 wxASSERT(pNewPl
); // DBG:: plugin's class should be dynamic
1750 // insert it to the chain
1752 if ( pNextPl
->GetPreviousHandler() )
1754 pNextPl
->GetPreviousHandler()->SetNextHandler( pNewPl
);
1756 mpTopPlugin
= pNewPl
;
1758 pNewPl
->SetNextHandler( pNextPl
);
1760 pNewPl
->SetPreviousHandler( pNextPl
->GetPreviousHandler() );
1762 pNextPl
->SetPreviousHandler( pNewPl
);
1766 pNewPl
->mPaneMask
= paneMask
;
1767 pNewPl
->mpLayout
= this;
1769 pNewPl
->OnInitPlugin();
1772 void wxFrameLayout::RemovePlugin( wxClassInfo
* pPlInfo
)
1774 cbPluginBase
* pPlugin
= FindPlugin( pPlInfo
);
1776 if ( !pPlugin
) return; // it's OK to remove not-existing plugin ;-)
1778 if ( pPlugin
->GetPreviousHandler() == NULL
)
1780 mpTopPlugin
= (cbPluginBase
*)pPlugin
->GetNextHandler();
1785 cbPluginBase
* wxFrameLayout::FindPlugin( wxClassInfo
* pPlInfo
)
1787 cbPluginBase
*pCur
= mpTopPlugin
;
1791 // NOTE:: it might appear useful matching plugin
1792 // classes "polymorphically":
1794 if ( pCur
->GetClassInfo()->IsKindOf( pPlInfo
) )
1798 pCur
= (cbPluginBase
*)pCur
->GetNextHandler();
1804 /***** Implementation for class cbUpdateMgrData *****/
1806 IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData
, wxObject
)
1808 cbUpdateMgrData::cbUpdateMgrData()
1810 : mPrevBounds( -1,-1,0,0 ),
1811 mIsDirty( TRUE
) // inidicate initial change
1814 void cbUpdateMgrData::StoreItemState( const wxRect
& boundsInParent
)
1816 mPrevBounds
= boundsInParent
;
1819 void cbUpdateMgrData::SetDirty( bool isDirty
)
1824 void cbUpdateMgrData::SetCustomData( wxObject
* pCustomData
)
1826 mpCustomData
= pCustomData
;
1829 /***** Implementation for class cbDockPane *****/
1831 void wxBarIterator::Reset()
1833 mpRow
= ( mpRows
->Count() ) ? (*mpRows
)[0] : NULL
;
1837 wxBarIterator::wxBarIterator( RowArrayT
& rows
)
1846 bool wxBarIterator::Next()
1851 mpBar
= mpBar
->mpNext
;
1854 if ( mpRow
->mBars
.GetCount() == 0 )
1859 mpBar
= mpRow
->mBars
[0];
1864 // skip to the next row
1866 mpRow
= mpRow
->mpNext
;
1870 mpBar
= mpRow
->mBars
[0];
1881 cbBarInfo
& wxBarIterator::BarInfo()
1886 cbRowInfo
& wxBarIterator::RowInfo()
1891 /***** Implementation for class cbBarDimHandlerBase *****/
1893 IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase
, wxObject
)
1895 cbBarDimHandlerBase::cbBarDimHandlerBase()
1899 void cbBarDimHandlerBase::AddRef()
1904 void cbBarDimHandlerBase::RemoveRef()
1906 if ( --mRefCount
<= 0 ) delete this;
1909 /***** Implementation for class cbDimInfo *****/
1911 IMPLEMENT_DYNAMIC_CLASS( cbDimInfo
, wxObject
)
1913 cbDimInfo::cbDimInfo()
1922 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1927 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1931 cbDimInfo::cbDimInfo( cbBarDimHandlerBase
* pDimHandler
,
1936 mIsFixed ( isFixed
),
1938 mpHandler( pDimHandler
)
1942 // int vtad = *((int*)mpHandler);
1943 mpHandler
->AddRef();
1947 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1952 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1956 cbDimInfo::cbDimInfo( int dh_x
, int dh_y
,
1964 cbBarDimHandlerBase
* pDimHandler
1966 : mVertGap ( vertGap
),
1967 mHorizGap ( horizGap
),
1968 mIsFixed ( isFixed
),
1969 mpHandler( pDimHandler
)
1973 // int vtad = *((int*)mpHandler);
1974 mpHandler
->AddRef();
1977 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= dh_x
;
1978 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= dh_y
;
1979 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= dv_x
;
1980 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= dv_y
;
1981 mSizes
[wxCBAR_FLOATING
].x
= f_x
;
1982 mSizes
[wxCBAR_FLOATING
].y
= f_y
;
1985 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1986 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1989 cbDimInfo::cbDimInfo( int x
, int y
,
1990 bool isFixed
, int gap
,
1991 cbBarDimHandlerBase
* pDimHandler
)
1994 mIsFixed ( isFixed
),
1995 mpHandler( pDimHandler
)
1999 // int vtad = *((int*)mpHandler);
2000 mpHandler
->AddRef();
2003 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= x
;
2004 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= y
;
2005 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= x
;
2006 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= y
;
2007 mSizes
[wxCBAR_FLOATING
].x
= x
;
2008 mSizes
[wxCBAR_FLOATING
].y
= y
;
2011 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2012 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
2015 cbDimInfo::~cbDimInfo()
2019 mpHandler
->RemoveRef();
2022 const cbDimInfo
& cbDimInfo::operator=( const cbDimInfo
& other
)
2024 if ( this == &other
)
2028 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2029 mSizes
[i
] = other
.mSizes
[i
];
2031 mIsFixed
= other
.mIsFixed
;
2032 mpHandler
= other
.mpHandler
;
2034 mVertGap
= other
.mVertGap
;
2035 mHorizGap
= other
.mHorizGap
;
2039 mpHandler
->AddRef();
2044 /***** Implementation for structure cbCommonPaneProperties *****/
2046 IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties
, wxObject
)
2048 cbCommonPaneProperties::cbCommonPaneProperties(void)
2050 : mRealTimeUpdatesOn ( TRUE
),
2051 mOutOfPaneDragOn ( TRUE
),
2052 mExactDockPredictionOn( FALSE
),
2053 mNonDestructFrictionOn( FALSE
),
2054 mShow3DPaneBorderOn ( TRUE
),
2055 mBarFloatingOn ( FALSE
),
2056 mRowProportionsOn ( FALSE
),
2057 mColProportionsOn ( TRUE
),
2058 mBarCollapseIconsOn ( FALSE
),
2059 mBarDragHintsOn ( FALSE
),
2061 mMinCBarDim( 16, 16 ),
2062 mResizeHandleSize( 4 )
2065 cbCommonPaneProperties::cbCommonPaneProperties(const cbCommonPaneProperties
& props
)
2068 mRealTimeUpdatesOn (props
.mRealTimeUpdatesOn
),
2069 mOutOfPaneDragOn (props
.mOutOfPaneDragOn
),
2070 mExactDockPredictionOn(props
.mExactDockPredictionOn
),
2071 mNonDestructFrictionOn(props
.mNonDestructFrictionOn
),
2072 mShow3DPaneBorderOn (props
.mShow3DPaneBorderOn
),
2073 mBarFloatingOn (props
.mBarFloatingOn
),
2074 mRowProportionsOn (props
.mRowProportionsOn
),
2075 mColProportionsOn (props
.mColProportionsOn
),
2076 mBarCollapseIconsOn (props
.mBarCollapseIconsOn
),
2077 mBarDragHintsOn (props
.mBarDragHintsOn
),
2079 mMinCBarDim(props
.mMinCBarDim
),
2080 mResizeHandleSize(props
.mResizeHandleSize
)
2083 cbCommonPaneProperties
& cbCommonPaneProperties::operator=(const cbCommonPaneProperties
& props
)
2085 mRealTimeUpdatesOn
= props
.mRealTimeUpdatesOn
;
2086 mOutOfPaneDragOn
= props
.mOutOfPaneDragOn
;
2087 mExactDockPredictionOn
= props
.mExactDockPredictionOn
;
2088 mNonDestructFrictionOn
= props
.mNonDestructFrictionOn
;
2089 mShow3DPaneBorderOn
= props
.mShow3DPaneBorderOn
;
2090 mBarFloatingOn
= props
.mBarFloatingOn
;
2091 mRowProportionsOn
= props
.mRowProportionsOn
;
2092 mColProportionsOn
= props
.mColProportionsOn
;
2093 mBarCollapseIconsOn
= props
.mBarCollapseIconsOn
;
2094 mBarDragHintsOn
= props
.mBarDragHintsOn
;
2096 mMinCBarDim
= props
.mMinCBarDim
;
2097 mResizeHandleSize
= props
.mResizeHandleSize
;
2102 /***** Implementation for class cbRowInfo *****/
2104 IMPLEMENT_DYNAMIC_CLASS( cbRowInfo
, wxObject
)
2106 cbRowInfo::cbRowInfo(void)
2108 : mNotFixedBarsCnt( FALSE
),
2111 mpExpandedBar ( NULL
)
2114 cbRowInfo::~cbRowInfo()
2116 // nothing! all bars are removed using global bar
2117 // list in wxFrameLayout class
2120 /***** Implementation for class cbBarInfo *****/
2122 IMPLEMENT_DYNAMIC_CLASS( cbBarInfo
, wxObject
)
2124 cbBarInfo::cbBarInfo(void)
2132 cbBarInfo::~cbBarInfo()
2137 /***** Implementation for class cbDockPane *****/
2139 IMPLEMENT_DYNAMIC_CLASS( cbDockPane
, wxObject
)
2141 // FIXME:: how to eliminate these cut&pasted constructors?
2143 cbDockPane::cbDockPane(void)
2144 : mLeftMargin ( 1 ),
2148 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2149 // since the real dimensions of the pane may not
2150 // be known, while inserting bars initially
2151 mPaneHeight( 32768 ),
2157 cbDockPane::cbDockPane( int alignment
, wxFrameLayout
* pPanel
)
2159 : mLeftMargin ( 1 ),
2163 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2164 // since the real dimensions of the pane may not
2165 // be known, while inserting bars initially
2166 mPaneHeight( 32768 ),
2167 mAlignment ( alignment
),
2168 mpLayout ( pPanel
),
2172 cbDockPane::~cbDockPane()
2175 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2178 mRowShapeData
.DeleteContents( TRUE
);
2180 // NOTE:: control bar infromation structures are cleaned-up
2181 // in wxFrameLayout's destructor, using global control-bar list
2184 void cbDockPane::SetMargins( int top
, int bottom
, int left
, int right
)
2187 mBottomMargin
= bottom
;
2189 mRightMargin
= right
;
2192 /*** helpers of cbDockPane ***/
2194 void cbDockPane::PaintBarDecorations( cbBarInfo
* pBar
, wxDC
& dc
)
2196 cbDrawBarDecorEvent
evt( pBar
, dc
, this );
2198 mpLayout
->FirePluginEvent( evt
);
2201 void cbDockPane::PaintBarHandles( cbBarInfo
* pBar
, wxDC
& dc
)
2203 cbDrawBarHandlesEvent
evt( pBar
, dc
, this );
2205 mpLayout
->FirePluginEvent( evt
);
2208 void cbDockPane::PaintBar( cbBarInfo
* pBar
, wxDC
& dc
)
2210 PaintBarDecorations( pBar
, dc
);
2211 PaintBarHandles( pBar
, dc
);
2214 void cbDockPane::PaintRowHandles( cbRowInfo
* pRow
, wxDC
& dc
)
2216 cbDrawRowHandlesEvent
evt( pRow
, dc
, this );
2218 mpLayout
->FirePluginEvent( evt
);
2220 cbDrawRowDecorEvent
evt1( pRow
, dc
, this );
2222 mpLayout
->FirePluginEvent( evt1
);
2225 void cbDockPane::PaintRowBackground ( cbRowInfo
* pRow
, wxDC
& dc
)
2227 cbDrawRowBkGroundEvent
evt( pRow
, dc
, this );
2229 mpLayout
->FirePluginEvent( evt
);
2232 void cbDockPane::PaintRowDecorations( cbRowInfo
* pRow
, wxDC
& dc
)
2236 // decorations first
2237 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2239 PaintBarDecorations( pRow
->mBars
[i
], dc
);
2241 // then handles if present
2242 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2244 PaintBarHandles( pRow
->mBars
[i
], dc
);
2247 void cbDockPane::PaintRow( cbRowInfo
* pRow
, wxDC
& dc
)
2249 PaintRowBackground ( pRow
, dc
);
2250 PaintRowDecorations( pRow
, dc
);
2251 PaintRowHandles ( pRow
, dc
);
2254 void cbDockPane::PaintPaneBackground( wxDC
& dc
)
2256 cbDrawPaneBkGroundEvent
evt( dc
, this );
2258 mpLayout
->FirePluginEvent( evt
);
2261 void cbDockPane::PaintPaneDecorations( wxDC
& dc
)
2263 cbDrawPaneDecorEvent
evt( dc
, this );
2265 mpLayout
->FirePluginEvent( evt
);
2268 void cbDockPane::PaintPane( wxDC
& dc
)
2270 PaintPaneBackground( dc
);
2274 // first decorations
2275 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2277 PaintRowBackground( mRows
[i
], dc
);
2278 PaintRowDecorations( mRows
[i
], dc
);
2282 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2283 PaintRowHandles( mRows
[i
], dc
);
2286 PaintPaneDecorations( dc
);
2289 void cbDockPane::SizeBar( cbBarInfo
* pBar
)
2291 cbSizeBarWndEvent
evt( pBar
, this );
2293 mpLayout
->FirePluginEvent( evt
);
2297 void cbDockPane::SizeRowObjects( cbRowInfo
* pRow
)
2300 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2301 SizeBar( pRow
->mBars
[i
] );
2304 void cbDockPane::SizePaneObjects()
2307 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2308 SizeRowObjects( mRows
[i
] );
2311 wxDC
* cbDockPane::StartDrawInArea( const wxRect
& area
)
2315 cbStartDrawInAreaEvent
evt( area
, &pDc
, this );
2317 mpLayout
->FirePluginEvent( evt
);
2322 void cbDockPane::FinishDrawInArea( const wxRect
& area
)
2324 cbFinishDrawInAreaEvent
evt( area
, this );
2326 mpLayout
->FirePluginEvent( evt
);
2329 bool cbDockPane::IsFixedSize( cbBarInfo
* pInfo
)
2331 return ( pInfo
->mDimInfo
.mIsFixed
);
2334 int cbDockPane::GetNotFixedBarsCount( cbRowInfo
* pRow
)
2339 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2341 if ( !pRow
->mBars
[i
]->IsFixed() )
2348 void cbDockPane::RemoveBar( cbBarInfo
* pBar
)
2350 bool needsRestoring
= mProps
.mNonDestructFrictionOn
&&
2351 mpStoredRow
== pBar
->mpRow
;
2353 cbRemoveBarEvent
evt( pBar
, this );
2355 mpLayout
->FirePluginEvent( evt
);
2357 if ( needsRestoring
)
2359 SetRowShapeData( mpStoredRow
, &mRowShapeData
);
2365 void cbDockPane::SyncRowFlags( cbRowInfo
* pRow
)
2367 // setup mHasOnlyFixedBars flag for the row information
2368 pRow
->mHasOnlyFixedBars
= TRUE
;
2370 pRow
->mNotFixedBarsCnt
= 0;
2373 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2375 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2379 if ( !bar
.IsFixed() )
2381 pRow
->mHasOnlyFixedBars
= FALSE
;
2382 ++pRow
->mNotFixedBarsCnt
;
2387 void cbDockPane::FrameToPane( int* x
, int* y
)
2392 if ( mAlignment
== FL_ALIGN_TOP
||
2393 mAlignment
== FL_ALIGN_BOTTOM
2396 *x
-= mBoundsInParent
.x
;
2397 *y
-= mBoundsInParent
.y
;
2401 int rx
= *x
, ry
= *y
;
2403 *x
= ry
- mBoundsInParent
.y
;
2405 *y
= rx
- mBoundsInParent
.x
;
2409 void cbDockPane::PaneToFrame( int* x
, int* y
)
2411 if ( mAlignment
== FL_ALIGN_TOP
||
2412 mAlignment
== FL_ALIGN_BOTTOM
2415 *x
+= mBoundsInParent
.x
;
2416 *y
+= mBoundsInParent
.y
;
2420 int rx
= *x
, ry
= *y
;
2422 *x
= ry
+ mBoundsInParent
.x
;
2424 *y
= mBoundsInParent
.y
+ rx
;
2431 void cbDockPane::FrameToPane( wxRect
* pRect
)
2433 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2434 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2435 pRect
->y
+ pRect
->height
);
2437 FrameToPane( &upperLeft
.x
, &upperLeft
.y
);
2438 FrameToPane( &lowerRight
.x
, &lowerRight
.y
);
2440 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2441 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2443 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2444 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2447 void cbDockPane::PaneToFrame( wxRect
* pRect
)
2449 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2450 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2451 pRect
->y
+ pRect
->height
);
2453 PaneToFrame( &upperLeft
.x
, &upperLeft
.y
);
2454 PaneToFrame( &lowerRight
.x
, &lowerRight
.y
);
2456 //wxRect newRect = wxRect( upperLeft, lowerRight );
2458 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2459 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2461 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2462 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2465 int cbDockPane::GetRowAt( int paneY
)
2474 for ( ; i
!= mRows
.Count(); ++i
)
2476 int rowHeight
= mRows
[i
]->mRowHeight
;
2478 int third
= rowHeight
/3;
2480 if ( paneY
>= curY
&& paneY
< curY
+ third
)
2483 if ( paneY
>= curY
+ third
&& paneY
< curY
+ rowHeight
- third
)
2492 int cbDockPane::GetRowAt( int upperY
, int lowerY
)
2496 int range = lowerY - upperY;
2497 int oneThird = range / 3;
2499 wxNode* pRow = mRows.First();
2503 if ( lowerY <= 0 ) return -1;
2507 int rowHeight = GetRowHeight( (wxList*)pRow->Data() );
2509 if ( upperY >= curY &&
2510 lowerY < curY ) return row;
2512 if ( upperY <= curY &&
2514 curY - upperY >= oneThird ) return row-1;
2516 if ( ( upperY < curY + rowHeight &&
2517 lowerY >= curY + rowHeight &&
2518 curY + rowHeight - lowerY >= oneThird )
2522 if ( lowerY <= curY + rowHeight ) return row;
2526 pRow = pRow->Next();
2530 int mid
= upperY
+ (lowerY
- upperY
)/2;
2538 for ( ; i
!= mRows
.Count(); ++i
)
2540 int rowHeight
= mRows
[i
]->mRowHeight
;
2542 if ( mid
>= curY
&& mid
< curY
+ rowHeight
) return i
;
2550 int cbDockPane::GetRowY( cbRowInfo
* pRow
)
2555 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2557 if ( mRows
[i
] == pRow
)
2560 curY
+= mRows
[i
]->mRowHeight
;
2566 bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo
* pRow
)
2568 while ( pRow
->mpPrev
)
2570 pRow
= pRow
->mpPrev
;
2572 if ( pRow
->mHasOnlyFixedBars
)
2580 bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo
* pRow
)
2582 while( pRow
->mpNext
)
2584 pRow
= pRow
->mpNext
;
2586 if ( pRow
->mHasOnlyFixedBars
)
2594 bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo
* pBar
)
2596 while( pBar
->mpPrev
)
2598 pBar
= pBar
->mpPrev
;
2600 if ( pBar
->IsFixed() )
2608 bool cbDockPane::HasNotFixedBarsRight( cbBarInfo
* pBar
)
2610 while( pBar
->mpNext
)
2612 pBar
= pBar
->mpNext
;
2614 if ( pBar
->IsFixed() )
2622 void cbDockPane::CalcLengthRatios( cbRowInfo
* pInRow
)
2628 // calc current-maximal-total-length of all maximized bars
2630 for ( i
= 0; i
!= pInRow
->mBars
.GetCount(); ++i
)
2632 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2634 if ( !bar
.IsFixed() )
2635 totalWidth
+= bar
.mBounds
.width
;
2638 // set up percentages of occupied space for each maximized bar
2640 for ( i
= 0; i
!= pInRow
->mBars
.Count(); ++i
)
2642 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2644 if ( !bar
.IsFixed() )
2645 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalWidth
);
2649 void cbDockPane::RecalcRowLayout( cbRowInfo
* pRow
)
2651 cbLayoutRowEvent
evt( pRow
, this );
2653 mpLayout
->FirePluginEvent( evt
);
2656 void cbDockPane::ExpandBar( cbBarInfo
* pBar
)
2658 mpLayout
->GetUpdatesManager().OnStartChanges();
2660 if ( !pBar
->mpRow
->mpExpandedBar
)
2662 // save ratios only when there arent any bars expanded yet
2664 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2667 ratios
.Alloc( pBar
->mpRow
->mNotFixedBarsCnt
);
2669 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2673 if ( !pCur
->IsFixed() )
2676 ratios
[ ratios
.GetCount() - 1 ] = pCur
->mLenRatio
;
2679 pCur
= pCur
->mpNext
;
2683 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2687 pCur
->mLenRatio
= 0.0; // minimize the rest
2689 pCur
= pCur
->mpNext
;
2692 pBar
->mLenRatio
= 1.0; // 100%
2693 pBar
->mBounds
.width
= 0;
2695 pBar
->mpRow
->mpExpandedBar
= pBar
;
2697 mpLayout
->RecalcLayout( FALSE
);
2699 mpLayout
->GetUpdatesManager().OnFinishChanges();
2700 mpLayout
->GetUpdatesManager().UpdateNow();
2703 void cbDockPane::ContractBar( cbBarInfo
* pBar
)
2705 mpLayout
->GetUpdatesManager().OnStartChanges();
2707 // FIXME: What's the purpose of this???
2708 // double ratio = 1.0/ double( pBar->mpRow->mNotFixedBarsCnt );
2710 // restore ratios which were present before expansion
2712 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2714 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2720 if ( !pCur
->IsFixed() )
2722 pCur
->mLenRatio
= ratios
[i
];
2726 pCur
= pCur
->mpNext
;
2732 pBar
->mpRow
->mpExpandedBar
= NULL
;
2734 mpLayout
->RecalcLayout( FALSE
);
2736 mpLayout
->GetUpdatesManager().OnFinishChanges();
2737 mpLayout
->GetUpdatesManager().UpdateNow();
2740 void cbDockPane::InitLinksForRow( cbRowInfo
* pRow
)
2743 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2745 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2750 bar
.mpPrev
= pRow
->mBars
[i
-1];
2752 if ( i
== pRow
->mBars
.Count() - 1 )
2755 bar
.mpNext
= pRow
->mBars
[i
+1];
2759 void cbDockPane::InitLinksForRows()
2762 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2764 cbRowInfo
& row
= *mRows
[i
];
2769 row
.mpPrev
= mRows
[i
-1];
2771 if ( i
== mRows
.Count() - 1 )
2774 row
.mpNext
= mRows
[i
+1];
2778 void cbDockPane::DoInsertBar( cbBarInfo
* pBar
, int rowNo
)
2780 cbRowInfo
* pRow
= NULL
;
2782 if ( rowNo
== -1 || rowNo
>= (int)mRows
.Count() )
2784 pRow
= new cbRowInfo();
2786 if ( rowNo
== -1 && mRows
.Count() )
2788 mRows
.Insert( pRow
, 0 );
2796 pRow
= mRows
[rowNo
];
2798 if ( mProps
.mNonDestructFrictionOn
== TRUE
)
2800 // store original shape of the row (before the bar is inserted)
2804 GetRowShapeData( mpStoredRow
, &mRowShapeData
);
2808 if ( pRow
->mBars
.Count() )
2810 pRow
->mpExpandedBar
= NULL
;
2812 cbInsertBarEvent
insEvt( pBar
, pRow
, this );
2814 mpLayout
->FirePluginEvent( insEvt
);
2816 mpLayout
->GetUpdatesManager().OnRowWillChange( pRow
, this );
2819 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
, const wxRect
& atRect
)
2821 wxRect rect
= atRect
;
2822 FrameToPane( &rect
);
2824 pBarInfo
->mBounds
.x
= rect
.x
;
2825 pBarInfo
->mBounds
.width
= rect
.width
;
2826 pBarInfo
->mBounds
.height
= rect
.height
;
2828 int row
= GetRowAt( rect
.y
, rect
.y
+ rect
.height
);
2830 DoInsertBar( pBarInfo
, row
);
2833 void cbDockPane::InsertBar( cbBarInfo
* pBar
, cbRowInfo
* pIntoRow
)
2835 cbInsertBarEvent
insEvt( pBar
, pIntoRow
, this );
2837 mpLayout
->FirePluginEvent( insEvt
);
2839 mpLayout
->GetUpdatesManager().OnRowWillChange( pIntoRow
, this );
2842 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
)
2844 // set transient properties
2846 pBarInfo
->mpRow
= NULL
;
2847 pBarInfo
->mHasLeftHandle
= FALSE
;
2848 pBarInfo
->mHasRightHandle
= FALSE
;
2849 pBarInfo
->mLenRatio
= 0.0;
2851 // set preferred bar dimensions, according to the state in which
2852 // the bar is being inserted
2854 pBarInfo
->mBounds
.width
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].x
;
2855 pBarInfo
->mBounds
.height
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].y
;
2857 DoInsertBar( pBarInfo
, pBarInfo
->mRowNo
);
2860 void cbDockPane::RemoveRow( cbRowInfo
* pRow
)
2863 // first, hide all bar-windows in the removed row
2864 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2866 if ( pRow
->mBars
[i
]->mpBarWnd
)
2867 pRow
->mBars
[i
]->mpBarWnd
->Show( FALSE
);
2870 mRows
.Remove( pRow
);
2872 pRow
->mUMgrData
.SetDirty(TRUE
);
2875 void cbDockPane::InsertRow( cbRowInfo
* pRow
, cbRowInfo
* pBeforeRow
)
2881 mRows
.Insert( pRow
, mRows
.Index( pBeforeRow
) );
2885 pRow
->mUMgrData
.SetDirty(TRUE
);
2888 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2889 pRow
->mBars
[i
]->mUMgrData
.SetDirty( TRUE
);
2891 SyncRowFlags( pRow
);
2894 void cbDockPane::SetPaneWidth(int width
)
2896 if ( IsHorizontal() )
2897 mPaneWidth
= width
- mLeftMargin
- mRightMargin
;
2899 mPaneWidth
= width
- mTopMargin
- mBottomMargin
;
2903 void cbDockPane::SetBoundsInParent( const wxRect
& rect
)
2905 mBoundsInParent
= rect
;
2907 // set pane dimensions in local coordinates
2909 if ( IsHorizontal() )
2911 mPaneWidth
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2912 mPaneHeight
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2916 mPaneWidth
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2917 mPaneHeight
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2920 // convert bounding rectangles of all pane items into parent frame's coordinates
2922 wxBarIterator
i( mRows
);
2924 wxRect noMarginsRect
= mBoundsInParent
;
2926 noMarginsRect
.x
+= mLeftMargin
;
2927 noMarginsRect
.y
+= mTopMargin
;
2928 noMarginsRect
.width
-= ( mLeftMargin
+ mRightMargin
);
2929 noMarginsRect
.height
-= ( mTopMargin
+ mBottomMargin
);
2931 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2933 if ( mBoundsInParent
.width
< 0 ||
2934 mBoundsInParent
.height
< 0 )
2936 hide_rect( mBoundsInParent
);
2938 if ( noMarginsRect
.width
< 0 ||
2939 noMarginsRect
.height
< 0 )
2941 hide_rect( noMarginsRect
);
2943 // calculate mBoundsInParent for each item in the pane
2947 cbBarInfo
& bar
= i
.BarInfo();
2949 cbRowInfo
* pRowInfo
= bar
.mpRow
;
2951 // set up row info, if this is first bar in the row
2953 if ( pRowInfo
&& bar
.mpPrev
== NULL
)
2955 pRowInfo
->mBoundsInParent
.y
= pRowInfo
->mRowY
;
2956 pRowInfo
->mBoundsInParent
.x
= 0;
2957 pRowInfo
->mBoundsInParent
.width
= mPaneWidth
;
2958 pRowInfo
->mBoundsInParent
.height
= pRowInfo
->mRowHeight
;
2960 PaneToFrame( &pRowInfo
->mBoundsInParent
);
2962 clip_rect_against_rect( pRowInfo
->mBoundsInParent
, noMarginsRect
);
2965 wxRect bounds
= bar
.mBounds
;
2967 // exclude dimensions of handles, when calculating
2968 // bar's bounds in parent (i.e. "visual bounds")
2970 if ( bar
.mHasLeftHandle
)
2972 bounds
.x
+= mProps
.mResizeHandleSize
;
2973 bounds
.width
-= mProps
.mResizeHandleSize
;
2976 if ( bar
.mHasRightHandle
)
2978 bounds
.width
-= mProps
.mResizeHandleSize
;
2980 PaneToFrame( &bounds
);
2982 clip_rect_against_rect( bounds
, noMarginsRect
);
2984 bar
.mBoundsInParent
= bounds
;
2988 bool cbDockPane::BarPresent( cbBarInfo
* pBar
)
2990 wxBarIterator
iter( mRows
);
2992 while( iter
.Next() )
2994 if ( &iter
.BarInfo() == pBar
) return TRUE
;
2999 cbRowInfo
* cbDockPane::GetRow( int row
)
3001 if ( row
>= (int)mRows
.Count() ) return NULL
;
3003 return mRows
[ row
];
3006 int cbDockPane::GetRowIndex( cbRowInfo
* pRow
)
3009 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3011 if ( mRows
[i
] == pRow
)
3015 wxFAIL_MSG("Row must be present to call cbDockPane::GetRowIndex()");
3020 int cbDockPane::GetPaneHeight()
3022 // first, recalculate row heights and the Y-positions
3024 cbLayoutRowsEvent
evt( this );
3025 mpLayout
->FirePluginEvent( evt
);
3029 if ( IsHorizontal() )
3031 height
+= mTopMargin
+ mBottomMargin
;
3033 height
+= mLeftMargin
+ mRightMargin
;
3035 int count
= mRows
.Count();
3039 height
+= mRows
[count
-1]->mRowY
+ mRows
[count
-1]->mRowHeight
;
3044 int cbDockPane::GetAlignment()
3049 bool cbDockPane::MatchesMask( int paneMask
)
3053 // FIXME:: use array instead of switch()
3057 case FL_ALIGN_TOP
: thisMask
= FL_ALIGN_TOP_PANE
; break;
3058 case FL_ALIGN_BOTTOM
: thisMask
= FL_ALIGN_BOTTOM_PANE
;break;
3059 case FL_ALIGN_LEFT
: thisMask
= FL_ALIGN_LEFT_PANE
; break;
3060 case FL_ALIGN_RIGHT
: thisMask
= FL_ALIGN_RIGHT_PANE
; break;
3063 wxFAIL_MSG("Bad FL alignment type detected in cbDockPane::MatchesMask()");
3066 return ( thisMask
& paneMask
) != 0;
3069 void cbDockPane::RecalcLayout()
3071 // first, reposition rows and items vertically
3073 cbLayoutRowsEvent
evt( this );
3074 mpLayout
->FirePluginEvent( evt
);
3076 // then horizontally in each row
3079 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3080 RecalcRowLayout( mRows
[i
] );
3083 int cbDockPane::GetDockingState()
3085 if ( mAlignment
== FL_ALIGN_TOP
||
3086 mAlignment
== FL_ALIGN_BOTTOM
)
3088 return wxCBAR_DOCKED_HORIZONTALLY
;
3091 return wxCBAR_DOCKED_VERTICALLY
;
3094 inline bool cbDockPane::HasPoint( const wxPoint
& pos
, int x
, int y
,
3095 int width
, int height
)
3097 return ( pos
.x
>= x
&&
3099 pos
.x
< x
+ width
&&
3100 pos
.y
< y
+ height
);
3103 int cbDockPane::HitTestPaneItems( const wxPoint
& pos
,
3112 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3114 cbRowInfo
& row
= *mRows
[i
];
3118 // hit-test handles of the row, if present
3120 if ( row
.mHasUpperHandle
)
3122 if ( HasPoint( pos
, 0, row
.mRowY
,
3123 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3125 return CB_UPPER_ROW_HANDLE_HITTED
;
3128 if ( row
.mHasLowerHandle
)
3130 if ( HasPoint( pos
, 0, row
.mRowY
+ row
.mRowHeight
- mProps
.mResizeHandleSize
,
3131 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3133 return CB_LOWER_ROW_HANDLE_HITTED
;
3136 // hit-test bar handles and bar content
3139 for ( k
= 0; k
!= row
.mBars
.Count(); ++k
)
3141 cbBarInfo
& bar
= *row
.mBars
[k
];
3142 wxRect
& bounds
= bar
.mBounds
;
3146 if ( bar
.mHasLeftHandle
)
3148 if ( HasPoint( pos
, bounds
.x
, bounds
.y
,
3149 mProps
.mResizeHandleSize
, bounds
.height
) )
3151 return CB_LEFT_BAR_HANDLE_HITTED
;
3154 if ( bar
.mHasRightHandle
)
3156 if ( HasPoint( pos
, bounds
.x
+ bounds
.width
- mProps
.mResizeHandleSize
, bounds
.y
,
3157 mProps
.mResizeHandleSize
, bounds
.height
) )
3159 return CB_RIGHT_BAR_HANDLE_HITTED
;
3162 if ( HasPoint( pos
, bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
) )
3163 return CB_BAR_CONTENT_HITTED
;
3165 } // hit-test next bar
3169 return CB_NO_ITEMS_HITTED
;
3172 void cbDockPane::GetBarResizeRange( cbBarInfo
* pBar
, int* from
, int *till
,
3173 bool forLeftHandle
)
3175 cbBarInfo
* pGivenBar
= pBar
;
3179 // calc unavailable space from the left
3181 while( pBar
->mpPrev
)
3183 pBar
= pBar
->mpPrev
;
3185 if ( !pBar
->IsFixed() ) notFree
+= mProps
.mMinCBarDim
.x
;
3186 else notFree
+= pBar
->mBounds
.width
;
3195 // calc unavailable space from the right
3197 while( pBar
->mpNext
)
3199 pBar
= pBar
->mpNext
;
3201 if ( pBar
->mBounds
.x
>= mPaneWidth
) break;
3203 // treat not-fixed bars as minimized
3205 if ( !pBar
->IsFixed() )
3207 notFree
+= mProps
.mMinCBarDim
.x
;
3210 if ( pBar
->mBounds
.x
+ pBar
->mBounds
.width
>= mPaneWidth
)
3212 notFree
+= mPaneWidth
- pBar
->mBounds
.x
;
3216 notFree
+= pBar
->mBounds
.width
;
3221 *till
= mPaneWidth
- notFree
;
3223 // do not let resizing totally deform the bar itself
3225 if ( forLeftHandle
)
3227 (*till
) -= mProps
.mMinCBarDim
.x
;
3230 (*from
) += mProps
.mMinCBarDim
.x
;
3233 int cbDockPane::GetMinimalRowHeight( cbRowInfo
* pRow
)
3235 int height
= mProps
.mMinCBarDim
.y
;
3238 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3240 if ( pRow
->mBars
[i
]->IsFixed() )
3241 height
= wxMax( height
, pRow
->mBars
[i
]->mBounds
.height
);
3244 if ( pRow
->mHasUpperHandle
)
3245 height
+= mProps
.mResizeHandleSize
;
3247 if ( pRow
->mHasLowerHandle
)
3248 height
+= mProps
.mResizeHandleSize
;
3253 void cbDockPane::SetRowHeight( cbRowInfo
* pRow
, int newHeight
)
3255 if ( pRow
->mHasUpperHandle
)
3257 newHeight
-= mProps
.mResizeHandleSize
;
3259 if ( pRow
->mHasLowerHandle
)
3261 newHeight
-= mProps
.mResizeHandleSize
;
3264 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3266 if ( !pRow
->mBars
[i
]->IsFixed() )
3267 pRow
->mBars
[i
]->mBounds
.height
= newHeight
;
3271 void cbDockPane::GetRowResizeRange( cbRowInfo
* pRow
, int* from
, int* till
,
3272 bool forUpperHandle
)
3274 cbRowInfo
* pGivenRow
= pRow
;
3276 // calc unavailable space from above
3280 while( pRow
->mpPrev
)
3282 pRow
= pRow
->mpPrev
;
3284 notFree
+= GetMinimalRowHeight( pRow
);
3290 // allow accupy the client window space by resizing pane rows
3291 if ( mAlignment
== FL_ALIGN_BOTTOM
)
3293 *from
-= mpLayout
->GetClientHeight();
3295 if ( mAlignment
== FL_ALIGN_RIGHT
)
3297 *from
-= mpLayout
->GetClientWidth();
3299 // calc unavailable space from below
3305 while( pRow
->mpNext
)
3307 pRow
= pRow
->mpNext
;
3309 notFree
+= GetMinimalRowHeight( pRow
);
3313 *till
= mPaneHeight
- notFree
;
3315 // allow adjustinig pane space vs. client window space by resizing pane row heights
3317 if ( mAlignment
== FL_ALIGN_TOP
)
3319 *till
+= mpLayout
->GetClientHeight();
3321 if ( mAlignment
== FL_ALIGN_LEFT
)
3323 *till
+= mpLayout
->GetClientWidth();
3325 // do not let the resizing of the row totally squeeze the row itself
3327 cbRowInfo
& row
= *pGivenRow
;
3329 if ( forUpperHandle
)
3331 *till
= row
.mRowY
+ row
.mRowHeight
- GetMinimalRowHeight( pGivenRow
);
3333 if ( row
.mHasUpperHandle
)
3335 *till
-= mProps
.mResizeHandleSize
;
3339 *from
+= GetMinimalRowHeight( pGivenRow
);
3341 if ( row
.mHasLowerHandle
)
3343 *from
-= mProps
.mResizeHandleSize
;
3347 void cbDockPane::ResizeRow( cbRowInfo
* pRow
, int ofs
,
3348 bool forUpperHandle
)
3350 cbResizeRowEvent
evt( pRow
, ofs
, forUpperHandle
, this );
3352 mpLayout
->FirePluginEvent( evt
);
3355 void cbDockPane::ResizeBar( cbBarInfo
* pBar
, int ofs
,
3356 bool forLeftHandle
)
3358 pBar
->mpRow
->mpExpandedBar
= NULL
;
3360 mpLayout
->GetUpdatesManager().OnStartChanges();
3362 wxRect
& bounds
= pBar
->mBounds
;
3364 if ( forLeftHandle
)
3366 // do not allow bar width become less then minimal
3367 if ( bounds
.x
+ ofs
> bounds
.x
+ bounds
.width
- mProps
.mMinCBarDim
.x
)
3369 bounds
.width
= mProps
.mMinCBarDim
.x
;
3375 bounds
.width
-= ofs
;
3380 // move bar left if necessary
3381 if ( bounds
.width
+ ofs
< mProps
.mMinCBarDim
.x
)
3383 bounds
.x
= bounds
.x
+ bounds
.width
+ ofs
- mProps
.mMinCBarDim
.x
;
3384 bounds
.width
= mProps
.mMinCBarDim
.x
;
3387 // resize right border only
3388 bounds
.width
+= ofs
;
3392 cbRowInfo
* pToRow
= pBar
->mpRow
;
3394 this->RemoveBar( pBar
);
3396 InsertBar( pBar
, pToRow
);
3398 mpLayout
->RecalcLayout(FALSE
);
3400 mpLayout
->GetUpdatesManager().OnFinishChanges();
3401 mpLayout
->GetUpdatesManager().UpdateNow();
3405 /*** row/bar resizing related methods ***/
3407 void cbDockPane::DrawVertHandle( wxDC
& dc
, int x
, int y
, int height
)
3409 int lower
= y
+ height
;
3411 dc
.SetPen( mpLayout
->mLightPen
);
3412 dc
.DrawLine( x
,y
, x
, lower
);
3414 dc
.SetPen( mpLayout
->mGrayPen
);
3416 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3419 dc
.DrawLine( x
,y
, x
, lower
);
3422 dc
.SetPen( mpLayout
->mDarkPen
);
3424 dc
.DrawLine( x
,y
, x
, lower
);
3426 dc
.SetPen( mpLayout
->mBlackPen
);
3428 dc
.DrawLine( x
,y
, x
, lower
);
3431 void cbDockPane::DrawHorizHandle( wxDC
& dc
, int x
, int y
, int width
)
3433 int right
= x
+ width
;
3435 dc
.SetPen( mpLayout
->mLightPen
);
3436 dc
.DrawLine( x
,y
, right
, y
);
3438 dc
.SetPen( mpLayout
->mGrayPen
);
3441 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3444 dc
.DrawLine( x
,y
, right
, y
);
3447 dc
.SetPen( mpLayout
->mDarkPen
);
3448 dc
.DrawLine( x
,y
, right
, ++y
);
3450 dc
.SetPen( mpLayout
->mBlackPen
);
3451 dc
.DrawLine( x
,y
, right
, ++y
);
3454 cbBarInfo
* cbDockPane::GetBarInfoByWindow( wxWindow
* pBarWnd
)
3456 wxBarIterator
i( mRows
);
3460 if ( i
.BarInfo().mpBarWnd
== pBarWnd
)
3462 return &i
.BarInfo();
3467 void cbDockPane::GetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3469 pLst
->DeleteContents( TRUE
);
3473 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3475 cbBarInfo
& bar
= *pRow
->mBars
[i
];
3477 cbBarShapeData
* pData
= new cbBarShapeData();
3479 pLst
->Append( (wxObject
*)pData
);
3481 pData
->mBounds
= bar
.mBounds
;
3482 pData
->mLenRatio
= bar
.mLenRatio
;
3486 void cbDockPane::SetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3488 if ( pLst
->First() == NULL
)
3491 wxNode
* pData
= pLst
->First();
3494 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3496 wxASSERT( pData
); // DBG::
3498 cbBarInfo
& bar
= *pRow
->mBars
[i
];;
3500 cbBarShapeData
& data
= *((cbBarShapeData
*)pData
->Data());
3502 bar
.mBounds
= data
.mBounds
;
3503 bar
.mLenRatio
= data
.mLenRatio
;
3505 pData
= pData
->Next();
3509 /***** Implementation for class cbUpdatesManagerBase *****/
3511 IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase
, wxObject
)
3513 /***** Implementation for class cbPluginBase *****/
3515 IMPLEMENT_ABSTRACT_CLASS( cbPluginBase
, wxEvtHandler
)
3517 cbPluginBase::~cbPluginBase()
3522 bool cbPluginBase::ProcessEvent(wxEvent
& event
)
3524 if ( mPaneMask
== wxALL_PANES
)
3526 return wxEvtHandler::ProcessEvent( event
);
3528 // extract mask info. from received event
3530 cbPluginEvent
& evt
= *( (cbPluginEvent
*)&event
);
3532 if ( evt
.mpPane
== 0 &&
3533 mPaneMask
== wxALL_PANES
)
3535 return wxEvtHandler::ProcessEvent( event
);
3539 switch ( evt
.mpPane
->mAlignment
)
3541 case FL_ALIGN_TOP
: mask
= FL_ALIGN_TOP_PANE
; break;
3542 case FL_ALIGN_BOTTOM
: mask
= FL_ALIGN_BOTTOM_PANE
;break;
3543 case FL_ALIGN_LEFT
: mask
= FL_ALIGN_LEFT_PANE
; break;
3544 case FL_ALIGN_RIGHT
: mask
= FL_ALIGN_RIGHT_PANE
; break;
3547 // if event's pane maks matches the plugin's mask
3549 if ( mPaneMask
& mask
)
3551 return wxEvtHandler::ProcessEvent( event
);
3553 // otherwise pass to the next handler if present
3555 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event
) )