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
| wxFRAME_TOOL_WINDOW
902 pMiniFrm
->SetClient( pBar
->mpBarWnd
);
904 ReparentWindow( pBar
->mpBarWnd
, pMiniFrm
);
906 mFloatedFrames
.Append( pMiniFrm
);
908 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
910 // check if it wasn't floated anytime before
912 if ( bounds
.width
== -1 )
914 wxRect
& clntRect
= GetClientRect();
916 // adjust position into which the next floated bar will be placed
918 if ( mNextFloatedWndPos
.x
+ bounds
.width
> clntRect
.width
)
920 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
922 if ( mNextFloatedWndPos
.y
+ bounds
.height
> clntRect
.height
)
924 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
926 bounds
.x
= mNextFloatedWndPos
.x
+ clntRect
.x
;
927 bounds
.y
= mNextFloatedWndPos
.y
+ clntRect
.y
;
929 bounds
.width
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].x
;
930 bounds
.height
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].y
;
932 mNextFloatedWndPos
.x
+= mFloatingPosStep
.x
;
933 mNextFloatedWndPos
.y
+= mFloatingPosStep
.y
;
936 pMiniFrm
->Show( TRUE
);
938 // FIXME:: this is excessive
939 pBar
->mpBarWnd
->Show(TRUE
);
943 void wxFrameLayout::RemoveBar( cbBarInfo
* pBarInfo
)
945 // first, try to "guess" what was the perviouse state of the bar
950 if ( LocateBar( pBarInfo
, &pRow
, &pPane
) )
952 // ...aha, bar was docked into one of the panes,
953 // remove it from there
955 pPane
->RemoveBar( pBarInfo
);
959 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
961 if ( mAllBars
[i
] == pBarInfo
)
963 #if wxCHECK_VERSION(2,3,2)
964 mAllBars
.RemoveAt(i
);
968 if ( pBarInfo
->mpBarWnd
) // hides it's window
970 pBarInfo
->mpBarWnd
->Show( FALSE
);
977 wxFAIL_MSG("bar info should be present in the list of all bars of all panes");
980 bool wxFrameLayout::LocateBar( cbBarInfo
* pBarInfo
,
982 cbDockPane
** ppPane
)
988 for ( n
= 0; n
!= MAX_PANES
; ++n
)
990 wxBarIterator
i( mPanes
[n
]->GetRowList() );
994 if ( &i
.BarInfo() == pBarInfo
)
996 (*ppPane
) = mPanes
[n
];
997 (*ppRow
) = &i
.RowInfo();
1006 void wxFrameLayout::RecalcLayout( bool repositionBarsNow
)
1008 mRecalcPending
= FALSE
;
1010 int frmWidth
, frmHeight
;
1011 mpFrame
->GetClientSize( &frmWidth
, &frmHeight
);
1018 // pane positioning priorities in decreasing order:
1019 // top, bottom, left, right
1023 cbDockPane
* pPane
= mPanes
[ FL_ALIGN_TOP
];
1025 pPane
->SetPaneWidth( frmWidth
);
1026 pPane
->RecalcLayout();
1028 paneHeight
= pPane
->GetPaneHeight();
1032 rect
.width
= frmWidth
;
1033 rect
.height
= wxMin( paneHeight
, frmHeight
- curY
);
1035 pPane
->SetBoundsInParent( rect
);
1039 // setup BOTTOM pane
1041 pPane
= mPanes
[ FL_ALIGN_BOTTOM
];
1043 pPane
->SetPaneWidth( frmWidth
);
1044 pPane
->RecalcLayout();
1046 paneHeight
= pPane
->GetPaneHeight();
1049 rect
.y
= wxMax( frmHeight
- paneHeight
, curY
);
1050 rect
.width
= frmWidth
;
1051 rect
.height
= frmHeight
- rect
.y
;
1053 pPane
->SetBoundsInParent( rect
);
1057 pPane
= mPanes
[ FL_ALIGN_LEFT
];
1060 pPane
->SetPaneWidth( rect
.y
- curY
);
1062 pPane
->RecalcLayout();
1063 paneHeight
= pPane
->GetPaneHeight();
1066 rect
.height
= rect
.y
- curY
;
1069 rect
.width
= wxMin( paneHeight
, frmWidth
);
1071 pPane
->SetBoundsInParent( rect
);
1077 pPane
= mPanes
[ FL_ALIGN_RIGHT
];
1079 // left pane's height
1080 pPane
->SetPaneWidth( rect
.height
);
1082 pPane
->RecalcLayout();
1083 paneHeight
= pPane
->GetPaneHeight();
1085 // left pane's height
1086 rect
.height
= rect
.height
;
1087 rect
.x
= wxMax( frmWidth
- paneHeight
, curX
);
1089 rect
.width
= frmWidth
- rect
.x
;
1091 pPane
->SetBoundsInParent( rect
);
1093 // recalc bounds of the client-window
1095 mClntWndBounds
.x
= mPanes
[FL_ALIGN_LEFT
]->mBoundsInParent
.x
+
1096 mPanes
[FL_ALIGN_LEFT
]->mBoundsInParent
.width
;
1097 mClntWndBounds
.y
= mPanes
[FL_ALIGN_TOP
]->mBoundsInParent
.y
+
1098 mPanes
[FL_ALIGN_TOP
]->mBoundsInParent
.height
;
1100 mClntWndBounds
.width
= mPanes
[FL_ALIGN_RIGHT
]->mBoundsInParent
.x
-
1102 mClntWndBounds
.height
= mPanes
[FL_ALIGN_BOTTOM
]->mBoundsInParent
.y
-
1105 if ( repositionBarsNow
)
1110 int wxFrameLayout::GetClientHeight()
1112 // for better portablility wxWindow::GetSzie() is not used here
1114 return mClntWndBounds
.height
;
1117 int wxFrameLayout::GetClientWidth()
1119 // for better portablility wxWindow::GetSzie() is not used here
1121 return mClntWndBounds
.width
;
1124 void wxFrameLayout::PositionClientWindow()
1126 if ( mpFrameClient
)
1128 if ( mClntWndBounds
.width
>= 1 && mClntWndBounds
.height
>= 1 )
1130 mpFrameClient
->SetSize( mClntWndBounds
.x
, mClntWndBounds
.y
,
1131 mClntWndBounds
.width
, mClntWndBounds
.height
, 0 );
1133 if ( !mpFrameClient
->IsShown() )
1135 mpFrameClient
->Show( TRUE
);
1138 mpFrameClient
->Show( FALSE
);
1142 void wxFrameLayout::PositionPanes()
1144 PositionClientWindow();
1146 // FOR NOW:: excessive updates!
1147 // reposition bars within all panes
1150 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1151 mPanes
[i
]->SizePaneObjects();
1154 void wxFrameLayout::OnSize( wxSizeEvent
& event
)
1156 if ( event
.GetEventObject() == (wxObject
*) mpFrame
)
1158 GetUpdatesManager().OnStartChanges();
1160 GetUpdatesManager().OnFinishChanges();
1161 GetUpdatesManager().UpdateNow();
1166 /*** protected members ***/
1168 void wxFrameLayout::HideBarWindows()
1171 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
1172 if ( mAllBars
[i
]->mpBarWnd
&& mAllBars
[i
]->mState
!= wxCBAR_FLOATING
)
1173 mAllBars
[i
]->mpBarWnd
->Show( FALSE
);
1175 // then floated frames
1177 ShowFloatedWindows( FALSE
);
1179 if ( mpFrameClient
)
1181 mpFrameClient
->Show( FALSE
);
1184 void wxFrameLayout::UnhookFromFrame()
1186 // NOTE:: the SetEvtHandlerEnabled() method is not used
1187 // here, since it is assumed that unhooking layout
1188 // from window may result destroying of the layout itself
1190 // BUG BUG BUG (wx):: this would not be a problem if
1191 // wxEvtHandler's destructor checked if
1192 // this handler is currently the top-most
1193 // handler of some window, and additionally
1194 // to the reconnecting itself from the chain.
1195 // It would also re-setup current event handler
1196 // of the window using wxWindow::SetEventHandler()
1200 if ( mpFrame
->GetEventHandler() == this )
1202 mpFrame
->PopEventHandler();
1208 if ( this == mpFrame
->GetEventHandler() )
1210 mpFrame
->SetEventHandler( this->GetNextHandler() );
1214 wxEvtHandler
* pCur
= mpFrame
->GetEventHandler();
1221 pCur
= pCur
->GetNextHandler();
1224 // do not try to unhook ourselves if we're not hooked yet
1229 if ( GetPreviousHandler() )
1230 GetPreviousHandler()->SetNextHandler( GetNextHandler() );
1233 mpFrame
->PopEventHandler();
1237 if ( GetNextHandler() )
1238 GetNextHandler()->SetPreviousHandler( GetPreviousHandler() );
1240 SetNextHandler( NULL
);
1241 SetPreviousHandler( NULL
);
1245 void wxFrameLayout::HookUpToFrame()
1247 // unhook us first, we're already hooked up
1251 // put ourselves on top
1253 mpFrame
->PushEventHandler( this );
1256 cbDockPane
* wxFrameLayout::GetBarPane( cbBarInfo
* pBar
)
1259 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1260 if ( mPanes
[i
]->BarPresent( pBar
) )
1266 void wxFrameLayout::CreateCursors()
1269 // FIXME:: The below code somehow doesn't work - cursors remain unchanged
1272 set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
1274 mpHorizCursor = new wxCursor( bits, 32, 16 );
1276 set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
1278 mpVertCursor = new wxCursor( bits, 32, 16 );
1281 // FOR NOW:: use standard ones
1283 mpHorizCursor
= new wxCursor(wxCURSOR_SIZEWE
);
1284 mpVertCursor
= new wxCursor(wxCURSOR_SIZENS
);
1285 mpNormalCursor
= new wxCursor(wxCURSOR_ARROW
);
1286 mpDragCursor
= new wxCursor(wxCURSOR_CROSS
);
1287 mpNECursor
= new wxCursor(wxCURSOR_NO_ENTRY
);
1289 mFloatingPosStep
.x
= 25;
1290 mFloatingPosStep
.y
= 25;
1292 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
1293 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
1296 bool wxFrameLayout::HitTestPane( cbDockPane
* pPane
, int x
, int y
)
1298 return rect_contains_point( pPane
->GetRealRect(), x
, y
);
1301 cbDockPane
* wxFrameLayout::HitTestPanes( const wxRect
& rect
,
1302 cbDockPane
* pCurPane
)
1304 // first, give the privilege to the current pane
1306 if ( pCurPane
&& rect_hits_rect( pCurPane
->GetRealRect(), rect
) )
1311 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1313 if ( pCurPane
!= mPanes
[i
] &&
1314 rect_hits_rect( mPanes
[i
]->GetRealRect(), rect
) )
1322 void wxFrameLayout::ForwardMouseEvent( wxMouseEvent
& event
,
1323 cbDockPane
* pToPane
,
1326 wxPoint
pos( event
.m_x
, event
.m_y
);
1327 pToPane
->FrameToPane( &pos
.x
, &pos
.y
);
1329 if ( eventType
== cbEVT_PL_LEFT_DOWN
)
1331 cbLeftDownEvent
evt( pos
, pToPane
);
1332 FirePluginEvent( evt
);
1334 else if ( eventType
== cbEVT_PL_LEFT_DCLICK
)
1336 cbLeftDClickEvent
evt( pos
, pToPane
);
1337 FirePluginEvent( evt
);
1339 else if ( eventType
== cbEVT_PL_LEFT_UP
)
1341 cbLeftUpEvent
evt( pos
, pToPane
);
1342 FirePluginEvent( evt
);
1344 else if ( eventType
== cbEVT_PL_RIGHT_DOWN
)
1346 cbRightDownEvent
evt( pos
, pToPane
);
1347 FirePluginEvent( evt
);
1349 else if ( eventType
== cbEVT_PL_RIGHT_UP
)
1351 cbRightUpEvent
evt( pos
, pToPane
);
1352 FirePluginEvent( evt
);
1354 else if ( eventType
== cbEVT_PL_MOTION
)
1356 cbMotionEvent
evt( pos
, pToPane
);
1357 FirePluginEvent( evt
);
1361 int avoidCompilerWarning
= 0;
1362 wxASSERT(avoidCompilerWarning
); // DBG::
1364 } // wxFrameLayout::ForwardMouseEvent()
1367 void wxFrameLayout::RouteMouseEvent( wxMouseEvent
& event
, int pluginEvtType
)
1369 if ( mpPaneInFocus
)
1371 ForwardMouseEvent( event
, mpPaneInFocus
, pluginEvtType
);
1375 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1377 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1379 ForwardMouseEvent( event
, mPanes
[i
], pluginEvtType
);
1386 /*** event handlers ***/
1388 void wxFrameLayout::OnRButtonDown( wxMouseEvent
& event
)
1390 RouteMouseEvent( event
, cbEVT_PL_RIGHT_DOWN
);
1393 void wxFrameLayout::OnRButtonUp( wxMouseEvent
& event
)
1395 RouteMouseEvent( event
, cbEVT_PL_RIGHT_UP
);
1398 void wxFrameLayout::OnLButtonDown( wxMouseEvent
& event
)
1400 RouteMouseEvent( event
, cbEVT_PL_LEFT_DOWN
);
1403 void wxFrameLayout::OnLDblClick( wxMouseEvent
& event
)
1405 RouteMouseEvent( event
, cbEVT_PL_LEFT_DCLICK
);
1408 void wxFrameLayout::OnLButtonUp( wxMouseEvent
& event
)
1410 RouteMouseEvent( event
, cbEVT_PL_LEFT_UP
);
1413 void wxFrameLayout::OnMouseMove( wxMouseEvent
& event
)
1415 if ( mpPaneInFocus
)
1417 ForwardMouseEvent( event
, mpPaneInFocus
, cbEVT_PL_MOTION
);
1421 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1423 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1425 if ( mpLRUPane
&& mpLRUPane
!= mPanes
[i
] )
1427 // simulate "mouse-leave" event
1428 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1431 ForwardMouseEvent( event
, mPanes
[i
], cbEVT_PL_MOTION
);
1433 mpLRUPane
= mPanes
[i
];
1442 // simulate "mouse-leave" event
1443 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1448 void wxFrameLayout::OnPaint( wxPaintEvent
& event
)
1450 if ( mRecalcPending
)
1451 RecalcLayout( TRUE
);
1453 wxPaintDC
dc(mpFrame
);
1456 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1458 wxRect
& rect
= mPanes
[i
]->mBoundsInParent
;
1460 dc
.SetClippingRegion( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1462 mPanes
[i
]->PaintPane(dc
);
1464 dc
.DestroyClippingRegion();
1470 void wxFrameLayout::OnEraseBackground( wxEraseEvent
& event
)
1475 void wxFrameLayout::OnIdle( wxIdleEvent
& event
)
1477 wxWindow
* focus
= wxWindow::FindFocus();
1479 if ( !focus
&& mCheckFocusWhenIdle
)
1481 wxMessageBox( "Hi, no more focus in this app!" );
1483 mCheckFocusWhenIdle
= FALSE
;
1484 //ShowFloatedWindows( FALSE );
1487 mCheckFocusWhenIdle
= FALSE
;
1493 void wxFrameLayout::OnKillFocus( wxFocusEvent
& event
)
1495 //wxMessageBox( "wxFrameLayoutGot Kill Focus!" );
1496 //ShowFloatedWindows( FALSE );
1499 void wxFrameLayout::OnSetFocus( wxFocusEvent
& event
)
1501 //ShowFloatedWindows( TRUE );
1504 void wxFrameLayout::OnActivate( wxActivateEvent
& event
)
1507 if ( event
.GetActive() == FALSE
)
1509 wxWindow
* focus
= wxWindow::FindFocus();
1511 if ( !focus
|| focus
== &GetParentFrame() )
1513 mCheckFocusWhenIdle
= TRUE
;
1517 wxMessageBox("Deactivated!" );
1524 void wxFrameLayout::GetPaneProperties( cbCommonPaneProperties
& props
, int alignment
)
1526 props
= mPanes
[alignment
]->mProps
;
1529 void wxFrameLayout::SetPaneProperties( const cbCommonPaneProperties
& props
, int paneMask
)
1532 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1534 if ( mPanes
[i
]->MatchesMask( paneMask
) )
1535 mPanes
[i
]->mProps
= props
;
1539 void wxFrameLayout::SetMargins( int top
, int bottom
, int left
, int right
,
1543 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1545 cbDockPane
& pane
= *mPanes
[i
];
1547 if ( pane
.MatchesMask( paneMask
) )
1549 pane
.mTopMargin
= top
;
1550 pane
.mBottomMargin
= bottom
;
1551 pane
.mLeftMargin
= left
;
1552 pane
.mRightMargin
= right
;
1557 void wxFrameLayout::SetPaneBackground( const wxColour
& colour
)
1559 mBorderPen
.SetColour( colour
);
1562 void wxFrameLayout::RefreshNow( bool recalcLayout
)
1565 RecalcLayout( TRUE
);
1571 /*** plugin-related methods ***/
1573 void wxFrameLayout::FirePluginEvent( cbPluginEvent
& event
)
1575 // check state of input capture, before processing the event
1577 if ( mpCaputesInput
)
1579 bool isInputEvt
= TRUE
;
1580 #if wxCHECK_VERSION(2,3,0)
1581 if ( event
.m_eventType
!= cbEVT_PL_LEFT_DOWN
&&
1582 event
.m_eventType
!= cbEVT_PL_LEFT_UP
&&
1583 event
.m_eventType
!= cbEVT_PL_RIGHT_DOWN
&&
1584 event
.m_eventType
!= cbEVT_PL_RIGHT_UP
&&
1585 event
.m_eventType
!= cbEVT_PL_MOTION
)
1588 switch ( event
.m_eventType
)
1590 case cbEVT_PL_LEFT_DOWN
: break;
1591 case cbEVT_PL_LEFT_UP
: break;
1592 case cbEVT_PL_RIGHT_DOWN
: break;
1593 case cbEVT_PL_RIGHT_UP
: break;
1594 case cbEVT_PL_MOTION
: break;
1596 default : isInputEvt
= FALSE
; break;
1598 #endif // #if wxCHECK_VERSION(2,3,0)
1602 mpCaputesInput
->ProcessEvent( event
);
1607 GetTopPlugin().ProcessEvent( event
);
1610 void wxFrameLayout::CaptureEventsForPlugin ( cbPluginBase
* pPlugin
)
1612 // cannot capture events for more than one plugin at a time
1613 wxASSERT( mpCaputesInput
== NULL
);
1615 mpCaputesInput
= pPlugin
;
1619 void wxFrameLayout::ReleaseEventsFromPlugin( cbPluginBase
* pPlugin
)
1621 // events should be captured first
1622 wxASSERT( mpCaputesInput
!= NULL
);
1624 mpCaputesInput
= NULL
;
1627 void wxFrameLayout::CaptureEventsForPane( cbDockPane
* toPane
)
1629 // cannot capture events twice (without releasing)
1630 wxASSERT( mpPaneInFocus
== NULL
);
1632 mpFrame
->CaptureMouse();
1634 mpPaneInFocus
= toPane
;
1637 void wxFrameLayout::ReleaseEventsFromPane( cbDockPane
* fromPane
)
1639 // cannot release events without capturing them
1640 wxASSERT( mpPaneInFocus
!= NULL
);
1642 mpFrame
->ReleaseMouse();
1644 mpPaneInFocus
= NULL
;
1647 cbPluginBase
& wxFrameLayout::GetTopPlugin()
1651 PushDefaultPlugins(); // automatic configuration
1653 return *mpTopPlugin
;
1656 void wxFrameLayout::SetTopPlugin( cbPluginBase
* pPlugin
)
1658 mpTopPlugin
= pPlugin
;
1661 bool wxFrameLayout::HasTopPlugin()
1663 return ( mpTopPlugin
!= NULL
);
1666 void wxFrameLayout::PushPlugin( cbPluginBase
* pPlugin
)
1670 mpTopPlugin
= pPlugin
;
1673 pPlugin
->SetNextHandler( mpTopPlugin
);
1675 mpTopPlugin
->SetPreviousHandler( pPlugin
);
1677 mpTopPlugin
= pPlugin
;
1680 mpTopPlugin
->OnInitPlugin(); // notification
1683 void wxFrameLayout::PopPlugin()
1685 wxASSERT( mpTopPlugin
); // DBG:: at least one plugin should be present
1687 cbPluginBase
* pPopped
= mpTopPlugin
;
1689 mpTopPlugin
= (cbPluginBase
*)mpTopPlugin
->GetNextHandler();
1694 void wxFrameLayout::PopAllPlugins()
1696 while( mpTopPlugin
) PopPlugin();
1699 void wxFrameLayout::PushDefaultPlugins()
1701 // FIXME:: to much of the stuff for the default...
1703 AddPlugin( CLASSINFO( cbRowLayoutPlugin
) );
1704 AddPlugin( CLASSINFO( cbBarDragPlugin
) );
1705 AddPlugin( CLASSINFO( cbPaneDrawPlugin
) );
1708 void wxFrameLayout::AddPlugin( wxClassInfo
* pPlInfo
, int paneMask
)
1710 if ( FindPlugin ( pPlInfo
) ) return; // same type of plugin cannot be added twice
1712 cbPluginBase
* pObj
= (cbPluginBase
*)pPlInfo
->CreateObject();
1714 wxASSERT(pObj
); // DBG:: plugin's class should be dynamic
1716 pObj
->mPaneMask
= paneMask
;
1717 pObj
->mpLayout
= this;
1722 void wxFrameLayout::AddPluginBefore( wxClassInfo
* pNextPlInfo
, wxClassInfo
* pPlInfo
,
1725 wxASSERT( pNextPlInfo
!= pPlInfo
); // DBG:: no sense
1727 cbPluginBase
* pNextPl
= FindPlugin( pNextPlInfo
);
1731 AddPlugin( pPlInfo
, paneMask
);
1736 // remove existing one if present
1738 cbPluginBase
* pExistingPl
= FindPlugin( pPlInfo
);
1740 if ( pExistingPl
) RemovePlugin( pPlInfo
);
1742 // create an instance
1744 cbPluginBase
* pNewPl
= (cbPluginBase
*)pPlInfo
->CreateObject();
1746 wxASSERT(pNewPl
); // DBG:: plugin's class should be dynamic
1748 // insert it to the chain
1750 if ( pNextPl
->GetPreviousHandler() )
1752 pNextPl
->GetPreviousHandler()->SetNextHandler( pNewPl
);
1754 mpTopPlugin
= pNewPl
;
1756 pNewPl
->SetNextHandler( pNextPl
);
1758 pNewPl
->SetPreviousHandler( pNextPl
->GetPreviousHandler() );
1760 pNextPl
->SetPreviousHandler( pNewPl
);
1764 pNewPl
->mPaneMask
= paneMask
;
1765 pNewPl
->mpLayout
= this;
1767 pNewPl
->OnInitPlugin();
1770 void wxFrameLayout::RemovePlugin( wxClassInfo
* pPlInfo
)
1772 cbPluginBase
* pPlugin
= FindPlugin( pPlInfo
);
1774 if ( !pPlugin
) return; // it's OK to remove not-existing plugin ;-)
1776 if ( pPlugin
->GetPreviousHandler() == NULL
)
1778 mpTopPlugin
= (cbPluginBase
*)pPlugin
->GetNextHandler();
1783 cbPluginBase
* wxFrameLayout::FindPlugin( wxClassInfo
* pPlInfo
)
1785 cbPluginBase
*pCur
= mpTopPlugin
;
1789 // NOTE:: it might appear useful matching plugin
1790 // classes "polymorphically":
1792 if ( pCur
->GetClassInfo()->IsKindOf( pPlInfo
) )
1796 pCur
= (cbPluginBase
*)pCur
->GetNextHandler();
1802 /***** Implementation for class cbUpdateMgrData *****/
1804 IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData
, wxObject
)
1806 cbUpdateMgrData::cbUpdateMgrData()
1808 : mPrevBounds( -1,-1,0,0 ),
1809 mIsDirty( TRUE
) // inidicate initial change
1812 void cbUpdateMgrData::StoreItemState( const wxRect
& boundsInParent
)
1814 mPrevBounds
= boundsInParent
;
1817 void cbUpdateMgrData::SetDirty( bool isDirty
)
1822 void cbUpdateMgrData::SetCustomData( wxObject
* pCustomData
)
1824 mpCustomData
= pCustomData
;
1827 /***** Implementation for class cbDockPane *****/
1829 void wxBarIterator::Reset()
1831 mpRow
= ( mpRows
->Count() ) ? (*mpRows
)[0] : NULL
;
1835 wxBarIterator::wxBarIterator( RowArrayT
& rows
)
1844 bool wxBarIterator::Next()
1849 mpBar
= mpBar
->mpNext
;
1852 if ( mpRow
->mBars
.GetCount() == 0 )
1857 mpBar
= mpRow
->mBars
[0];
1862 // skip to the next row
1864 mpRow
= mpRow
->mpNext
;
1868 mpBar
= mpRow
->mBars
[0];
1879 cbBarInfo
& wxBarIterator::BarInfo()
1884 cbRowInfo
& wxBarIterator::RowInfo()
1889 /***** Implementation for class cbBarDimHandlerBase *****/
1891 IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase
, wxObject
)
1893 cbBarDimHandlerBase::cbBarDimHandlerBase()
1897 void cbBarDimHandlerBase::AddRef()
1902 void cbBarDimHandlerBase::RemoveRef()
1904 if ( --mRefCount
<= 0 ) delete this;
1907 /***** Implementation for class cbDimInfo *****/
1909 IMPLEMENT_DYNAMIC_CLASS( cbDimInfo
, wxObject
)
1911 cbDimInfo::cbDimInfo()
1920 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1925 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1929 cbDimInfo::cbDimInfo( cbBarDimHandlerBase
* pDimHandler
,
1934 mIsFixed ( isFixed
),
1936 mpHandler( pDimHandler
)
1940 // int vtad = *((int*)mpHandler);
1941 mpHandler
->AddRef();
1945 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1950 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1954 cbDimInfo::cbDimInfo( int dh_x
, int dh_y
,
1962 cbBarDimHandlerBase
* pDimHandler
1964 : mVertGap ( vertGap
),
1965 mHorizGap ( horizGap
),
1966 mIsFixed ( isFixed
),
1967 mpHandler( pDimHandler
)
1971 // int vtad = *((int*)mpHandler);
1972 mpHandler
->AddRef();
1975 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= dh_x
;
1976 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= dh_y
;
1977 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= dv_x
;
1978 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= dv_y
;
1979 mSizes
[wxCBAR_FLOATING
].x
= f_x
;
1980 mSizes
[wxCBAR_FLOATING
].y
= f_y
;
1983 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1984 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1987 cbDimInfo::cbDimInfo( int x
, int y
,
1988 bool isFixed
, int gap
,
1989 cbBarDimHandlerBase
* pDimHandler
)
1992 mIsFixed ( isFixed
),
1993 mpHandler( pDimHandler
)
1997 // int vtad = *((int*)mpHandler);
1998 mpHandler
->AddRef();
2001 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= x
;
2002 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= y
;
2003 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= x
;
2004 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= y
;
2005 mSizes
[wxCBAR_FLOATING
].x
= x
;
2006 mSizes
[wxCBAR_FLOATING
].y
= y
;
2009 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2010 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
2013 cbDimInfo::~cbDimInfo()
2017 mpHandler
->RemoveRef();
2020 const cbDimInfo
& cbDimInfo::operator=( const cbDimInfo
& other
)
2022 if ( this == &other
)
2026 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2027 mSizes
[i
] = other
.mSizes
[i
];
2029 mIsFixed
= other
.mIsFixed
;
2030 mpHandler
= other
.mpHandler
;
2032 mVertGap
= other
.mVertGap
;
2033 mHorizGap
= other
.mHorizGap
;
2037 mpHandler
->AddRef();
2042 /***** Implementation for structure cbCommonPaneProperties *****/
2044 IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties
, wxObject
)
2046 cbCommonPaneProperties::cbCommonPaneProperties(void)
2048 : mRealTimeUpdatesOn ( TRUE
),
2049 mOutOfPaneDragOn ( TRUE
),
2050 mExactDockPredictionOn( FALSE
),
2051 mNonDestructFrictionOn( FALSE
),
2052 mShow3DPaneBorderOn ( TRUE
),
2053 mBarFloatingOn ( FALSE
),
2054 mRowProportionsOn ( FALSE
),
2055 mColProportionsOn ( TRUE
),
2056 mBarCollapseIconsOn ( FALSE
),
2057 mBarDragHintsOn ( FALSE
),
2059 mMinCBarDim( 16, 16 ),
2060 mResizeHandleSize( 4 )
2063 cbCommonPaneProperties::cbCommonPaneProperties(const cbCommonPaneProperties
& props
)
2066 mRealTimeUpdatesOn (props
.mRealTimeUpdatesOn
),
2067 mOutOfPaneDragOn (props
.mOutOfPaneDragOn
),
2068 mExactDockPredictionOn(props
.mExactDockPredictionOn
),
2069 mNonDestructFrictionOn(props
.mNonDestructFrictionOn
),
2070 mShow3DPaneBorderOn (props
.mShow3DPaneBorderOn
),
2071 mBarFloatingOn (props
.mBarFloatingOn
),
2072 mRowProportionsOn (props
.mRowProportionsOn
),
2073 mColProportionsOn (props
.mColProportionsOn
),
2074 mBarCollapseIconsOn (props
.mBarCollapseIconsOn
),
2075 mBarDragHintsOn (props
.mBarDragHintsOn
),
2077 mMinCBarDim(props
.mMinCBarDim
),
2078 mResizeHandleSize(props
.mResizeHandleSize
)
2081 cbCommonPaneProperties
& cbCommonPaneProperties::operator=(const cbCommonPaneProperties
& props
)
2087 /***** Implementation for class cbRowInfo *****/
2089 IMPLEMENT_DYNAMIC_CLASS( cbRowInfo
, wxObject
)
2091 cbRowInfo::cbRowInfo(void)
2093 : mNotFixedBarsCnt( FALSE
),
2096 mpExpandedBar ( NULL
)
2099 cbRowInfo::~cbRowInfo()
2101 // nothing! all bars are removed using global bar
2102 // list in wxFrameLayout class
2105 /***** Implementation for class cbBarInfo *****/
2107 IMPLEMENT_DYNAMIC_CLASS( cbBarInfo
, wxObject
)
2109 cbBarInfo::cbBarInfo(void)
2117 cbBarInfo::~cbBarInfo()
2122 /***** Implementation for class cbDockPane *****/
2124 IMPLEMENT_DYNAMIC_CLASS( cbDockPane
, wxObject
)
2126 // FIXME:: how to eliminate these cut&pasted constructors?
2128 cbDockPane::cbDockPane(void)
2129 : mLeftMargin ( 1 ),
2133 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2134 // since the real dimensions of the pane may not
2135 // be known, while inserting bars initially
2136 mPaneHeight( 32768 ),
2142 cbDockPane::cbDockPane( int alignment
, wxFrameLayout
* pPanel
)
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 ),
2152 mAlignment ( alignment
),
2153 mpLayout ( pPanel
),
2157 cbDockPane::~cbDockPane()
2160 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2163 mRowShapeData
.DeleteContents( TRUE
);
2165 // NOTE:: control bar infromation structures are cleaned-up
2166 // in wxFrameLayout's destructor, using global control-bar list
2169 void cbDockPane::SetMargins( int top
, int bottom
, int left
, int right
)
2172 mBottomMargin
= bottom
;
2174 mRightMargin
= right
;
2177 /*** helpers of cbDockPane ***/
2179 void cbDockPane::PaintBarDecorations( cbBarInfo
* pBar
, wxDC
& dc
)
2181 cbDrawBarDecorEvent
evt( pBar
, dc
, this );
2183 mpLayout
->FirePluginEvent( evt
);
2186 void cbDockPane::PaintBarHandles( cbBarInfo
* pBar
, wxDC
& dc
)
2188 cbDrawBarHandlesEvent
evt( pBar
, dc
, this );
2190 mpLayout
->FirePluginEvent( evt
);
2193 void cbDockPane::PaintBar( cbBarInfo
* pBar
, wxDC
& dc
)
2195 PaintBarDecorations( pBar
, dc
);
2196 PaintBarHandles( pBar
, dc
);
2199 void cbDockPane::PaintRowHandles( cbRowInfo
* pRow
, wxDC
& dc
)
2201 cbDrawRowHandlesEvent
evt( pRow
, dc
, this );
2203 mpLayout
->FirePluginEvent( evt
);
2205 cbDrawRowDecorEvent
evt1( pRow
, dc
, this );
2207 mpLayout
->FirePluginEvent( evt1
);
2210 void cbDockPane::PaintRowBackground ( cbRowInfo
* pRow
, wxDC
& dc
)
2212 cbDrawRowBkGroundEvent
evt( pRow
, dc
, this );
2214 mpLayout
->FirePluginEvent( evt
);
2217 void cbDockPane::PaintRowDecorations( cbRowInfo
* pRow
, wxDC
& dc
)
2221 // decorations first
2222 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2224 PaintBarDecorations( pRow
->mBars
[i
], dc
);
2226 // then handles if present
2227 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2229 PaintBarHandles( pRow
->mBars
[i
], dc
);
2232 void cbDockPane::PaintRow( cbRowInfo
* pRow
, wxDC
& dc
)
2234 PaintRowBackground ( pRow
, dc
);
2235 PaintRowDecorations( pRow
, dc
);
2236 PaintRowHandles ( pRow
, dc
);
2239 void cbDockPane::PaintPaneBackground( wxDC
& dc
)
2241 cbDrawPaneBkGroundEvent
evt( dc
, this );
2243 mpLayout
->FirePluginEvent( evt
);
2246 void cbDockPane::PaintPaneDecorations( wxDC
& dc
)
2248 cbDrawPaneDecorEvent
evt( dc
, this );
2250 mpLayout
->FirePluginEvent( evt
);
2253 void cbDockPane::PaintPane( wxDC
& dc
)
2255 PaintPaneBackground( dc
);
2259 // first decorations
2260 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2262 PaintRowBackground( mRows
[i
], dc
);
2263 PaintRowDecorations( mRows
[i
], dc
);
2267 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2268 PaintRowHandles( mRows
[i
], dc
);
2271 PaintPaneDecorations( dc
);
2274 void cbDockPane::SizeBar( cbBarInfo
* pBar
)
2276 cbSizeBarWndEvent
evt( pBar
, this );
2278 mpLayout
->FirePluginEvent( evt
);
2282 void cbDockPane::SizeRowObjects( cbRowInfo
* pRow
)
2285 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2286 SizeBar( pRow
->mBars
[i
] );
2289 void cbDockPane::SizePaneObjects()
2292 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2293 SizeRowObjects( mRows
[i
] );
2296 wxDC
* cbDockPane::StartDrawInArea( const wxRect
& area
)
2300 cbStartDrawInAreaEvent
evt( area
, &pDc
, this );
2302 mpLayout
->FirePluginEvent( evt
);
2307 void cbDockPane::FinishDrawInArea( const wxRect
& area
)
2309 cbFinishDrawInAreaEvent
evt( area
, this );
2311 mpLayout
->FirePluginEvent( evt
);
2314 bool cbDockPane::IsFixedSize( cbBarInfo
* pInfo
)
2316 return ( pInfo
->mDimInfo
.mIsFixed
);
2319 int cbDockPane::GetNotFixedBarsCount( cbRowInfo
* pRow
)
2324 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2326 if ( !pRow
->mBars
[i
]->IsFixed() )
2333 void cbDockPane::RemoveBar( cbBarInfo
* pBar
)
2335 bool needsRestoring
= mProps
.mNonDestructFrictionOn
&&
2336 mpStoredRow
== pBar
->mpRow
;
2338 cbRemoveBarEvent
evt( pBar
, this );
2340 mpLayout
->FirePluginEvent( evt
);
2342 if ( needsRestoring
)
2344 SetRowShapeData( mpStoredRow
, &mRowShapeData
);
2350 void cbDockPane::SyncRowFlags( cbRowInfo
* pRow
)
2352 // setup mHasOnlyFixedBars flag for the row information
2353 pRow
->mHasOnlyFixedBars
= TRUE
;
2355 pRow
->mNotFixedBarsCnt
= 0;
2358 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2360 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2364 if ( !bar
.IsFixed() )
2366 pRow
->mHasOnlyFixedBars
= FALSE
;
2367 ++pRow
->mNotFixedBarsCnt
;
2372 void cbDockPane::FrameToPane( int* x
, int* y
)
2377 if ( mAlignment
== FL_ALIGN_TOP
||
2378 mAlignment
== FL_ALIGN_BOTTOM
2381 *x
-= mBoundsInParent
.x
;
2382 *y
-= mBoundsInParent
.y
;
2386 int rx
= *x
, ry
= *y
;
2388 *x
= ry
- mBoundsInParent
.y
;
2390 *y
= rx
- mBoundsInParent
.x
;
2394 void cbDockPane::PaneToFrame( int* x
, int* y
)
2396 if ( mAlignment
== FL_ALIGN_TOP
||
2397 mAlignment
== FL_ALIGN_BOTTOM
2400 *x
+= mBoundsInParent
.x
;
2401 *y
+= mBoundsInParent
.y
;
2405 int rx
= *x
, ry
= *y
;
2407 *x
= ry
+ mBoundsInParent
.x
;
2409 *y
= mBoundsInParent
.y
+ rx
;
2416 void cbDockPane::FrameToPane( wxRect
* pRect
)
2418 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2419 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2420 pRect
->y
+ pRect
->height
);
2422 FrameToPane( &upperLeft
.x
, &upperLeft
.y
);
2423 FrameToPane( &lowerRight
.x
, &lowerRight
.y
);
2425 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2426 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2428 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2429 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2432 void cbDockPane::PaneToFrame( wxRect
* pRect
)
2434 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2435 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2436 pRect
->y
+ pRect
->height
);
2438 PaneToFrame( &upperLeft
.x
, &upperLeft
.y
);
2439 PaneToFrame( &lowerRight
.x
, &lowerRight
.y
);
2441 //wxRect newRect = wxRect( upperLeft, lowerRight );
2443 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2444 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2446 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2447 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2450 int cbDockPane::GetRowAt( int paneY
)
2459 for ( ; i
!= mRows
.Count(); ++i
)
2461 int rowHeight
= mRows
[i
]->mRowHeight
;
2463 int third
= rowHeight
/3;
2465 if ( paneY
>= curY
&& paneY
< curY
+ third
)
2468 if ( paneY
>= curY
+ third
&& paneY
< curY
+ rowHeight
- third
)
2477 int cbDockPane::GetRowAt( int upperY
, int lowerY
)
2481 int range = lowerY - upperY;
2482 int oneThird = range / 3;
2484 wxNode* pRow = mRows.First();
2488 if ( lowerY <= 0 ) return -1;
2492 int rowHeight = GetRowHeight( (wxList*)pRow->Data() );
2494 if ( upperY >= curY &&
2495 lowerY < curY ) return row;
2497 if ( upperY <= curY &&
2499 curY - upperY >= oneThird ) return row-1;
2501 if ( ( upperY < curY + rowHeight &&
2502 lowerY >= curY + rowHeight &&
2503 curY + rowHeight - lowerY >= oneThird )
2507 if ( lowerY <= curY + rowHeight ) return row;
2511 pRow = pRow->Next();
2515 int mid
= upperY
+ (lowerY
- upperY
)/2;
2523 for ( ; i
!= mRows
.Count(); ++i
)
2525 int rowHeight
= mRows
[i
]->mRowHeight
;
2527 if ( mid
>= curY
&& mid
< curY
+ rowHeight
) return i
;
2535 int cbDockPane::GetRowY( cbRowInfo
* pRow
)
2540 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2542 if ( mRows
[i
] == pRow
)
2545 curY
+= mRows
[i
]->mRowHeight
;
2551 bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo
* pRow
)
2553 while ( pRow
->mpPrev
)
2555 pRow
= pRow
->mpPrev
;
2557 if ( pRow
->mHasOnlyFixedBars
)
2565 bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo
* pRow
)
2567 while( pRow
->mpNext
)
2569 pRow
= pRow
->mpNext
;
2571 if ( pRow
->mHasOnlyFixedBars
)
2579 bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo
* pBar
)
2581 while( pBar
->mpPrev
)
2583 pBar
= pBar
->mpPrev
;
2585 if ( pBar
->IsFixed() )
2593 bool cbDockPane::HasNotFixedBarsRight( cbBarInfo
* pBar
)
2595 while( pBar
->mpNext
)
2597 pBar
= pBar
->mpNext
;
2599 if ( pBar
->IsFixed() )
2607 void cbDockPane::CalcLengthRatios( cbRowInfo
* pInRow
)
2613 // calc current-maximal-total-length of all maximized bars
2615 for ( i
= 0; i
!= pInRow
->mBars
.GetCount(); ++i
)
2617 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2619 if ( !bar
.IsFixed() )
2620 totalWidth
+= bar
.mBounds
.width
;
2623 // set up percentages of occupied space for each maximized bar
2625 for ( i
= 0; i
!= pInRow
->mBars
.Count(); ++i
)
2627 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2629 if ( !bar
.IsFixed() )
2630 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalWidth
);
2634 void cbDockPane::RecalcRowLayout( cbRowInfo
* pRow
)
2636 cbLayoutRowEvent
evt( pRow
, this );
2638 mpLayout
->FirePluginEvent( evt
);
2641 void cbDockPane::ExpandBar( cbBarInfo
* pBar
)
2643 mpLayout
->GetUpdatesManager().OnStartChanges();
2645 if ( !pBar
->mpRow
->mpExpandedBar
)
2647 // save ratios only when there arent any bars expanded yet
2649 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2652 ratios
.Alloc( pBar
->mpRow
->mNotFixedBarsCnt
);
2654 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2658 if ( !pCur
->IsFixed() )
2661 ratios
[ ratios
.GetCount() - 1 ] = pCur
->mLenRatio
;
2664 pCur
= pCur
->mpNext
;
2668 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2672 pCur
->mLenRatio
= 0.0; // minimize the rest
2674 pCur
= pCur
->mpNext
;
2677 pBar
->mLenRatio
= 1.0; // 100%
2678 pBar
->mBounds
.width
= 0;
2680 pBar
->mpRow
->mpExpandedBar
= pBar
;
2682 mpLayout
->RecalcLayout( FALSE
);
2684 mpLayout
->GetUpdatesManager().OnFinishChanges();
2685 mpLayout
->GetUpdatesManager().UpdateNow();
2688 void cbDockPane::ContractBar( cbBarInfo
* pBar
)
2690 mpLayout
->GetUpdatesManager().OnStartChanges();
2692 // FIXME: What's the purpose of this???
2693 // double ratio = 1.0/ double( pBar->mpRow->mNotFixedBarsCnt );
2695 // restore ratios which were present before expansion
2697 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2699 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2705 if ( !pCur
->IsFixed() )
2707 pCur
->mLenRatio
= ratios
[i
];
2711 pCur
= pCur
->mpNext
;
2717 pBar
->mpRow
->mpExpandedBar
= NULL
;
2719 mpLayout
->RecalcLayout( FALSE
);
2721 mpLayout
->GetUpdatesManager().OnFinishChanges();
2722 mpLayout
->GetUpdatesManager().UpdateNow();
2725 void cbDockPane::InitLinksForRow( cbRowInfo
* pRow
)
2728 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2730 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2735 bar
.mpPrev
= pRow
->mBars
[i
-1];
2737 if ( i
== pRow
->mBars
.Count() - 1 )
2740 bar
.mpNext
= pRow
->mBars
[i
+1];
2744 void cbDockPane::InitLinksForRows()
2747 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2749 cbRowInfo
& row
= *mRows
[i
];
2754 row
.mpPrev
= mRows
[i
-1];
2756 if ( i
== mRows
.Count() - 1 )
2759 row
.mpNext
= mRows
[i
+1];
2763 void cbDockPane::DoInsertBar( cbBarInfo
* pBar
, int rowNo
)
2765 cbRowInfo
* pRow
= NULL
;
2767 if ( rowNo
== -1 || rowNo
>= (int)mRows
.Count() )
2769 pRow
= new cbRowInfo();
2771 if ( rowNo
== -1 && mRows
.Count() )
2773 mRows
.Insert( pRow
, 0 );
2781 pRow
= mRows
[rowNo
];
2783 if ( mProps
.mNonDestructFrictionOn
== TRUE
)
2785 // store original shape of the row (before the bar is inserted)
2789 GetRowShapeData( mpStoredRow
, &mRowShapeData
);
2793 if ( pRow
->mBars
.Count() )
2795 pRow
->mpExpandedBar
= NULL
;
2797 cbInsertBarEvent
insEvt( pBar
, pRow
, this );
2799 mpLayout
->FirePluginEvent( insEvt
);
2801 mpLayout
->GetUpdatesManager().OnRowWillChange( pRow
, this );
2804 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
, const wxRect
& atRect
)
2806 wxRect rect
= atRect
;
2807 FrameToPane( &rect
);
2809 pBarInfo
->mBounds
.x
= rect
.x
;
2810 pBarInfo
->mBounds
.width
= rect
.width
;
2811 pBarInfo
->mBounds
.height
= rect
.height
;
2813 int row
= GetRowAt( rect
.y
, rect
.y
+ rect
.height
);
2815 DoInsertBar( pBarInfo
, row
);
2818 void cbDockPane::InsertBar( cbBarInfo
* pBar
, cbRowInfo
* pIntoRow
)
2820 cbInsertBarEvent
insEvt( pBar
, pIntoRow
, this );
2822 mpLayout
->FirePluginEvent( insEvt
);
2824 mpLayout
->GetUpdatesManager().OnRowWillChange( pIntoRow
, this );
2827 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
)
2829 // set transient properties
2831 pBarInfo
->mpRow
= NULL
;
2832 pBarInfo
->mHasLeftHandle
= FALSE
;
2833 pBarInfo
->mHasRightHandle
= FALSE
;
2834 pBarInfo
->mLenRatio
= 0.0;
2836 // set preferred bar dimensions, according to the state in which
2837 // the bar is being inserted
2839 pBarInfo
->mBounds
.width
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].x
;
2840 pBarInfo
->mBounds
.height
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].y
;
2842 DoInsertBar( pBarInfo
, pBarInfo
->mRowNo
);
2845 void cbDockPane::RemoveRow( cbRowInfo
* pRow
)
2848 // first, hide all bar-windows in the removed row
2849 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2851 if ( pRow
->mBars
[i
]->mpBarWnd
)
2852 pRow
->mBars
[i
]->mpBarWnd
->Show( FALSE
);
2855 mRows
.Remove( pRow
);
2857 pRow
->mUMgrData
.SetDirty(TRUE
);
2860 void cbDockPane::InsertRow( cbRowInfo
* pRow
, cbRowInfo
* pBeforeRow
)
2866 mRows
.Insert( pRow
, mRows
.Index( pBeforeRow
) );
2870 pRow
->mUMgrData
.SetDirty(TRUE
);
2873 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2874 pRow
->mBars
[i
]->mUMgrData
.SetDirty( TRUE
);
2876 SyncRowFlags( pRow
);
2879 void cbDockPane::SetPaneWidth(int width
)
2881 if ( IsHorizontal() )
2882 mPaneWidth
= width
- mLeftMargin
- mRightMargin
;
2884 mPaneWidth
= width
- mTopMargin
- mBottomMargin
;
2888 void cbDockPane::SetBoundsInParent( const wxRect
& rect
)
2890 mBoundsInParent
= rect
;
2892 // set pane dimensions in local coordinates
2894 if ( IsHorizontal() )
2896 mPaneWidth
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2897 mPaneHeight
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2901 mPaneWidth
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2902 mPaneHeight
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2905 // convert bounding rectangles of all pane items into parent frame's coordinates
2907 wxBarIterator
i( mRows
);
2909 wxRect noMarginsRect
= mBoundsInParent
;
2911 noMarginsRect
.x
+= mLeftMargin
;
2912 noMarginsRect
.y
+= mTopMargin
;
2913 noMarginsRect
.width
-= ( mLeftMargin
+ mRightMargin
);
2914 noMarginsRect
.height
-= ( mTopMargin
+ mBottomMargin
);
2916 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2918 if ( mBoundsInParent
.width
< 0 ||
2919 mBoundsInParent
.height
< 0 )
2921 hide_rect( mBoundsInParent
);
2923 if ( noMarginsRect
.width
< 0 ||
2924 noMarginsRect
.height
< 0 )
2926 hide_rect( noMarginsRect
);
2928 // calculate mBoundsInParent for each item in the pane
2932 cbBarInfo
& bar
= i
.BarInfo();
2934 cbRowInfo
* pRowInfo
= bar
.mpRow
;
2936 // set up row info, if this is first bar in the row
2938 if ( pRowInfo
&& bar
.mpPrev
== NULL
)
2940 pRowInfo
->mBoundsInParent
.y
= pRowInfo
->mRowY
;
2941 pRowInfo
->mBoundsInParent
.x
= 0;
2942 pRowInfo
->mBoundsInParent
.width
= mPaneWidth
;
2943 pRowInfo
->mBoundsInParent
.height
= pRowInfo
->mRowHeight
;
2945 PaneToFrame( &pRowInfo
->mBoundsInParent
);
2947 clip_rect_against_rect( pRowInfo
->mBoundsInParent
, noMarginsRect
);
2950 wxRect bounds
= bar
.mBounds
;
2952 // exclude dimensions of handles, when calculating
2953 // bar's bounds in parent (i.e. "visual bounds")
2955 if ( bar
.mHasLeftHandle
)
2957 bounds
.x
+= mProps
.mResizeHandleSize
;
2958 bounds
.width
-= mProps
.mResizeHandleSize
;
2961 if ( bar
.mHasRightHandle
)
2963 bounds
.width
-= mProps
.mResizeHandleSize
;
2965 PaneToFrame( &bounds
);
2967 clip_rect_against_rect( bounds
, noMarginsRect
);
2969 bar
.mBoundsInParent
= bounds
;
2973 bool cbDockPane::BarPresent( cbBarInfo
* pBar
)
2975 wxBarIterator
iter( mRows
);
2977 while( iter
.Next() )
2979 if ( &iter
.BarInfo() == pBar
) return TRUE
;
2984 cbRowInfo
* cbDockPane::GetRow( int row
)
2986 if ( row
>= (int)mRows
.Count() ) return NULL
;
2988 return mRows
[ row
];
2991 int cbDockPane::GetRowIndex( cbRowInfo
* pRow
)
2994 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2996 if ( mRows
[i
] == pRow
)
3000 wxFAIL_MSG("Row must be present to call cbDockPane::GetRowIndex()");
3005 int cbDockPane::GetPaneHeight()
3007 // first, recalculate row heights and the Y-positions
3009 cbLayoutRowsEvent
evt( this );
3010 mpLayout
->FirePluginEvent( evt
);
3014 if ( IsHorizontal() )
3016 height
+= mTopMargin
+ mBottomMargin
;
3018 height
+= mLeftMargin
+ mRightMargin
;
3020 int count
= mRows
.Count();
3024 height
+= mRows
[count
-1]->mRowY
+ mRows
[count
-1]->mRowHeight
;
3029 int cbDockPane::GetAlignment()
3034 bool cbDockPane::MatchesMask( int paneMask
)
3038 // FIXME:: use array instead of switch()
3042 case FL_ALIGN_TOP
: thisMask
= FL_ALIGN_TOP_PANE
; break;
3043 case FL_ALIGN_BOTTOM
: thisMask
= FL_ALIGN_BOTTOM_PANE
;break;
3044 case FL_ALIGN_LEFT
: thisMask
= FL_ALIGN_LEFT_PANE
; break;
3045 case FL_ALIGN_RIGHT
: thisMask
= FL_ALIGN_RIGHT_PANE
; break;
3048 wxFAIL_MSG("Bad FL alignment type detected in cbDockPane::MatchesMask()");
3051 return ( thisMask
& paneMask
) != 0;
3054 void cbDockPane::RecalcLayout()
3056 // first, reposition rows and items vertically
3058 cbLayoutRowsEvent
evt( this );
3059 mpLayout
->FirePluginEvent( evt
);
3061 // then horizontally in each row
3064 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3065 RecalcRowLayout( mRows
[i
] );
3068 int cbDockPane::GetDockingState()
3070 if ( mAlignment
== FL_ALIGN_TOP
||
3071 mAlignment
== FL_ALIGN_BOTTOM
)
3073 return wxCBAR_DOCKED_HORIZONTALLY
;
3076 return wxCBAR_DOCKED_VERTICALLY
;
3079 inline bool cbDockPane::HasPoint( const wxPoint
& pos
, int x
, int y
,
3080 int width
, int height
)
3082 return ( pos
.x
>= x
&&
3084 pos
.x
< x
+ width
&&
3085 pos
.y
< y
+ height
);
3088 int cbDockPane::HitTestPaneItems( const wxPoint
& pos
,
3097 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3099 cbRowInfo
& row
= *mRows
[i
];
3103 // hit-test handles of the row, if present
3105 if ( row
.mHasUpperHandle
)
3107 if ( HasPoint( pos
, 0, row
.mRowY
,
3108 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3110 return CB_UPPER_ROW_HANDLE_HITTED
;
3113 if ( row
.mHasLowerHandle
)
3115 if ( HasPoint( pos
, 0, row
.mRowY
+ row
.mRowHeight
- mProps
.mResizeHandleSize
,
3116 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3118 return CB_LOWER_ROW_HANDLE_HITTED
;
3121 // hit-test bar handles and bar content
3124 for ( k
= 0; k
!= row
.mBars
.Count(); ++k
)
3126 cbBarInfo
& bar
= *row
.mBars
[k
];
3127 wxRect
& bounds
= bar
.mBounds
;
3131 if ( bar
.mHasLeftHandle
)
3133 if ( HasPoint( pos
, bounds
.x
, bounds
.y
,
3134 mProps
.mResizeHandleSize
, bounds
.height
) )
3136 return CB_LEFT_BAR_HANDLE_HITTED
;
3139 if ( bar
.mHasRightHandle
)
3141 if ( HasPoint( pos
, bounds
.x
+ bounds
.width
- mProps
.mResizeHandleSize
, bounds
.y
,
3142 mProps
.mResizeHandleSize
, bounds
.height
) )
3144 return CB_RIGHT_BAR_HANDLE_HITTED
;
3147 if ( HasPoint( pos
, bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
) )
3148 return CB_BAR_CONTENT_HITTED
;
3150 } // hit-test next bar
3154 return CB_NO_ITEMS_HITTED
;
3157 void cbDockPane::GetBarResizeRange( cbBarInfo
* pBar
, int* from
, int *till
,
3158 bool forLeftHandle
)
3160 cbBarInfo
* pGivenBar
= pBar
;
3164 // calc unavailable space from the left
3166 while( pBar
->mpPrev
)
3168 pBar
= pBar
->mpPrev
;
3170 if ( !pBar
->IsFixed() ) notFree
+= mProps
.mMinCBarDim
.x
;
3171 else notFree
+= pBar
->mBounds
.width
;
3180 // calc unavailable space from the right
3182 while( pBar
->mpNext
)
3184 pBar
= pBar
->mpNext
;
3186 if ( pBar
->mBounds
.x
>= mPaneWidth
) break;
3188 // treat not-fixed bars as minimized
3190 if ( !pBar
->IsFixed() )
3192 notFree
+= mProps
.mMinCBarDim
.x
;
3195 if ( pBar
->mBounds
.x
+ pBar
->mBounds
.width
>= mPaneWidth
)
3197 notFree
+= mPaneWidth
- pBar
->mBounds
.x
;
3201 notFree
+= pBar
->mBounds
.width
;
3206 *till
= mPaneWidth
- notFree
;
3208 // do not let resizing totally deform the bar itself
3210 if ( forLeftHandle
)
3212 (*till
) -= mProps
.mMinCBarDim
.x
;
3215 (*from
) += mProps
.mMinCBarDim
.x
;
3218 int cbDockPane::GetMinimalRowHeight( cbRowInfo
* pRow
)
3220 int height
= mProps
.mMinCBarDim
.y
;
3223 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3225 if ( pRow
->mBars
[i
]->IsFixed() )
3226 height
= wxMax( height
, pRow
->mBars
[i
]->mBounds
.height
);
3229 if ( pRow
->mHasUpperHandle
)
3230 height
+= mProps
.mResizeHandleSize
;
3232 if ( pRow
->mHasLowerHandle
)
3233 height
+= mProps
.mResizeHandleSize
;
3238 void cbDockPane::SetRowHeight( cbRowInfo
* pRow
, int newHeight
)
3240 if ( pRow
->mHasUpperHandle
)
3242 newHeight
-= mProps
.mResizeHandleSize
;
3244 if ( pRow
->mHasLowerHandle
)
3246 newHeight
-= mProps
.mResizeHandleSize
;
3249 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3251 if ( !pRow
->mBars
[i
]->IsFixed() )
3252 pRow
->mBars
[i
]->mBounds
.height
= newHeight
;
3256 void cbDockPane::GetRowResizeRange( cbRowInfo
* pRow
, int* from
, int* till
,
3257 bool forUpperHandle
)
3259 cbRowInfo
* pGivenRow
= pRow
;
3261 // calc unavailable space from above
3265 while( pRow
->mpPrev
)
3267 pRow
= pRow
->mpPrev
;
3269 notFree
+= GetMinimalRowHeight( pRow
);
3275 // allow accupy the client window space by resizing pane rows
3276 if ( mAlignment
== FL_ALIGN_BOTTOM
)
3278 *from
-= mpLayout
->GetClientHeight();
3280 if ( mAlignment
== FL_ALIGN_RIGHT
)
3282 *from
-= mpLayout
->GetClientWidth();
3284 // calc unavailable space from below
3290 while( pRow
->mpNext
)
3292 pRow
= pRow
->mpNext
;
3294 notFree
+= GetMinimalRowHeight( pRow
);
3298 *till
= mPaneHeight
- notFree
;
3300 // allow adjustinig pane space vs. client window space by resizing pane row heights
3302 if ( mAlignment
== FL_ALIGN_TOP
)
3304 *till
+= mpLayout
->GetClientHeight();
3306 if ( mAlignment
== FL_ALIGN_LEFT
)
3308 *till
+= mpLayout
->GetClientWidth();
3310 // do not let the resizing of the row totally squeeze the row itself
3312 cbRowInfo
& row
= *pGivenRow
;
3314 if ( forUpperHandle
)
3316 *till
= row
.mRowY
+ row
.mRowHeight
- GetMinimalRowHeight( pGivenRow
);
3318 if ( row
.mHasUpperHandle
)
3320 *till
-= mProps
.mResizeHandleSize
;
3324 *from
+= GetMinimalRowHeight( pGivenRow
);
3326 if ( row
.mHasLowerHandle
)
3328 *from
-= mProps
.mResizeHandleSize
;
3332 void cbDockPane::ResizeRow( cbRowInfo
* pRow
, int ofs
,
3333 bool forUpperHandle
)
3335 cbResizeRowEvent
evt( pRow
, ofs
, forUpperHandle
, this );
3337 mpLayout
->FirePluginEvent( evt
);
3340 void cbDockPane::ResizeBar( cbBarInfo
* pBar
, int ofs
,
3341 bool forLeftHandle
)
3343 pBar
->mpRow
->mpExpandedBar
= NULL
;
3345 mpLayout
->GetUpdatesManager().OnStartChanges();
3347 wxRect
& bounds
= pBar
->mBounds
;
3349 if ( forLeftHandle
)
3351 // do not allow bar width become less then minimal
3352 if ( bounds
.x
+ ofs
> bounds
.x
+ bounds
.width
- mProps
.mMinCBarDim
.x
)
3354 bounds
.width
= mProps
.mMinCBarDim
.x
;
3360 bounds
.width
-= ofs
;
3365 // move bar left if necessary
3366 if ( bounds
.width
+ ofs
< mProps
.mMinCBarDim
.x
)
3368 bounds
.x
= bounds
.x
+ bounds
.width
+ ofs
- mProps
.mMinCBarDim
.x
;
3369 bounds
.width
= mProps
.mMinCBarDim
.x
;
3372 // resize right border only
3373 bounds
.width
+= ofs
;
3377 cbRowInfo
* pToRow
= pBar
->mpRow
;
3379 this->RemoveBar( pBar
);
3381 InsertBar( pBar
, pToRow
);
3383 mpLayout
->RecalcLayout(FALSE
);
3385 mpLayout
->GetUpdatesManager().OnFinishChanges();
3386 mpLayout
->GetUpdatesManager().UpdateNow();
3390 /*** row/bar resizing related methods ***/
3392 void cbDockPane::DrawVertHandle( wxDC
& dc
, int x
, int y
, int height
)
3394 int lower
= y
+ height
;
3396 dc
.SetPen( mpLayout
->mLightPen
);
3397 dc
.DrawLine( x
,y
, x
, lower
);
3399 dc
.SetPen( mpLayout
->mGrayPen
);
3401 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3404 dc
.DrawLine( x
,y
, x
, lower
);
3407 dc
.SetPen( mpLayout
->mDarkPen
);
3409 dc
.DrawLine( x
,y
, x
, lower
);
3411 dc
.SetPen( mpLayout
->mBlackPen
);
3413 dc
.DrawLine( x
,y
, x
, lower
);
3416 void cbDockPane::DrawHorizHandle( wxDC
& dc
, int x
, int y
, int width
)
3418 int right
= x
+ width
;
3420 dc
.SetPen( mpLayout
->mLightPen
);
3421 dc
.DrawLine( x
,y
, right
, y
);
3423 dc
.SetPen( mpLayout
->mGrayPen
);
3426 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3429 dc
.DrawLine( x
,y
, right
, y
);
3432 dc
.SetPen( mpLayout
->mDarkPen
);
3433 dc
.DrawLine( x
,y
, right
, ++y
);
3435 dc
.SetPen( mpLayout
->mBlackPen
);
3436 dc
.DrawLine( x
,y
, right
, ++y
);
3439 cbBarInfo
* cbDockPane::GetBarInfoByWindow( wxWindow
* pBarWnd
)
3441 wxBarIterator
i( mRows
);
3445 if ( i
.BarInfo().mpBarWnd
== pBarWnd
)
3447 return &i
.BarInfo();
3452 void cbDockPane::GetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3454 pLst
->DeleteContents( TRUE
);
3458 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3460 cbBarInfo
& bar
= *pRow
->mBars
[i
];
3462 cbBarShapeData
* pData
= new cbBarShapeData();
3464 pLst
->Append( (wxObject
*)pData
);
3466 pData
->mBounds
= bar
.mBounds
;
3467 pData
->mLenRatio
= bar
.mLenRatio
;
3471 void cbDockPane::SetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3473 if ( pLst
->First() == NULL
)
3476 wxNode
* pData
= pLst
->First();
3479 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3481 wxASSERT( pData
); // DBG::
3483 cbBarInfo
& bar
= *pRow
->mBars
[i
];;
3485 cbBarShapeData
& data
= *((cbBarShapeData
*)pData
->Data());
3487 bar
.mBounds
= data
.mBounds
;
3488 bar
.mLenRatio
= data
.mLenRatio
;
3490 pData
= pData
->Next();
3494 /***** Implementation for class cbUpdatesManagerBase *****/
3496 IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase
, wxObject
)
3498 /***** Implementation for class cbPluginBase *****/
3500 IMPLEMENT_ABSTRACT_CLASS( cbPluginBase
, wxEvtHandler
)
3502 cbPluginBase::~cbPluginBase()
3507 bool cbPluginBase::ProcessEvent(wxEvent
& event
)
3509 if ( mPaneMask
== wxALL_PANES
)
3511 return wxEvtHandler::ProcessEvent( event
);
3513 // extract mask info. from received event
3515 cbPluginEvent
& evt
= *( (cbPluginEvent
*)&event
);
3517 if ( evt
.mpPane
== 0 &&
3518 mPaneMask
== wxALL_PANES
)
3520 return wxEvtHandler::ProcessEvent( event
);
3524 switch ( evt
.mpPane
->mAlignment
)
3526 case FL_ALIGN_TOP
: mask
= FL_ALIGN_TOP_PANE
; break;
3527 case FL_ALIGN_BOTTOM
: mask
= FL_ALIGN_BOTTOM_PANE
;break;
3528 case FL_ALIGN_LEFT
: mask
= FL_ALIGN_LEFT_PANE
; break;
3529 case FL_ALIGN_RIGHT
: mask
= FL_ALIGN_RIGHT_PANE
; break;
3532 // if event's pane maks matches the plugin's mask
3534 if ( mPaneMask
& mask
)
3536 return wxEvtHandler::ProcessEvent( event
);
3538 // otherwise pass to the next handler if present
3540 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event
) )