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__)
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 /***** Implementation for class cbRowInfo *****/
2065 IMPLEMENT_DYNAMIC_CLASS( cbRowInfo
, wxObject
)
2067 cbRowInfo::cbRowInfo(void)
2069 : mNotFixedBarsCnt( FALSE
),
2072 mpExpandedBar ( NULL
)
2075 cbRowInfo::~cbRowInfo()
2077 // nothing! all bars are removed using global bar
2078 // list in wxFrameLayout class
2081 /***** Implementation for class cbBarInfo *****/
2083 IMPLEMENT_DYNAMIC_CLASS( cbBarInfo
, wxObject
)
2085 cbBarInfo::cbBarInfo(void)
2093 cbBarInfo::~cbBarInfo()
2098 /***** Implementation for class cbDockPane *****/
2100 IMPLEMENT_DYNAMIC_CLASS( cbDockPane
, wxObject
)
2102 // FIXME:: how to eliminate these cut&pasted constructors?
2104 cbDockPane::cbDockPane(void)
2105 : mLeftMargin ( 1 ),
2109 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2110 // since the real dimensions of the pane may not
2111 // be known, while inserting bars initially
2112 mPaneHeight( 32768 ),
2118 cbDockPane::cbDockPane( int alignment
, wxFrameLayout
* pPanel
)
2120 : mLeftMargin ( 1 ),
2124 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2125 // since the real dimensions of the pane may not
2126 // be known, while inserting bars initially
2127 mPaneHeight( 32768 ),
2128 mAlignment ( alignment
),
2129 mpLayout ( pPanel
),
2133 cbDockPane::~cbDockPane()
2136 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2139 mRowShapeData
.DeleteContents( TRUE
);
2141 // NOTE:: control bar infromation structures are cleaned-up
2142 // in wxFrameLayout's destructor, using global control-bar list
2145 void cbDockPane::SetMargins( int top
, int bottom
, int left
, int right
)
2148 mBottomMargin
= bottom
;
2150 mRightMargin
= right
;
2153 /*** helpers of cbDockPane ***/
2155 void cbDockPane::PaintBarDecorations( cbBarInfo
* pBar
, wxDC
& dc
)
2157 cbDrawBarDecorEvent
evt( pBar
, dc
, this );
2159 mpLayout
->FirePluginEvent( evt
);
2162 void cbDockPane::PaintBarHandles( cbBarInfo
* pBar
, wxDC
& dc
)
2164 cbDrawBarHandlesEvent
evt( pBar
, dc
, this );
2166 mpLayout
->FirePluginEvent( evt
);
2169 void cbDockPane::PaintBar( cbBarInfo
* pBar
, wxDC
& dc
)
2171 PaintBarDecorations( pBar
, dc
);
2172 PaintBarHandles( pBar
, dc
);
2175 void cbDockPane::PaintRowHandles( cbRowInfo
* pRow
, wxDC
& dc
)
2177 cbDrawRowHandlesEvent
evt( pRow
, dc
, this );
2179 mpLayout
->FirePluginEvent( evt
);
2181 cbDrawRowDecorEvent
evt1( pRow
, dc
, this );
2183 mpLayout
->FirePluginEvent( evt1
);
2186 void cbDockPane::PaintRowBackground ( cbRowInfo
* pRow
, wxDC
& dc
)
2188 cbDrawRowBkGroundEvent
evt( pRow
, dc
, this );
2190 mpLayout
->FirePluginEvent( evt
);
2193 void cbDockPane::PaintRowDecorations( cbRowInfo
* pRow
, wxDC
& dc
)
2197 // decorations first
2198 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2200 PaintBarDecorations( pRow
->mBars
[i
], dc
);
2202 // then handles if present
2203 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2205 PaintBarHandles( pRow
->mBars
[i
], dc
);
2208 void cbDockPane::PaintRow( cbRowInfo
* pRow
, wxDC
& dc
)
2210 PaintRowBackground ( pRow
, dc
);
2211 PaintRowDecorations( pRow
, dc
);
2212 PaintRowHandles ( pRow
, dc
);
2215 void cbDockPane::PaintPaneBackground( wxDC
& dc
)
2217 cbDrawPaneBkGroundEvent
evt( dc
, this );
2219 mpLayout
->FirePluginEvent( evt
);
2222 void cbDockPane::PaintPaneDecorations( wxDC
& dc
)
2224 cbDrawPaneDecorEvent
evt( dc
, this );
2226 mpLayout
->FirePluginEvent( evt
);
2229 void cbDockPane::PaintPane( wxDC
& dc
)
2231 PaintPaneBackground( dc
);
2235 // first decorations
2236 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2238 PaintRowBackground( mRows
[i
], dc
);
2239 PaintRowDecorations( mRows
[i
], dc
);
2243 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2244 PaintRowHandles( mRows
[i
], dc
);
2247 PaintPaneDecorations( dc
);
2250 void cbDockPane::SizeBar( cbBarInfo
* pBar
)
2252 cbSizeBarWndEvent
evt( pBar
, this );
2254 mpLayout
->FirePluginEvent( evt
);
2258 void cbDockPane::SizeRowObjects( cbRowInfo
* pRow
)
2261 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2262 SizeBar( pRow
->mBars
[i
] );
2265 void cbDockPane::SizePaneObjects()
2268 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2269 SizeRowObjects( mRows
[i
] );
2272 wxDC
* cbDockPane::StartDrawInArea( const wxRect
& area
)
2276 cbStartDrawInAreaEvent
evt( area
, &pDc
, this );
2278 mpLayout
->FirePluginEvent( evt
);
2283 void cbDockPane::FinishDrawInArea( const wxRect
& area
)
2285 cbFinishDrawInAreaEvent
evt( area
, this );
2287 mpLayout
->FirePluginEvent( evt
);
2290 bool cbDockPane::IsFixedSize( cbBarInfo
* pInfo
)
2292 return ( pInfo
->mDimInfo
.mIsFixed
);
2295 int cbDockPane::GetNotFixedBarsCount( cbRowInfo
* pRow
)
2300 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2302 if ( !pRow
->mBars
[i
]->IsFixed() )
2309 void cbDockPane::RemoveBar( cbBarInfo
* pBar
)
2311 bool needsRestoring
= mProps
.mNonDestructFrictionOn
&&
2312 mpStoredRow
== pBar
->mpRow
;
2314 cbRemoveBarEvent
evt( pBar
, this );
2316 mpLayout
->FirePluginEvent( evt
);
2318 if ( needsRestoring
)
2320 SetRowShapeData( mpStoredRow
, &mRowShapeData
);
2326 void cbDockPane::SyncRowFlags( cbRowInfo
* pRow
)
2328 // setup mHasOnlyFixedBars flag for the row information
2329 pRow
->mHasOnlyFixedBars
= TRUE
;
2331 pRow
->mNotFixedBarsCnt
= 0;
2334 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2336 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2340 if ( !bar
.IsFixed() )
2342 pRow
->mHasOnlyFixedBars
= FALSE
;
2343 ++pRow
->mNotFixedBarsCnt
;
2348 void cbDockPane::FrameToPane( int* x
, int* y
)
2353 if ( mAlignment
== FL_ALIGN_TOP
||
2354 mAlignment
== FL_ALIGN_BOTTOM
2357 *x
-= mBoundsInParent
.x
;
2358 *y
-= mBoundsInParent
.y
;
2362 int rx
= *x
, ry
= *y
;
2364 *x
= ry
- mBoundsInParent
.y
;
2366 *y
= rx
- mBoundsInParent
.x
;
2370 void cbDockPane::PaneToFrame( int* x
, int* y
)
2372 if ( mAlignment
== FL_ALIGN_TOP
||
2373 mAlignment
== FL_ALIGN_BOTTOM
2376 *x
+= mBoundsInParent
.x
;
2377 *y
+= mBoundsInParent
.y
;
2381 int rx
= *x
, ry
= *y
;
2383 *x
= ry
+ mBoundsInParent
.x
;
2385 *y
= mBoundsInParent
.y
+ rx
;
2392 void cbDockPane::FrameToPane( wxRect
* pRect
)
2394 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2395 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2396 pRect
->y
+ pRect
->height
);
2398 FrameToPane( &upperLeft
.x
, &upperLeft
.y
);
2399 FrameToPane( &lowerRight
.x
, &lowerRight
.y
);
2401 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2402 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2404 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2405 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2408 void cbDockPane::PaneToFrame( wxRect
* pRect
)
2410 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2411 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2412 pRect
->y
+ pRect
->height
);
2414 PaneToFrame( &upperLeft
.x
, &upperLeft
.y
);
2415 PaneToFrame( &lowerRight
.x
, &lowerRight
.y
);
2417 //wxRect newRect = wxRect( upperLeft, lowerRight );
2419 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2420 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2422 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2423 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2426 int cbDockPane::GetRowAt( int paneY
)
2435 for ( ; i
!= mRows
.Count(); ++i
)
2437 int rowHeight
= mRows
[i
]->mRowHeight
;
2439 int third
= rowHeight
/3;
2441 if ( paneY
>= curY
&& paneY
< curY
+ third
)
2444 if ( paneY
>= curY
+ third
&& paneY
< curY
+ rowHeight
- third
)
2453 int cbDockPane::GetRowAt( int upperY
, int lowerY
)
2457 int range = lowerY - upperY;
2458 int oneThird = range / 3;
2460 wxNode* pRow = mRows.First();
2464 if ( lowerY <= 0 ) return -1;
2468 int rowHeight = GetRowHeight( (wxList*)pRow->Data() );
2470 if ( upperY >= curY &&
2471 lowerY < curY ) return row;
2473 if ( upperY <= curY &&
2475 curY - upperY >= oneThird ) return row-1;
2477 if ( ( upperY < curY + rowHeight &&
2478 lowerY >= curY + rowHeight &&
2479 curY + rowHeight - lowerY >= oneThird )
2483 if ( lowerY <= curY + rowHeight ) return row;
2487 pRow = pRow->Next();
2491 int mid
= upperY
+ (lowerY
- upperY
)/2;
2499 for ( ; i
!= mRows
.Count(); ++i
)
2501 int rowHeight
= mRows
[i
]->mRowHeight
;
2503 if ( mid
>= curY
&& mid
< curY
+ rowHeight
) return i
;
2511 int cbDockPane::GetRowY( cbRowInfo
* pRow
)
2516 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2518 if ( mRows
[i
] == pRow
)
2521 curY
+= mRows
[i
]->mRowHeight
;
2527 bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo
* pRow
)
2529 while ( pRow
->mpPrev
)
2531 pRow
= pRow
->mpPrev
;
2533 if ( pRow
->mHasOnlyFixedBars
)
2541 bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo
* pRow
)
2543 while( pRow
->mpNext
)
2545 pRow
= pRow
->mpNext
;
2547 if ( pRow
->mHasOnlyFixedBars
)
2555 bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo
* pBar
)
2557 while( pBar
->mpPrev
)
2559 pBar
= pBar
->mpPrev
;
2561 if ( pBar
->IsFixed() )
2569 bool cbDockPane::HasNotFixedBarsRight( cbBarInfo
* pBar
)
2571 while( pBar
->mpNext
)
2573 pBar
= pBar
->mpNext
;
2575 if ( pBar
->IsFixed() )
2583 void cbDockPane::CalcLengthRatios( cbRowInfo
* pInRow
)
2589 // calc current-maximal-total-length of all maximized bars
2591 for ( i
= 0; i
!= pInRow
->mBars
.GetCount(); ++i
)
2593 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2595 if ( !bar
.IsFixed() )
2596 totalWidth
+= bar
.mBounds
.width
;
2599 // set up percentages of occupied space for each maximized bar
2601 for ( i
= 0; i
!= pInRow
->mBars
.Count(); ++i
)
2603 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2605 if ( !bar
.IsFixed() )
2606 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalWidth
);
2610 void cbDockPane::RecalcRowLayout( cbRowInfo
* pRow
)
2612 cbLayoutRowEvent
evt( pRow
, this );
2614 mpLayout
->FirePluginEvent( evt
);
2617 void cbDockPane::ExpandBar( cbBarInfo
* pBar
)
2619 mpLayout
->GetUpdatesManager().OnStartChanges();
2621 if ( !pBar
->mpRow
->mpExpandedBar
)
2623 // save ratios only when there arent any bars expanded yet
2625 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2628 ratios
.Alloc( pBar
->mpRow
->mNotFixedBarsCnt
);
2630 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2634 if ( !pCur
->IsFixed() )
2637 ratios
[ ratios
.GetCount() - 1 ] = pCur
->mLenRatio
;
2640 pCur
= pCur
->mpNext
;
2644 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2648 pCur
->mLenRatio
= 0.0; // minimize the rest
2650 pCur
= pCur
->mpNext
;
2653 pBar
->mLenRatio
= 1.0; // 100%
2654 pBar
->mBounds
.width
= 0;
2656 pBar
->mpRow
->mpExpandedBar
= pBar
;
2658 mpLayout
->RecalcLayout( FALSE
);
2660 mpLayout
->GetUpdatesManager().OnFinishChanges();
2661 mpLayout
->GetUpdatesManager().UpdateNow();
2664 void cbDockPane::ContractBar( cbBarInfo
* pBar
)
2666 mpLayout
->GetUpdatesManager().OnStartChanges();
2668 // FIXME: What's the purpose of this???
2669 // double ratio = 1.0/ double( pBar->mpRow->mNotFixedBarsCnt );
2671 // restore ratios which were present before expansion
2673 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2675 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2681 if ( !pCur
->IsFixed() )
2683 pCur
->mLenRatio
= ratios
[i
];
2687 pCur
= pCur
->mpNext
;
2693 pBar
->mpRow
->mpExpandedBar
= NULL
;
2695 mpLayout
->RecalcLayout( FALSE
);
2697 mpLayout
->GetUpdatesManager().OnFinishChanges();
2698 mpLayout
->GetUpdatesManager().UpdateNow();
2701 void cbDockPane::InitLinksForRow( cbRowInfo
* pRow
)
2704 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2706 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2711 bar
.mpPrev
= pRow
->mBars
[i
-1];
2713 if ( i
== pRow
->mBars
.Count() - 1 )
2716 bar
.mpNext
= pRow
->mBars
[i
+1];
2720 void cbDockPane::InitLinksForRows()
2723 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2725 cbRowInfo
& row
= *mRows
[i
];
2730 row
.mpPrev
= mRows
[i
-1];
2732 if ( i
== mRows
.Count() - 1 )
2735 row
.mpNext
= mRows
[i
+1];
2739 void cbDockPane::DoInsertBar( cbBarInfo
* pBar
, int rowNo
)
2741 cbRowInfo
* pRow
= NULL
;
2743 if ( rowNo
== -1 || rowNo
>= (int)mRows
.Count() )
2745 pRow
= new cbRowInfo();
2747 if ( rowNo
== -1 && mRows
.Count() )
2749 mRows
.Insert( pRow
, 0 );
2757 pRow
= mRows
[rowNo
];
2759 if ( mProps
.mNonDestructFrictionOn
== TRUE
)
2761 // store original shape of the row (before the bar is inserted)
2765 GetRowShapeData( mpStoredRow
, &mRowShapeData
);
2769 if ( pRow
->mBars
.Count() )
2771 pRow
->mpExpandedBar
= NULL
;
2773 cbInsertBarEvent
insEvt( pBar
, pRow
, this );
2775 mpLayout
->FirePluginEvent( insEvt
);
2777 mpLayout
->GetUpdatesManager().OnRowWillChange( pRow
, this );
2780 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
, const wxRect
& atRect
)
2782 wxRect rect
= atRect
;
2783 FrameToPane( &rect
);
2785 pBarInfo
->mBounds
.x
= rect
.x
;
2786 pBarInfo
->mBounds
.width
= rect
.width
;
2787 pBarInfo
->mBounds
.height
= rect
.height
;
2789 int row
= GetRowAt( rect
.y
, rect
.y
+ rect
.height
);
2791 DoInsertBar( pBarInfo
, row
);
2794 void cbDockPane::InsertBar( cbBarInfo
* pBar
, cbRowInfo
* pIntoRow
)
2796 cbInsertBarEvent
insEvt( pBar
, pIntoRow
, this );
2798 mpLayout
->FirePluginEvent( insEvt
);
2800 mpLayout
->GetUpdatesManager().OnRowWillChange( pIntoRow
, this );
2803 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
)
2805 // set transient properties
2807 pBarInfo
->mpRow
= NULL
;
2808 pBarInfo
->mHasLeftHandle
= FALSE
;
2809 pBarInfo
->mHasRightHandle
= FALSE
;
2810 pBarInfo
->mLenRatio
= 0.0;
2812 // set preferred bar dimensions, according to the state in which
2813 // the bar is being inserted
2815 pBarInfo
->mBounds
.width
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].x
;
2816 pBarInfo
->mBounds
.height
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].y
;
2818 DoInsertBar( pBarInfo
, pBarInfo
->mRowNo
);
2821 void cbDockPane::RemoveRow( cbRowInfo
* pRow
)
2824 // first, hide all bar-windows in the removed row
2825 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2827 if ( pRow
->mBars
[i
]->mpBarWnd
)
2828 pRow
->mBars
[i
]->mpBarWnd
->Show( FALSE
);
2831 mRows
.Remove( pRow
);
2833 pRow
->mUMgrData
.SetDirty(TRUE
);
2836 void cbDockPane::InsertRow( cbRowInfo
* pRow
, cbRowInfo
* pBeforeRow
)
2842 mRows
.Insert( pRow
, mRows
.Index( pBeforeRow
) );
2846 pRow
->mUMgrData
.SetDirty(TRUE
);
2849 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2850 pRow
->mBars
[i
]->mUMgrData
.SetDirty( TRUE
);
2852 SyncRowFlags( pRow
);
2855 void cbDockPane::SetPaneWidth(int width
)
2857 if ( IsHorizontal() )
2858 mPaneWidth
= width
- mLeftMargin
- mRightMargin
;
2860 mPaneWidth
= width
- mTopMargin
- mBottomMargin
;
2864 void cbDockPane::SetBoundsInParent( const wxRect
& rect
)
2866 mBoundsInParent
= rect
;
2868 // set pane dimensions in local coordinates
2870 if ( IsHorizontal() )
2872 mPaneWidth
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2873 mPaneHeight
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2877 mPaneWidth
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2878 mPaneHeight
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2881 // convert bounding rectangles of all pane items into parent frame's coordinates
2883 wxBarIterator
i( mRows
);
2885 wxRect noMarginsRect
= mBoundsInParent
;
2887 noMarginsRect
.x
+= mLeftMargin
;
2888 noMarginsRect
.y
+= mTopMargin
;
2889 noMarginsRect
.width
-= ( mLeftMargin
+ mRightMargin
);
2890 noMarginsRect
.height
-= ( mTopMargin
+ mBottomMargin
);
2892 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2894 if ( mBoundsInParent
.width
< 0 ||
2895 mBoundsInParent
.height
< 0 )
2897 hide_rect( mBoundsInParent
);
2899 if ( noMarginsRect
.width
< 0 ||
2900 noMarginsRect
.height
< 0 )
2902 hide_rect( noMarginsRect
);
2904 // calculate mBoundsInParent for each item in the pane
2908 cbBarInfo
& bar
= i
.BarInfo();
2910 cbRowInfo
* pRowInfo
= bar
.mpRow
;
2912 // set up row info, if this is first bar in the row
2914 if ( pRowInfo
&& bar
.mpPrev
== NULL
)
2916 pRowInfo
->mBoundsInParent
.y
= pRowInfo
->mRowY
;
2917 pRowInfo
->mBoundsInParent
.x
= 0;
2918 pRowInfo
->mBoundsInParent
.width
= mPaneWidth
;
2919 pRowInfo
->mBoundsInParent
.height
= pRowInfo
->mRowHeight
;
2921 PaneToFrame( &pRowInfo
->mBoundsInParent
);
2923 clip_rect_against_rect( pRowInfo
->mBoundsInParent
, noMarginsRect
);
2926 wxRect bounds
= bar
.mBounds
;
2928 // exclude dimensions of handles, when calculating
2929 // bar's bounds in parent (i.e. "visual bounds")
2931 if ( bar
.mHasLeftHandle
)
2933 bounds
.x
+= mProps
.mResizeHandleSize
;
2934 bounds
.width
-= mProps
.mResizeHandleSize
;
2937 if ( bar
.mHasRightHandle
)
2939 bounds
.width
-= mProps
.mResizeHandleSize
;
2941 PaneToFrame( &bounds
);
2943 clip_rect_against_rect( bounds
, noMarginsRect
);
2945 bar
.mBoundsInParent
= bounds
;
2949 bool cbDockPane::BarPresent( cbBarInfo
* pBar
)
2951 wxBarIterator
iter( mRows
);
2953 while( iter
.Next() )
2955 if ( &iter
.BarInfo() == pBar
) return TRUE
;
2960 cbRowInfo
* cbDockPane::GetRow( int row
)
2962 if ( row
>= (int)mRows
.Count() ) return NULL
;
2964 return mRows
[ row
];
2967 int cbDockPane::GetRowIndex( cbRowInfo
* pRow
)
2970 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2972 if ( mRows
[i
] == pRow
)
2976 wxFAIL_MSG("Row must be present to call cbDockPane::GetRowIndex()");
2981 int cbDockPane::GetPaneHeight()
2983 // first, recalculate row heights and the Y-positions
2985 cbLayoutRowsEvent
evt( this );
2986 mpLayout
->FirePluginEvent( evt
);
2990 if ( IsHorizontal() )
2992 height
+= mTopMargin
+ mBottomMargin
;
2994 height
+= mLeftMargin
+ mRightMargin
;
2996 int count
= mRows
.Count();
3000 height
+= mRows
[count
-1]->mRowY
+ mRows
[count
-1]->mRowHeight
;
3005 int cbDockPane::GetAlignment()
3010 bool cbDockPane::MatchesMask( int paneMask
)
3014 // FIXME:: use array instead of switch()
3018 case FL_ALIGN_TOP
: thisMask
= FL_ALIGN_TOP_PANE
; break;
3019 case FL_ALIGN_BOTTOM
: thisMask
= FL_ALIGN_BOTTOM_PANE
;break;
3020 case FL_ALIGN_LEFT
: thisMask
= FL_ALIGN_LEFT_PANE
; break;
3021 case FL_ALIGN_RIGHT
: thisMask
= FL_ALIGN_RIGHT_PANE
; break;
3024 wxFAIL_MSG("Bad FL alignment type detected in cbDockPane::MatchesMask()");
3027 return ( thisMask
& paneMask
) != 0;
3030 void cbDockPane::RecalcLayout()
3032 // first, reposition rows and items vertically
3034 cbLayoutRowsEvent
evt( this );
3035 mpLayout
->FirePluginEvent( evt
);
3037 // then horizontally in each row
3040 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3041 RecalcRowLayout( mRows
[i
] );
3044 int cbDockPane::GetDockingState()
3046 if ( mAlignment
== FL_ALIGN_TOP
||
3047 mAlignment
== FL_ALIGN_BOTTOM
)
3049 return wxCBAR_DOCKED_HORIZONTALLY
;
3052 return wxCBAR_DOCKED_VERTICALLY
;
3055 inline bool cbDockPane::HasPoint( const wxPoint
& pos
, int x
, int y
,
3056 int width
, int height
)
3058 return ( pos
.x
>= x
&&
3060 pos
.x
< x
+ width
&&
3061 pos
.y
< y
+ height
);
3064 int cbDockPane::HitTestPaneItems( const wxPoint
& pos
,
3073 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3075 cbRowInfo
& row
= *mRows
[i
];
3079 // hit-test handles of the row, if present
3081 if ( row
.mHasUpperHandle
)
3083 if ( HasPoint( pos
, 0, row
.mRowY
,
3084 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3086 return CB_UPPER_ROW_HANDLE_HITTED
;
3089 if ( row
.mHasLowerHandle
)
3091 if ( HasPoint( pos
, 0, row
.mRowY
+ row
.mRowHeight
- mProps
.mResizeHandleSize
,
3092 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3094 return CB_LOWER_ROW_HANDLE_HITTED
;
3097 // hit-test bar handles and bar content
3100 for ( k
= 0; k
!= row
.mBars
.Count(); ++k
)
3102 cbBarInfo
& bar
= *row
.mBars
[k
];
3103 wxRect
& bounds
= bar
.mBounds
;
3107 if ( bar
.mHasLeftHandle
)
3109 if ( HasPoint( pos
, bounds
.x
, bounds
.y
,
3110 mProps
.mResizeHandleSize
, bounds
.height
) )
3112 return CB_LEFT_BAR_HANDLE_HITTED
;
3115 if ( bar
.mHasRightHandle
)
3117 if ( HasPoint( pos
, bounds
.x
+ bounds
.width
- mProps
.mResizeHandleSize
, bounds
.y
,
3118 mProps
.mResizeHandleSize
, bounds
.height
) )
3120 return CB_RIGHT_BAR_HANDLE_HITTED
;
3123 if ( HasPoint( pos
, bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
) )
3124 return CB_BAR_CONTENT_HITTED
;
3126 } // hit-test next bar
3130 return CB_NO_ITEMS_HITTED
;
3133 void cbDockPane::GetBarResizeRange( cbBarInfo
* pBar
, int* from
, int *till
,
3134 bool forLeftHandle
)
3136 cbBarInfo
* pGivenBar
= pBar
;
3140 // calc unavailable space from the left
3142 while( pBar
->mpPrev
)
3144 pBar
= pBar
->mpPrev
;
3146 if ( !pBar
->IsFixed() ) notFree
+= mProps
.mMinCBarDim
.x
;
3147 else notFree
+= pBar
->mBounds
.width
;
3156 // calc unavailable space from the right
3158 while( pBar
->mpNext
)
3160 pBar
= pBar
->mpNext
;
3162 if ( pBar
->mBounds
.x
>= mPaneWidth
) break;
3164 // treat not-fixed bars as minimized
3166 if ( !pBar
->IsFixed() )
3168 notFree
+= mProps
.mMinCBarDim
.x
;
3171 if ( pBar
->mBounds
.x
+ pBar
->mBounds
.width
>= mPaneWidth
)
3173 notFree
+= mPaneWidth
- pBar
->mBounds
.x
;
3177 notFree
+= pBar
->mBounds
.width
;
3182 *till
= mPaneWidth
- notFree
;
3184 // do not let resizing totally deform the bar itself
3186 if ( forLeftHandle
)
3188 (*till
) -= mProps
.mMinCBarDim
.x
;
3191 (*from
) += mProps
.mMinCBarDim
.x
;
3194 int cbDockPane::GetMinimalRowHeight( cbRowInfo
* pRow
)
3196 int height
= mProps
.mMinCBarDim
.y
;
3199 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3201 if ( pRow
->mBars
[i
]->IsFixed() )
3202 height
= wxMax( height
, pRow
->mBars
[i
]->mBounds
.height
);
3205 if ( pRow
->mHasUpperHandle
)
3206 height
+= mProps
.mResizeHandleSize
;
3208 if ( pRow
->mHasLowerHandle
)
3209 height
+= mProps
.mResizeHandleSize
;
3214 void cbDockPane::SetRowHeight( cbRowInfo
* pRow
, int newHeight
)
3216 if ( pRow
->mHasUpperHandle
)
3218 newHeight
-= mProps
.mResizeHandleSize
;
3220 if ( pRow
->mHasLowerHandle
)
3222 newHeight
-= mProps
.mResizeHandleSize
;
3225 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3227 if ( !pRow
->mBars
[i
]->IsFixed() )
3228 pRow
->mBars
[i
]->mBounds
.height
= newHeight
;
3232 void cbDockPane::GetRowResizeRange( cbRowInfo
* pRow
, int* from
, int* till
,
3233 bool forUpperHandle
)
3235 cbRowInfo
* pGivenRow
= pRow
;
3237 // calc unavailable space from above
3241 while( pRow
->mpPrev
)
3243 pRow
= pRow
->mpPrev
;
3245 notFree
+= GetMinimalRowHeight( pRow
);
3251 // allow accupy the client window space by resizing pane rows
3252 if ( mAlignment
== FL_ALIGN_BOTTOM
)
3254 *from
-= mpLayout
->GetClientHeight();
3256 if ( mAlignment
== FL_ALIGN_RIGHT
)
3258 *from
-= mpLayout
->GetClientWidth();
3260 // calc unavailable space from below
3266 while( pRow
->mpNext
)
3268 pRow
= pRow
->mpNext
;
3270 notFree
+= GetMinimalRowHeight( pRow
);
3274 *till
= mPaneHeight
- notFree
;
3276 // allow adjustinig pane space vs. client window space by resizing pane row heights
3278 if ( mAlignment
== FL_ALIGN_TOP
)
3280 *till
+= mpLayout
->GetClientHeight();
3282 if ( mAlignment
== FL_ALIGN_LEFT
)
3284 *till
+= mpLayout
->GetClientWidth();
3286 // do not let the resizing of the row totally squeeze the row itself
3288 cbRowInfo
& row
= *pGivenRow
;
3290 if ( forUpperHandle
)
3292 *till
= row
.mRowY
+ row
.mRowHeight
- GetMinimalRowHeight( pGivenRow
);
3294 if ( row
.mHasUpperHandle
)
3296 *till
-= mProps
.mResizeHandleSize
;
3300 *from
+= GetMinimalRowHeight( pGivenRow
);
3302 if ( row
.mHasLowerHandle
)
3304 *from
-= mProps
.mResizeHandleSize
;
3308 void cbDockPane::ResizeRow( cbRowInfo
* pRow
, int ofs
,
3309 bool forUpperHandle
)
3311 cbResizeRowEvent
evt( pRow
, ofs
, forUpperHandle
, this );
3313 mpLayout
->FirePluginEvent( evt
);
3316 void cbDockPane::ResizeBar( cbBarInfo
* pBar
, int ofs
,
3317 bool forLeftHandle
)
3319 pBar
->mpRow
->mpExpandedBar
= NULL
;
3321 mpLayout
->GetUpdatesManager().OnStartChanges();
3323 wxRect
& bounds
= pBar
->mBounds
;
3325 if ( forLeftHandle
)
3327 // do not allow bar width become less then minimal
3328 if ( bounds
.x
+ ofs
> bounds
.x
+ bounds
.width
- mProps
.mMinCBarDim
.x
)
3330 bounds
.width
= mProps
.mMinCBarDim
.x
;
3336 bounds
.width
-= ofs
;
3341 // move bar left if necessary
3342 if ( bounds
.width
+ ofs
< mProps
.mMinCBarDim
.x
)
3344 bounds
.x
= bounds
.x
+ bounds
.width
+ ofs
- mProps
.mMinCBarDim
.x
;
3345 bounds
.width
= mProps
.mMinCBarDim
.x
;
3348 // resize right border only
3349 bounds
.width
+= ofs
;
3353 cbRowInfo
* pToRow
= pBar
->mpRow
;
3355 this->RemoveBar( pBar
);
3357 InsertBar( pBar
, pToRow
);
3359 mpLayout
->RecalcLayout(FALSE
);
3361 mpLayout
->GetUpdatesManager().OnFinishChanges();
3362 mpLayout
->GetUpdatesManager().UpdateNow();
3366 /*** row/bar resizing related methods ***/
3368 void cbDockPane::DrawVertHandle( wxDC
& dc
, int x
, int y
, int height
)
3370 int lower
= y
+ height
;
3372 dc
.SetPen( mpLayout
->mLightPen
);
3373 dc
.DrawLine( x
,y
, x
, lower
);
3375 dc
.SetPen( mpLayout
->mGrayPen
);
3377 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3380 dc
.DrawLine( x
,y
, x
, lower
);
3383 dc
.SetPen( mpLayout
->mDarkPen
);
3385 dc
.DrawLine( x
,y
, x
, lower
);
3387 dc
.SetPen( mpLayout
->mBlackPen
);
3389 dc
.DrawLine( x
,y
, x
, lower
);
3392 void cbDockPane::DrawHorizHandle( wxDC
& dc
, int x
, int y
, int width
)
3394 int right
= x
+ width
;
3396 dc
.SetPen( mpLayout
->mLightPen
);
3397 dc
.DrawLine( x
,y
, right
, y
);
3399 dc
.SetPen( mpLayout
->mGrayPen
);
3402 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3405 dc
.DrawLine( x
,y
, right
, y
);
3408 dc
.SetPen( mpLayout
->mDarkPen
);
3409 dc
.DrawLine( x
,y
, right
, ++y
);
3411 dc
.SetPen( mpLayout
->mBlackPen
);
3412 dc
.DrawLine( x
,y
, right
, ++y
);
3415 cbBarInfo
* cbDockPane::GetBarInfoByWindow( wxWindow
* pBarWnd
)
3417 wxBarIterator
i( mRows
);
3421 if ( i
.BarInfo().mpBarWnd
== pBarWnd
)
3423 return &i
.BarInfo();
3428 void cbDockPane::GetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3430 pLst
->DeleteContents( TRUE
);
3434 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3436 cbBarInfo
& bar
= *pRow
->mBars
[i
];
3438 cbBarShapeData
* pData
= new cbBarShapeData();
3440 pLst
->Append( (wxObject
*)pData
);
3442 pData
->mBounds
= bar
.mBounds
;
3443 pData
->mLenRatio
= bar
.mLenRatio
;
3447 void cbDockPane::SetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3449 if ( pLst
->First() == NULL
)
3452 wxNode
* pData
= pLst
->First();
3455 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3457 wxASSERT( pData
); // DBG::
3459 cbBarInfo
& bar
= *pRow
->mBars
[i
];;
3461 cbBarShapeData
& data
= *((cbBarShapeData
*)pData
->Data());
3463 bar
.mBounds
= data
.mBounds
;
3464 bar
.mLenRatio
= data
.mLenRatio
;
3466 pData
= pData
->Next();
3470 /***** Implementation for class cbUpdatesManagerBase *****/
3472 IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase
, wxObject
)
3474 /***** Implementation for class cbPluginBase *****/
3476 IMPLEMENT_ABSTRACT_CLASS( cbPluginBase
, wxEvtHandler
)
3478 cbPluginBase::~cbPluginBase()
3483 bool cbPluginBase::ProcessEvent(wxEvent
& event
)
3485 if ( mPaneMask
== wxALL_PANES
)
3487 return wxEvtHandler::ProcessEvent( event
);
3489 // extract mask info. from received event
3491 cbPluginEvent
& evt
= *( (cbPluginEvent
*)&event
);
3493 if ( evt
.mpPane
== 0 &&
3494 mPaneMask
== wxALL_PANES
)
3496 return wxEvtHandler::ProcessEvent( event
);
3500 switch ( evt
.mpPane
->mAlignment
)
3502 case FL_ALIGN_TOP
: mask
= FL_ALIGN_TOP_PANE
; break;
3503 case FL_ALIGN_BOTTOM
: mask
= FL_ALIGN_BOTTOM_PANE
;break;
3504 case FL_ALIGN_LEFT
: mask
= FL_ALIGN_LEFT_PANE
; break;
3505 case FL_ALIGN_RIGHT
: mask
= FL_ALIGN_RIGHT_PANE
; break;
3508 // if event's pane maks matches the plugin's mask
3510 if ( mPaneMask
& mask
)
3512 return wxEvtHandler::ProcessEvent( event
);
3514 // otherwise pass to the next handler if present
3516 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event
) )