1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Contrib. demo
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 #if wxCHECK_VERSION(2,3,0)
54 wxEventType cbEVT_PL_LEFT_DOWN
= wxNewEventType();
55 wxEventType cbEVT_PL_LEFT_UP
= wxNewEventType();
56 wxEventType cbEVT_PL_RIGHT_DOWN
= wxNewEventType();
57 wxEventType cbEVT_PL_RIGHT_UP
= wxNewEventType();
58 wxEventType cbEVT_PL_MOTION
= wxNewEventType();
60 wxEventType cbEVT_PL_LEFT_DCLICK
= wxNewEventType();
62 wxEventType cbEVT_PL_LAYOUT_ROW
= wxNewEventType();
63 wxEventType cbEVT_PL_RESIZE_ROW
= wxNewEventType();
64 wxEventType cbEVT_PL_LAYOUT_ROWS
= wxNewEventType();
65 wxEventType cbEVT_PL_INSERT_BAR
= wxNewEventType();
66 wxEventType cbEVT_PL_RESIZE_BAR
= wxNewEventType();
67 wxEventType cbEVT_PL_REMOVE_BAR
= wxNewEventType();
68 wxEventType cbEVT_PL_SIZE_BAR_WND
= wxNewEventType();
70 wxEventType cbEVT_PL_DRAW_BAR_DECOR
= wxNewEventType();
71 wxEventType cbEVT_PL_DRAW_ROW_DECOR
= wxNewEventType();
72 wxEventType cbEVT_PL_DRAW_PANE_DECOR
= wxNewEventType();
73 wxEventType cbEVT_PL_DRAW_BAR_HANDLES
= wxNewEventType();
74 wxEventType cbEVT_PL_DRAW_ROW_HANDLES
= wxNewEventType();
75 wxEventType cbEVT_PL_DRAW_ROW_BKGROUND
= wxNewEventType();
76 wxEventType cbEVT_PL_DRAW_PANE_BKGROUND
= wxNewEventType();
78 wxEventType cbEVT_PL_START_BAR_DRAGGING
= wxNewEventType();
79 wxEventType cbEVT_PL_DRAW_HINT_RECT
= wxNewEventType();
81 wxEventType cbEVT_PL_START_DRAW_IN_AREA
= wxNewEventType();
82 wxEventType cbEVT_PL_FINISH_DRAW_IN_AREA
= wxNewEventType();
84 wxEventType cbEVT_PL_CUSTOMIZE_BAR
= wxNewEventType();
85 wxEventType cbEVT_PL_CUSTOMIZE_LAYOUT
= wxNewEventType();
87 wxEventType wxCUSTOM_CB_PLUGIN_EVENTS_START_AT
= wxNewEventType();
88 #endif // #if wxCHECK_VERSION(2,3,0)
90 // some ascii-art, still can't get these *nice* cursors working on wx... :-(
92 static const char* _gHorizCursorImg
[] =
94 "............XX....XX............",
95 "............XX....XX............",
96 "............XX....XX............",
97 "............XX....XX............",
98 "............XX....XX............",
99 "...X........XX....XX........X...",
100 "..XX........XX....XX........XX..",
101 ".XXX........XX....XX........XXX.",
102 "XXXXXXXXXXXXXX....XXXXXXXXXXXXXX",
103 ".XXX........XX....XX........XXX.",
104 "..XX........XX....XX........XX..",
105 "...X........XX....XX........X...",
106 "............XX....XX............",
107 "............XX....XX............",
108 "............XX....XX............",
109 "............XX....XX............"
112 static const char* _gVertCursorImg
[] =
114 "................X...............",
115 "...............XXX..............",
116 "..............XXXXX.............",
117 ".............XXXXXXX............",
118 "................X...............",
119 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
120 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
121 "................................",
122 "................................",
123 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
124 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
125 "................X...............",
126 ".............XXXXXXX............",
127 "..............XXXXX.............",
128 "...............XXX..............",
129 "................X..............."
132 // helper inline functions
134 static inline bool rect_contains_point( const wxRect
& rect
, int x
, int y
)
136 return ( x
>= rect
.x
&&
138 x
< rect
.x
+ rect
.width
&&
139 y
< rect
.y
+ rect
.height
);
142 static inline bool rect_hits_rect( const wxRect
& r1
, const wxRect
& r2
)
144 if ( ( r2
.x
>= r1
.x
&& r2
.x
<= r1
.x
+ r1
.width
) ||
145 ( r1
.x
>= r2
.x
&& r1
.x
<= r2
.x
+ r2
.width
) )
147 if ( ( r2
.y
>= r1
.y
&& r2
.y
<= r1
.y
+ r1
.height
) ||
148 ( r1
.y
>= r2
.y
&& r1
.y
<= r2
.y
+ r2
.height
) )
155 static inline void hide_rect( wxRect
& r
)
163 static inline void clip_rect_against_rect( wxRect
& r1
, const wxRect
& r2
)
167 r1
.x
>= r2
.x
+ r2
.width
||
168 r1
.y
>= r2
.y
+ r2
.height
176 if ( r1
.x
+ r1
.width
> r2
.x
+ r2
.width
)
178 r1
.width
= r2
.x
+ r2
.width
- r1
.x
;
180 if ( r1
.y
+ r1
.height
> r2
.y
+ r2
.height
)
182 r1
.height
= r2
.y
+ r2
.height
- r1
.y
;
186 /***** Implementation for class cbBarSpy *****/
188 IMPLEMENT_DYNAMIC_CLASS( cbBarSpy
, wxEvtHandler
)
190 cbBarSpy::cbBarSpy(void)
195 cbBarSpy::cbBarSpy( wxFrameLayout
* pPanel
)
201 void cbBarSpy::SetBarWindow( wxWindow
* pWnd
)
206 bool cbBarSpy::ProcessEvent(wxEvent
& event
)
208 bool handled
= wxEvtHandler::ProcessEvent( event
);
210 int type
= event
.GetEventType();
212 if ( !handled
&& ( type
== wxEVT_LEFT_DOWN
||
213 type
== wxEVT_LEFT_DCLICK
) )
215 wxMouseEvent
& mevent
= *((wxMouseEvent
*)&event
);
220 mpBarWnd
->ClientToScreen( &x
, &y
);
221 mpLayout
->GetParentFrame().ScreenToClient( &x
, &y
);
226 // forwared not-handled event to frame-layout
228 if ( type
== wxEVT_LEFT_DOWN
)
230 //mpLayout->OnLButtonDown( mevent );
234 mpLayout
->OnLDblClick( mevent
);
242 /***** Implementation for class wxFrameLayout *****/
244 IMPLEMENT_DYNAMIC_CLASS( wxFrameLayout
, wxEvtHandler
)
246 BEGIN_EVENT_TABLE( wxFrameLayout
, wxEvtHandler
)
248 EVT_PAINT ( wxFrameLayout::OnPaint
)
249 EVT_SIZE ( wxFrameLayout::OnSize
)
250 EVT_LEFT_DOWN ( wxFrameLayout::OnLButtonDown
)
251 EVT_LEFT_UP ( wxFrameLayout::OnLButtonUp
)
252 EVT_RIGHT_DOWN ( wxFrameLayout::OnRButtonDown
)
253 EVT_RIGHT_UP ( wxFrameLayout::OnRButtonUp
)
254 EVT_MOTION ( wxFrameLayout::OnMouseMove
)
256 EVT_LEFT_DCLICK( wxFrameLayout::OnLDblClick
)
258 EVT_IDLE ( wxFrameLayout::OnIdle
)
259 EVT_SET_FOCUS ( wxFrameLayout::OnSetFocus
)
260 EVT_KILL_FOCUS ( wxFrameLayout::OnKillFocus
)
262 EVT_ACTIVATE ( wxFrameLayout::OnActivate
)
264 EVT_ERASE_BACKGROUND( wxFrameLayout::OnEraseBackground
)
268 // FIXME:: how to eliminate these cut&pasted constructors?
270 wxFrameLayout::wxFrameLayout(void)
273 mpFrameClient( NULL
),
275 mDarkPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
276 mLightPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHILIGHT
), 1, wxSOLID
),
277 mGrayPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
278 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID
),
279 mBorderPen( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
281 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT
),
283 mpPaneInFocus( NULL
),
287 mpTopPlugin ( NULL
),
288 mpCaputesInput( NULL
),
290 mClientWndRefreshPending( FALSE
),
291 mRecalcPending( TRUE
),
292 mCheckFocusWhenIdle( FALSE
)
296 for( int i
= 0; i
!= MAX_PANES
; ++i
)
300 mFloatingOn
= CanReparent();
303 wxFrameLayout::wxFrameLayout( wxWindow
* pParentFrame
, wxWindow
* pFrameClient
, bool activateNow
)
305 : mpFrame( pParentFrame
),
306 mpFrameClient(pFrameClient
),
308 mDarkPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
309 mLightPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHILIGHT
), 1, wxSOLID
),
310 mGrayPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
311 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID
),
312 mBorderPen( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
314 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT
),
316 mpPaneInFocus( NULL
),
319 mFloatingOn ( TRUE
),
321 mpTopPlugin ( NULL
),
322 mpCaputesInput( NULL
),
324 mClientWndRefreshPending( FALSE
),
325 mRecalcPending( TRUE
),
326 mCheckFocusWhenIdle( FALSE
),
332 for( int i
= 0; i
!= MAX_PANES
; ++i
)
334 mPanes
[i
] = new cbDockPane( i
, this );
341 // DBG:: set RED color of frame's background for the
342 // prurpose of tracking engine bugs "visually"
344 GetParentFrame().SetBackgroundColour( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
) );
347 mFloatingOn
= CanReparent();
350 // NOTE:: below are the only plaftorm-check "ifdef"s in the docking system!
352 bool wxFrameLayout::CanReparent()
356 #elif defined (__WXGTK__)
361 return FALSE
; // reparenting is not yet supported by Motif and others
371 void wxFrameLayout::ReparentWindow( wxWindow
* pChild
, wxWindow
* pNewParent
)
376 if ( pChild
->GetParent() )
378 bool success
= pChild
->GetParent()->GetChildren().DeleteObject( pChild
);
380 wxASSERT( success
); // DBG::
383 ::SetParent( (HWND
)pChild
->m_hWnd
, (HWND
)pNewParent
->m_hWnd
);
385 pNewParent
->GetChildren().Append( pChild
);
387 pChild
->SetParent( pNewParent
);
389 pChild
->Reparent(pNewParent
);
392 #elif defined(__WXGTK__)
393 // FOR NOW:: floating with wxGtk still very buggy
397 //pChild->ReParent( pNewParent );
401 wxMessageBox( "Sorry, docking is not supported for ports other than MSW and wxGTK" );
405 void wxFrameLayout::DestroyBarWindows()
407 wxNode
* pSpy
= mBarSpyList
.First();
411 cbBarSpy
& spy
= *((cbBarSpy
*)pSpy
->Data());
413 if ( spy
.mpBarWnd
->GetEventHandler() == &spy
)
415 spy
.mpBarWnd
->PopEventHandler();
424 for( size_t i
= 0; i
!= mAllBars
.Count(); ++i
)
426 if ( mAllBars
[i
]->mpBarWnd
)
428 mAllBars
[i
]->mpBarWnd
->Destroy();
429 mAllBars
[i
]->mpBarWnd
= NULL
;
434 void wxFrameLayout::ShowFloatedWindows( bool show
)
436 wxNode
* pNode
= mFloatedFrames
.First();
440 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
444 pNode
= pNode
->Next();
448 wxFrameLayout::~wxFrameLayout()
457 // destoy the chain of plugins from left to right
459 wxEvtHandler
* pCur
= mpTopPlugin
;
463 while ( pCur
->GetPreviousHandler() )
465 pCur
= pCur
->GetPreviousHandler();
469 wxEvtHandler
* pNext
= pCur
->GetNextHandler();
476 // destroy contents of arrays and lists
480 for( i
= 0; i
!= MAX_PANES
; ++i
)
486 delete mpHorizCursor
;
489 if ( mpNormalCursor
)
490 delete mpNormalCursor
;
496 wxNode
* pSpy
= mBarSpyList
.First();
500 cbBarSpy
& spy
= *((cbBarSpy
*)pSpy
->Data());
502 if ( spy
.mpBarWnd
->GetEventHandler() == &spy
)
504 spy
.mpBarWnd
->PopEventHandler();
511 for( i
= 0; i
!= mAllBars
.Count(); ++i
)
516 void wxFrameLayout::EnableFloating( bool enable
)
518 mFloatingOn
= enable
&& CanReparent();
521 void wxFrameLayout::Activate()
527 ShowFloatedWindows( TRUE
);
530 void wxFrameLayout::Deactivate()
532 ShowFloatedWindows( FALSE
);
539 void wxFrameLayout::SetFrameClient( wxWindow
* pFrameClient
)
541 mpFrameClient
= pFrameClient
;
544 wxWindow
* wxFrameLayout::GetFrameClient()
546 return mpFrameClient
;
549 cbUpdatesManagerBase
& wxFrameLayout::GetUpdatesManager()
552 mpUpdatesMgr
= CreateUpdatesManager();
554 return *mpUpdatesMgr
;
557 void wxFrameLayout::SetUpdatesManager( cbUpdatesManagerBase
* pUMgr
)
562 mpUpdatesMgr
= pUMgr
;
564 mpUpdatesMgr
->SetLayout( this );
567 cbUpdatesManagerBase
* wxFrameLayout::CreateUpdatesManager()
569 return new cbGCUpdatesMgr( this );
570 //return new cbSimpleUpdatesMgr( this );
573 void wxFrameLayout::AddBar( wxWindow
* pBarWnd
,
574 const cbDimInfo
& dimInfo
,
578 const wxString
& name
,
583 if ( pBarWnd
&& spyEvents
)
585 // hook up spy to bar window
586 cbBarSpy
* pSpy
= new cbBarSpy( this );
588 pSpy
->SetBarWindow( pBarWnd
);
589 pBarWnd
->PushEventHandler( pSpy
);
591 mBarSpyList
.Append( pSpy
);
594 cbBarInfo
* pInfo
= new cbBarInfo();
597 pInfo
->mpBarWnd
= pBarWnd
;
598 pInfo
->mDimInfo
= dimInfo
;
599 pInfo
->mState
= state
;
600 pInfo
->mAlignment
= alignment
;
601 pInfo
->mRowNo
= rowNo
;
602 pInfo
->mBounds
.x
= columnPos
;
604 mAllBars
.Add( pInfo
);
606 DoSetBarState( pInfo
);
609 bool wxFrameLayout::RedockBar( cbBarInfo
* pBar
,
610 const wxRect
& shapeInParent
,
616 pToPane
= HitTestPanes( shapeInParent
, NULL
);
620 return FALSE
; // bar's shape does not hit any pane
621 // - redocking is NOT possible
623 cbDockPane
* pBarPane
= GetBarPane( pBar
);
627 GetUpdatesManager().OnStartChanges();
629 pBarPane
->RemoveBar( pBar
);
631 // FIXME FIXME:: the below recalc. may be a *huge* performance
632 // hit, it could be eliminated though...
633 // but first the "pane-postion-changed" problem
636 RecalcLayout( FALSE
);
638 pToPane
->InsertBar( pBar
, shapeInParent
);
640 RecalcLayout( FALSE
);
642 // finish update "transaction"
646 GetUpdatesManager().OnFinishChanges();
647 GetUpdatesManager().UpdateNow();
653 cbBarInfo
* wxFrameLayout::FindBarByName( const wxString
& name
)
655 for( size_t i
= 0; i
!= mAllBars
.Count(); ++i
)
657 if ( mAllBars
[i
]->mName
== name
)
664 cbBarInfo
* wxFrameLayout::FindBarByWindow( const wxWindow
* pWnd
)
666 for( size_t i
= 0; i
!= mAllBars
.Count(); ++i
)
668 if ( mAllBars
[i
]->mpBarWnd
== pWnd
)
675 BarArrayT
& wxFrameLayout::GetBars()
680 void wxFrameLayout::SetBarState( cbBarInfo
* pBar
, int newState
, bool updateNow
)
682 if ( newState
== wxCBAR_FLOATING
&& !mFloatingOn
)
688 GetUpdatesManager().OnStartChanges();
690 pBar
->mUMgrData
.SetDirty(TRUE
);
692 // check bar's previous state
694 if ( pBar
->mState
!= wxCBAR_HIDDEN
&& pBar
->mState
!= wxCBAR_FLOATING
)
699 bool success
= LocateBar( pBar
, &pRow
, &pPane
);
701 wxASSERT( success
); // DBG::
703 // save LRU-dim info before removing bar
705 pBar
->mDimInfo
.mLRUPane
= pPane
->GetAlignment();
706 pBar
->mDimInfo
.mBounds
[ pPane
->GetAlignment() ] = pBar
->mBounds
;
708 // remove it from the pane it was docked on
710 pPane
->RemoveBar( pBar
);
714 if ( pBar
->mState
== wxCBAR_FLOATING
&& newState
!= wxCBAR_FLOATING
)
716 // remove bar's window form the containing mini-frame
717 // and set it's parent to be layout's parent frame
719 if ( pBar
->mpBarWnd
)
721 pBar
->mpBarWnd
->Show(FALSE
); // to avoid flicker upon reparenting
723 wxNode
* pNode
= mFloatedFrames
.First();
727 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
729 if ( pFFrm
->GetBar() == pBar
)
731 pFFrm
->Show( FALSE
); // reduces flicker sligthly
733 ReparentWindow( pBar
->mpBarWnd
, &GetParentFrame() );
735 pBar
->mBounds
= pBar
->mDimInfo
.mBounds
[ pBar
->mDimInfo
.mLRUPane
];
737 if ( newState
!= wxCBAR_HIDDEN
)
739 pBar
->mAlignment
= pBar
->mDimInfo
.mLRUPane
;
741 mFloatedFrames
.DeleteNode( pNode
);
743 pFFrm
->Show( FALSE
);
744 pFFrm
->Destroy(); break;
747 pNode
= pNode
->Next();
750 // FOR NOW:: excessive!
751 //if ( mpFrameClient ) mpFrameClient->Refresh();
753 mClientWndRefreshPending
= TRUE
;
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
);
958 for( size_t i
= 0; i
!= mAllBars
.Count(); ++i
)
960 if ( mAllBars
[i
] == pBarInfo
)
962 #if wxCHECK_VERSION(2,3,2)
963 mAllBars
.RemoveAt(i
);
967 if ( pBarInfo
->mpBarWnd
) // hides it's window
969 pBarInfo
->mpBarWnd
->Show( FALSE
);
976 int avoidCompilerWarning
= 0;
977 wxASSERT(avoidCompilerWarning
); // DBG:: bar info should be present in the list of all bars of all panes
981 bool wxFrameLayout::LocateBar( cbBarInfo
* pBarInfo
,
983 cbDockPane
** ppPane
)
988 for( int 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
1149 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1151 mPanes
[i
]->SizePaneObjects();
1154 void wxFrameLayout::OnSize( wxSizeEvent
& event
)
1156 if ( event
.GetEventObject() == (wxObject
*) mpFrame
)
1161 /*** protected members ***/
1163 void wxFrameLayout::HideBarWindows()
1165 for( size_t i
= 0; i
!= mAllBars
.Count(); ++i
)
1167 if ( mAllBars
[i
]->mpBarWnd
&& mAllBars
[i
]->mState
!= wxCBAR_FLOATING
)
1169 mAllBars
[i
]->mpBarWnd
->Show( FALSE
);
1171 // then floated frames
1173 ShowFloatedWindows( FALSE
);
1175 if ( mpFrameClient
)
1177 mpFrameClient
->Show( FALSE
);
1180 void wxFrameLayout::UnhookFromFrame()
1182 // NOTE:: the SetEvtHandlerEnabled() method is not used
1183 // here, since it is assumed, that unhooking layout
1184 // from window may result destroying of the layout itself
1186 // BUG BUG BUG (wx):: this would not be a problem if
1187 // wxEvtHandler's destructor would check if
1188 // this handler is currently the top-most
1189 // handler of some window, and additionally
1190 // to the reconnecting itself from the chain
1191 // it would also re-setup current event handler
1192 // of the window using wxWindow::SetEventHandler()
1196 if ( mpFrame
->GetEventHandler() == this )
1198 mpFrame
->PopEventHandler();
1202 // TBD ???: Cannot reach this code
1205 if ( this == mpFrame
->GetEventHandler() )
1207 mpFrame
->SetEventHandler( this->GetNextHandler() );
1210 wxEvtHandler
* pCur
= mpFrame
->GetEventHandler();
1214 if ( pCur
== this ) break;
1216 pCur
= pCur
->GetNextHandler();
1219 // do not try to unhook ourselves if we're not hooked yet
1220 if ( !pCur
) return;
1223 if ( GetPreviousHandler() )
1225 GetPreviousHandler()->SetNextHandler( GetNextHandler() );
1228 mpFrame
->PopEventHandler();
1233 if ( GetNextHandler() )
1235 GetNextHandler()->SetPreviousHandler( GetPreviousHandler() );
1237 SetNextHandler( NULL
);
1238 SetPreviousHandler( NULL
);
1242 void wxFrameLayout::HookUpToFrame()
1244 // unhook us first, we're already hooked up
1248 // put ourselves on top
1250 mpFrame
->PushEventHandler( this );
1253 cbDockPane
* wxFrameLayout::GetBarPane( cbBarInfo
* pBar
)
1255 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1257 if ( mPanes
[i
]->BarPresent( pBar
) ) return mPanes
[i
];
1262 void wxFrameLayout::CreateCursors()
1265 // FIXME:: The below code somehow doesn't work - cursors remain unchanged
1268 set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
1270 mpHorizCursor = new wxCursor( bits, 32, 16 );
1272 set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
1274 mpVertCursor = new wxCursor( bits, 32, 16 );
1277 // FOR NOW:: use standard ones
1279 mpHorizCursor
= new wxCursor(wxCURSOR_SIZEWE
);
1280 mpVertCursor
= new wxCursor(wxCURSOR_SIZENS
);
1281 mpNormalCursor
= new wxCursor(wxCURSOR_ARROW
);
1282 mpDragCursor
= new wxCursor(wxCURSOR_CROSS
);
1283 mpNECursor
= new wxCursor(wxCURSOR_NO_ENTRY
);
1285 mFloatingPosStep
.x
= 25;
1286 mFloatingPosStep
.y
= 25;
1288 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
1289 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
1292 bool wxFrameLayout::HitTestPane( cbDockPane
* pPane
, int x
, int y
)
1294 return rect_contains_point( pPane
->GetRealRect(), x
, y
);
1297 cbDockPane
* wxFrameLayout::HitTestPanes( const wxRect
& rect
,
1298 cbDockPane
* pCurPane
)
1300 // first, give the privilege to the current pane
1302 if ( pCurPane
&& rect_hits_rect( pCurPane
->GetRealRect(), rect
) )
1306 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1308 if ( pCurPane
!= mPanes
[i
] &&
1309 rect_hits_rect( mPanes
[i
]->GetRealRect(), rect
) )
1316 void wxFrameLayout::ForwardMouseEvent( wxMouseEvent
& event
,
1317 cbDockPane
* pToPane
,
1320 wxPoint
pos( event
.m_x
, event
.m_y
);
1321 pToPane
->FrameToPane( &pos
.x
, &pos
.y
);
1323 #if wxCHECK_VERSION(2,3,0)
1324 if ( eventType
== cbEVT_PL_LEFT_DOWN
)
1326 cbLeftDownEvent
evt( pos
, pToPane
);
1327 FirePluginEvent( evt
);
1329 else if ( eventType
== cbEVT_PL_LEFT_DCLICK
)
1331 cbLeftDClickEvent
evt( pos
, pToPane
);
1332 FirePluginEvent( evt
);
1334 else if ( eventType
== cbEVT_PL_LEFT_UP
)
1336 cbLeftUpEvent
evt( pos
, pToPane
);
1337 FirePluginEvent( evt
);
1339 else if ( eventType
== cbEVT_PL_RIGHT_DOWN
)
1341 cbRightDownEvent
evt( pos
, pToPane
);
1342 FirePluginEvent( evt
);
1344 else if ( eventType
== cbEVT_PL_RIGHT_UP
)
1346 cbRightUpEvent
evt( pos
, pToPane
);
1347 FirePluginEvent( evt
);
1349 else if ( eventType
== cbEVT_PL_MOTION
)
1351 cbMotionEvent
evt( pos
, pToPane
);
1352 FirePluginEvent( evt
);
1356 int avoidCompilerWarning
= 0;
1357 wxASSERT(avoidCompilerWarning
); // DBG::
1360 switch ( eventType
)
1362 case cbEVT_PL_LEFT_DOWN
: { cbLeftDownEvent
evt( pos
, pToPane
);
1363 FirePluginEvent( evt
); break;
1366 case cbEVT_PL_LEFT_DCLICK
:{ cbLeftDClickEvent
evt( pos
, pToPane
);
1367 FirePluginEvent( evt
); break;
1370 case cbEVT_PL_LEFT_UP
: { cbLeftUpEvent
evt( pos
, pToPane
);
1371 FirePluginEvent( evt
); break;
1374 case cbEVT_PL_RIGHT_DOWN
: { cbRightDownEvent
evt( pos
, pToPane
);
1375 FirePluginEvent( evt
); break;
1378 case cbEVT_PL_RIGHT_UP
: { cbRightUpEvent
evt( pos
, pToPane
);
1379 FirePluginEvent( evt
); break;
1382 case cbEVT_PL_MOTION
: { cbMotionEvent
evt( pos
, pToPane
);
1383 FirePluginEvent( evt
); break;
1386 default : wxASSERT(0); // DBG::
1388 #endif // #if wxCHECK_VERSION(2,3,0)
1389 } // wxFrameLayout::ForwardMouseEvent()
1392 void wxFrameLayout::RouteMouseEvent( wxMouseEvent
& event
, int pluginEvtType
)
1394 if ( mpPaneInFocus
)
1396 ForwardMouseEvent( event
, mpPaneInFocus
, pluginEvtType
);
1398 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1400 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1402 ForwardMouseEvent( event
, mPanes
[i
], pluginEvtType
);
1408 /*** event handlers ***/
1410 void wxFrameLayout::OnRButtonDown( wxMouseEvent
& event
)
1412 RouteMouseEvent( event
, cbEVT_PL_RIGHT_DOWN
);
1415 void wxFrameLayout::OnRButtonUp( wxMouseEvent
& event
)
1417 RouteMouseEvent( event
, cbEVT_PL_RIGHT_UP
);
1420 void wxFrameLayout::OnLButtonDown( wxMouseEvent
& event
)
1422 RouteMouseEvent( event
, cbEVT_PL_LEFT_DOWN
);
1425 void wxFrameLayout::OnLDblClick( wxMouseEvent
& event
)
1427 RouteMouseEvent( event
, cbEVT_PL_LEFT_DCLICK
);
1430 void wxFrameLayout::OnLButtonUp( wxMouseEvent
& event
)
1432 RouteMouseEvent( event
, cbEVT_PL_LEFT_UP
);
1435 void wxFrameLayout::OnMouseMove( wxMouseEvent
& event
)
1437 if ( mpPaneInFocus
)
1439 ForwardMouseEvent( event
, mpPaneInFocus
, cbEVT_PL_MOTION
);
1441 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1443 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1445 if ( mpLRUPane
&& mpLRUPane
!= mPanes
[i
] )
1447 // simulate "mouse-leave" event
1448 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1451 ForwardMouseEvent( event
, mPanes
[i
], cbEVT_PL_MOTION
);
1453 mpLRUPane
= mPanes
[i
];
1460 // simulate "mouse-leave" event
1461 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1466 void wxFrameLayout::OnPaint( wxPaintEvent
& event
)
1468 if ( mRecalcPending
)
1470 RecalcLayout( TRUE
);
1472 wxPaintDC
dc(mpFrame
);
1474 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1476 wxRect
& rect
= mPanes
[i
]->mBoundsInParent
;
1478 dc
.SetClippingRegion( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1480 mPanes
[i
]->PaintPane(dc
);
1482 dc
.DestroyClippingRegion();
1488 void wxFrameLayout::OnEraseBackground( wxEraseEvent
& event
)
1493 void wxFrameLayout::OnIdle( wxIdleEvent
& event
)
1495 wxWindow
* focus
= wxWindow::FindFocus();
1497 if ( !focus
&& mCheckFocusWhenIdle
)
1499 wxMessageBox( "Hi, no more focus in this app!" );
1501 mCheckFocusWhenIdle
= FALSE
;
1502 //ShowFloatedWindows( FALSE );
1505 mCheckFocusWhenIdle
= FALSE
;
1511 void wxFrameLayout::OnKillFocus( wxFocusEvent
& event
)
1513 //wxMessageBox( "wxFrameLayoutGot Kill Focus!" );
1514 //ShowFloatedWindows( FALSE );
1517 void wxFrameLayout::OnSetFocus( wxFocusEvent
& event
)
1519 //ShowFloatedWindows( TRUE );
1522 void wxFrameLayout::OnActivate( wxActivateEvent
& event
)
1525 if ( event
.GetActive() == FALSE
)
1527 wxWindow
* focus
= wxWindow::FindFocus();
1529 if ( !focus
|| focus
== &GetParentFrame() )
1531 mCheckFocusWhenIdle
= TRUE
;
1535 wxMessageBox("Deactivated!" );
1542 void wxFrameLayout::GetPaneProperties( cbCommonPaneProperties
& props
, int alignment
)
1544 props
= mPanes
[alignment
]->mProps
;
1547 void wxFrameLayout::SetPaneProperties( const cbCommonPaneProperties
& props
, int paneMask
)
1549 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1551 if ( mPanes
[i
]->MatchesMask( paneMask
) )
1553 mPanes
[i
]->mProps
= props
;
1556 void wxFrameLayout::SetMargins( int top
, int bottom
, int left
, int right
,
1559 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1561 cbDockPane
& pane
= *mPanes
[i
];
1563 if ( pane
.MatchesMask( paneMask
) )
1565 pane
.mTopMargin
= top
;
1566 pane
.mBottomMargin
= bottom
;
1567 pane
.mLeftMargin
= left
;
1568 pane
.mRightMargin
= right
;
1573 void wxFrameLayout::SetPaneBackground( const wxColour
& colour
)
1575 mBorderPen
.SetColour( colour
);
1578 void wxFrameLayout::RefreshNow( bool recalcLayout
)
1580 if ( recalcLayout
) RecalcLayout( TRUE
);
1582 if ( mpFrame
) mpFrame
->Refresh();
1585 /*** plugin-related methods ***/
1587 void wxFrameLayout::FirePluginEvent( cbPluginEvent
& event
)
1589 // check state of input capture, before processing the event
1591 if ( mpCaputesInput
)
1593 bool isInputEvt
= TRUE
;
1594 #if wxCHECK_VERSION(2,3,0)
1595 if ( event
.m_eventType
!= cbEVT_PL_LEFT_DOWN
&&
1596 event
.m_eventType
!= cbEVT_PL_LEFT_UP
&&
1597 event
.m_eventType
!= cbEVT_PL_RIGHT_DOWN
&&
1598 event
.m_eventType
!= cbEVT_PL_RIGHT_UP
&&
1599 event
.m_eventType
!= cbEVT_PL_MOTION
)
1602 switch ( event
.m_eventType
)
1604 case cbEVT_PL_LEFT_DOWN
: break;
1605 case cbEVT_PL_LEFT_UP
: break;
1606 case cbEVT_PL_RIGHT_DOWN
: break;
1607 case cbEVT_PL_RIGHT_UP
: break;
1608 case cbEVT_PL_MOTION
: break;
1610 default : isInputEvt
= FALSE
; break;
1612 #endif // #if wxCHECK_VERSION(2,3,0)
1616 mpCaputesInput
->ProcessEvent( event
);
1621 GetTopPlugin().ProcessEvent( event
);
1624 void wxFrameLayout::CaptureEventsForPlugin ( cbPluginBase
* pPlugin
)
1626 // cannot capture events for more than one plugin at a time
1627 wxASSERT( mpCaputesInput
== NULL
);
1629 mpCaputesInput
= pPlugin
;
1633 void wxFrameLayout::ReleaseEventsFromPlugin( cbPluginBase
* pPlugin
)
1635 // events should be captured first
1636 wxASSERT( mpCaputesInput
!= NULL
);
1638 mpCaputesInput
= NULL
;
1641 void wxFrameLayout::CaptureEventsForPane( cbDockPane
* toPane
)
1643 // cannot capture events twice (without releasing)
1644 wxASSERT( mpPaneInFocus
== NULL
);
1646 mpFrame
->CaptureMouse();
1648 mpPaneInFocus
= toPane
;
1651 void wxFrameLayout::ReleaseEventsFromPane( cbDockPane
* fromPane
)
1653 // cannot release events without capturing them
1654 wxASSERT( mpPaneInFocus
!= NULL
);
1656 mpFrame
->ReleaseMouse();
1658 mpPaneInFocus
= NULL
;
1661 cbPluginBase
& wxFrameLayout::GetTopPlugin()
1665 PushDefaultPlugins(); // automatic configuration
1667 return *mpTopPlugin
;
1670 void wxFrameLayout::SetTopPlugin( cbPluginBase
* pPlugin
)
1672 mpTopPlugin
= pPlugin
;
1675 bool wxFrameLayout::HasTopPlugin()
1677 return ( mpTopPlugin
!= NULL
);
1680 void wxFrameLayout::PushPlugin( cbPluginBase
* pPlugin
)
1684 mpTopPlugin
= pPlugin
;
1687 pPlugin
->SetNextHandler( mpTopPlugin
);
1689 mpTopPlugin
->SetPreviousHandler( pPlugin
);
1691 mpTopPlugin
= pPlugin
;
1694 mpTopPlugin
->OnInitPlugin(); // notification
1697 void wxFrameLayout::PopPlugin()
1699 wxASSERT( mpTopPlugin
); // DBG:: at least one plugin should be present
1701 cbPluginBase
* pPopped
= mpTopPlugin
;
1703 mpTopPlugin
= (cbPluginBase
*)mpTopPlugin
->GetNextHandler();
1708 void wxFrameLayout::PopAllPlugins()
1710 while( mpTopPlugin
) PopPlugin();
1713 void wxFrameLayout::PushDefaultPlugins()
1715 // FIXME:: to much of the stuff for the default...
1717 AddPlugin( CLASSINFO( cbRowLayoutPlugin
) );
1718 AddPlugin( CLASSINFO( cbBarDragPlugin
) );
1719 AddPlugin( CLASSINFO( cbPaneDrawPlugin
) );
1722 void wxFrameLayout::AddPlugin( wxClassInfo
* pPlInfo
, int paneMask
)
1724 if ( FindPlugin ( pPlInfo
) ) return; // same type of plugin cannot be added twice
1726 cbPluginBase
* pObj
= (cbPluginBase
*)pPlInfo
->CreateObject();
1728 wxASSERT(pObj
); // DBG:: plugin's class should be dynamic
1730 pObj
->mPaneMask
= paneMask
;
1731 pObj
->mpLayout
= this;
1736 void wxFrameLayout::AddPluginBefore( wxClassInfo
* pNextPlInfo
, wxClassInfo
* pPlInfo
,
1739 wxASSERT( pNextPlInfo
!= pPlInfo
); // DBG:: no sence
1741 cbPluginBase
* pNextPl
= FindPlugin( pNextPlInfo
);
1745 AddPlugin( pPlInfo
, paneMask
);
1750 // remove existing one if present
1752 cbPluginBase
* pExistingPl
= FindPlugin( pPlInfo
);
1754 if ( pExistingPl
) RemovePlugin( pPlInfo
);
1756 // create an instance
1758 cbPluginBase
* pNewPl
= (cbPluginBase
*)pPlInfo
->CreateObject();
1760 wxASSERT(pNewPl
); // DBG:: plugin's class should be dynamic
1762 // insert it to the chain
1764 if ( pNextPl
->GetPreviousHandler() )
1766 pNextPl
->GetPreviousHandler()->SetNextHandler( pNewPl
);
1768 mpTopPlugin
= pNewPl
;
1770 pNewPl
->SetNextHandler( pNextPl
);
1772 pNewPl
->SetPreviousHandler( pNextPl
->GetPreviousHandler() );
1774 pNextPl
->SetPreviousHandler( pNewPl
);
1778 pNewPl
->mPaneMask
= paneMask
;
1779 pNewPl
->mpLayout
= this;
1781 pNewPl
->OnInitPlugin();
1784 void wxFrameLayout::RemovePlugin( wxClassInfo
* pPlInfo
)
1786 cbPluginBase
* pPlugin
= FindPlugin( pPlInfo
);
1788 if ( !pPlugin
) return; // it's OK to remove not-existing plugin ;-)
1790 if ( pPlugin
->GetPreviousHandler() == NULL
)
1792 mpTopPlugin
= (cbPluginBase
*)pPlugin
->GetNextHandler();
1797 cbPluginBase
* wxFrameLayout::FindPlugin( wxClassInfo
* pPlInfo
)
1799 cbPluginBase
*pCur
= mpTopPlugin
;
1803 // NOTE:: it might appear useful matching plugin
1804 // classes "polymorphically":
1806 if ( pCur
->GetClassInfo()->IsKindOf( pPlInfo
) )
1810 pCur
= (cbPluginBase
*)pCur
->GetNextHandler();
1816 /***** Implementation for class cbUpdateMgrData *****/
1818 IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData
, wxObject
)
1820 cbUpdateMgrData::cbUpdateMgrData()
1822 : mPrevBounds( -1,-1,0,0 ),
1823 mIsDirty( TRUE
) // inidicate initial change
1826 void cbUpdateMgrData::StoreItemState( const wxRect
& boundsInParent
)
1828 mPrevBounds
= boundsInParent
;
1831 void cbUpdateMgrData::SetDirty( bool isDirty
)
1836 void cbUpdateMgrData::SetCustomData( wxObject
* pCustomData
)
1838 mpCustomData
= pCustomData
;
1841 /***** Implementation for class cbDockPane *****/
1843 void wxBarIterator::Reset()
1845 mpRow
= ( mpRows
->Count() ) ? (*mpRows
)[0] : NULL
;
1849 wxBarIterator::wxBarIterator( RowArrayT
& rows
)
1858 bool wxBarIterator::Next()
1863 mpBar
= mpBar
->mpNext
;
1866 if ( mpRow
->mBars
.GetCount() == 0 )
1871 mpBar
= mpRow
->mBars
[0];
1876 // skip to the next row
1878 mpRow
= mpRow
->mpNext
;
1882 mpBar
= mpRow
->mBars
[0];
1893 cbBarInfo
& wxBarIterator::BarInfo()
1898 cbRowInfo
& wxBarIterator::RowInfo()
1903 /***** Implementation for class cbBarDimHandlerBase *****/
1905 IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase
, wxObject
)
1907 cbBarDimHandlerBase::cbBarDimHandlerBase()
1911 void cbBarDimHandlerBase::AddRef()
1916 void cbBarDimHandlerBase::RemoveRef()
1918 if ( --mRefCount
<= 0 ) delete this;
1921 /***** Implementation for class cbDimInfo *****/
1923 IMPLEMENT_DYNAMIC_CLASS( cbDimInfo
, wxObject
)
1925 cbDimInfo::cbDimInfo()
1933 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1938 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1942 cbDimInfo::cbDimInfo( cbBarDimHandlerBase
* pDimHandler
,
1947 mIsFixed ( isFixed
),
1949 mpHandler( pDimHandler
)
1953 // int vtad = *((int*)mpHandler);
1954 mpHandler
->AddRef();
1957 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1962 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1966 cbDimInfo::cbDimInfo( int dh_x
, int dh_y
,
1974 cbBarDimHandlerBase
* pDimHandler
1976 : mVertGap ( vertGap
),
1977 mHorizGap ( horizGap
),
1978 mIsFixed ( isFixed
),
1979 mpHandler( pDimHandler
)
1983 // int vtad = *((int*)mpHandler);
1984 mpHandler
->AddRef();
1987 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= dh_x
;
1988 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= dh_y
;
1989 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= dv_x
;
1990 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= dv_y
;
1991 mSizes
[wxCBAR_FLOATING
].x
= f_x
;
1992 mSizes
[wxCBAR_FLOATING
].y
= f_y
;
1994 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1995 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1998 cbDimInfo::cbDimInfo( int x
, int y
,
1999 bool isFixed
, int gap
,
2000 cbBarDimHandlerBase
* pDimHandler
)
2003 mIsFixed ( isFixed
),
2004 mpHandler( pDimHandler
)
2008 // int vtad = *((int*)mpHandler);
2009 mpHandler
->AddRef();
2012 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= x
;
2013 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= y
;
2014 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= x
;
2015 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= y
;
2016 mSizes
[wxCBAR_FLOATING
].x
= x
;
2017 mSizes
[wxCBAR_FLOATING
].y
= y
;
2019 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2020 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
2023 cbDimInfo::~cbDimInfo()
2027 mpHandler
->RemoveRef();
2030 const cbDimInfo
& cbDimInfo::operator=( const cbDimInfo
& other
)
2032 if ( this == &other
) return *this;
2034 for( int i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2036 mSizes
[i
] = other
.mSizes
[i
];
2038 mIsFixed
= other
.mIsFixed
;
2039 mpHandler
= other
.mpHandler
;
2041 mVertGap
= other
.mVertGap
;
2042 mHorizGap
= other
.mHorizGap
;
2046 mpHandler
->AddRef();
2051 /***** Implementation for structure cbCommonPaneProperties *****/
2053 IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties
, wxObject
)
2055 cbCommonPaneProperties::cbCommonPaneProperties(void)
2057 : mRealTimeUpdatesOn ( TRUE
),
2058 mOutOfPaneDragOn ( TRUE
),
2059 mExactDockPredictionOn( FALSE
),
2060 mNonDestructFirctionOn( FALSE
),
2061 mShow3DPaneBorderOn ( TRUE
),
2062 mBarFloatingOn ( FALSE
),
2063 mRowProportionsOn ( FALSE
),
2064 mColProportionsOn ( TRUE
),
2065 mBarCollapseIconsOn ( FALSE
),
2066 mBarDragHintsOn ( FALSE
),
2068 mMinCBarDim( 16, 16 ),
2069 mResizeHandleSize( 4 )
2072 /***** Implementation for class cbRowInfo *****/
2074 IMPLEMENT_DYNAMIC_CLASS( cbRowInfo
, wxObject
)
2076 cbRowInfo::cbRowInfo(void)
2078 : mNotFixedBarsCnt( FALSE
),
2081 mpExpandedBar ( NULL
)
2084 cbRowInfo::~cbRowInfo()
2086 // nothing! all bars are removed using global bar
2087 // list in wxFrameLayout class
2090 /***** Implementation for class cbBarInfo *****/
2092 IMPLEMENT_DYNAMIC_CLASS( cbBarInfo
, wxObject
)
2094 cbBarInfo::cbBarInfo(void)
2102 cbBarInfo::~cbBarInfo()
2107 /***** Implementation for class cbDockPane *****/
2109 IMPLEMENT_DYNAMIC_CLASS( cbDockPane
, wxObject
)
2111 // FIXME:: how to eliminate these cut&pasted constructors?
2113 cbDockPane::cbDockPane(void)
2114 : mLeftMargin ( 1 ),
2118 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2119 // since the real dimensions of the pane may not
2120 // be known, while inserting bars initially
2121 mPaneHeight( 32768 ),
2127 cbDockPane::cbDockPane( int alignment
, wxFrameLayout
* pPanel
)
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 ),
2137 mAlignment ( alignment
),
2138 mpLayout ( pPanel
),
2142 cbDockPane::~cbDockPane()
2144 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2148 mRowShapeData
.DeleteContents( TRUE
);
2150 // NOTE:: control bar infromation structures are cleaned-up
2151 // in wxFrameLayout's destructor, using global control-bar list
2154 void cbDockPane::SetMargins( int top
, int bottom
, int left
, int right
)
2157 mBottomMargin
= bottom
;
2159 mRightMargin
= right
;
2162 /*** helpers of cbDockPane ***/
2164 void cbDockPane::PaintBarDecorations( cbBarInfo
* pBar
, wxDC
& dc
)
2166 cbDrawBarDecorEvent
evt( pBar
, dc
, this );
2168 mpLayout
->FirePluginEvent( evt
);
2171 void cbDockPane::PaintBarHandles( cbBarInfo
* pBar
, wxDC
& dc
)
2173 cbDrawBarHandlesEvent
evt( pBar
, dc
, this );
2175 mpLayout
->FirePluginEvent( evt
);
2178 void cbDockPane::PaintBar( cbBarInfo
* pBar
, wxDC
& dc
)
2180 PaintBarDecorations( pBar
, dc
);
2181 PaintBarHandles( pBar
, dc
);
2184 void cbDockPane::PaintRowHandles( cbRowInfo
* pRow
, wxDC
& dc
)
2186 cbDrawRowHandlesEvent
evt( pRow
, dc
, this );
2188 mpLayout
->FirePluginEvent( evt
);
2190 cbDrawRowDecorEvent
evt1( pRow
, dc
, this );
2192 mpLayout
->FirePluginEvent( evt1
);
2195 void cbDockPane::PaintRowBackground ( cbRowInfo
* pRow
, wxDC
& dc
)
2197 cbDrawRowBkGroundEvent
evt( pRow
, dc
, this );
2199 mpLayout
->FirePluginEvent( evt
);
2202 void cbDockPane::PaintRowDecorations( cbRowInfo
* pRow
, wxDC
& dc
)
2206 // decorations first
2207 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2209 PaintBarDecorations( pRow
->mBars
[i
], dc
);
2211 // then handles if present
2212 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2214 PaintBarHandles( pRow
->mBars
[i
], dc
);
2217 void cbDockPane::PaintRow( cbRowInfo
* pRow
, wxDC
& dc
)
2219 PaintRowBackground ( pRow
, dc
);
2220 PaintRowDecorations( pRow
, dc
);
2221 PaintRowHandles ( pRow
, dc
);
2224 void cbDockPane::PaintPaneBackground( wxDC
& dc
)
2226 cbDrawPaneBkGroundEvent
evt( dc
, this );
2228 mpLayout
->FirePluginEvent( evt
);
2231 void cbDockPane::PaintPaneDecorations( wxDC
& dc
)
2233 cbDrawPaneDecorEvent
evt( dc
, this );
2235 mpLayout
->FirePluginEvent( evt
);
2238 void cbDockPane::PaintPane( wxDC
& dc
)
2240 PaintPaneBackground( dc
);
2244 // first decorations
2245 for( i
= 0; i
!= mRows
.Count(); ++i
)
2247 PaintRowBackground( mRows
[i
], dc
);
2248 PaintRowDecorations( mRows
[i
], dc
);
2252 for( i
= 0; i
!= mRows
.Count(); ++i
)
2254 PaintRowHandles( mRows
[i
], dc
);
2257 PaintPaneDecorations( dc
);
2260 void cbDockPane::SizeBar( cbBarInfo
* pBar
)
2262 cbSizeBarWndEvent
evt( pBar
, this );
2264 mpLayout
->FirePluginEvent( evt
);
2268 void cbDockPane::SizeRowObjects( cbRowInfo
* pRow
)
2270 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2272 SizeBar( pRow
->mBars
[i
] );
2275 void cbDockPane::SizePaneObjects()
2277 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2279 SizeRowObjects( mRows
[i
] );
2282 wxDC
* cbDockPane::StartDrawInArea( const wxRect
& area
)
2286 cbStartDrawInAreaEvent
evt( area
, &pDc
, this );
2288 mpLayout
->FirePluginEvent( evt
);
2293 void cbDockPane::FinishDrawInArea( const wxRect
& area
)
2295 cbFinishDrawInAreaEvent
evt( area
, this );
2297 mpLayout
->FirePluginEvent( evt
);
2300 bool cbDockPane::IsFixedSize( cbBarInfo
* pInfo
)
2302 return ( pInfo
->mDimInfo
.mIsFixed
);
2305 int cbDockPane::GetNotFixedBarsCount( cbRowInfo
* pRow
)
2309 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2311 if ( !pRow
->mBars
[i
]->IsFixed() ) ++cnt
;
2316 void cbDockPane::RemoveBar( cbBarInfo
* pBar
)
2318 bool needsRestoring
= mProps
.mNonDestructFirctionOn
&&
2319 mpStoredRow
== pBar
->mpRow
;
2321 cbRemoveBarEvent
evt( pBar
, this );
2323 mpLayout
->FirePluginEvent( evt
);
2325 if ( needsRestoring
)
2327 SetRowShapeData( mpStoredRow
, &mRowShapeData
);
2333 void cbDockPane::SyncRowFlags( cbRowInfo
* pRow
)
2335 // setup mHasOnlyFixedBars flag for the row information
2336 pRow
->mHasOnlyFixedBars
= TRUE
;
2338 pRow
->mNotFixedBarsCnt
= 0;
2340 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2342 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2346 if ( !bar
.IsFixed() )
2348 pRow
->mHasOnlyFixedBars
= FALSE
;
2349 ++pRow
->mNotFixedBarsCnt
;
2354 void cbDockPane::FrameToPane( int* x
, int* y
)
2359 if ( mAlignment
== FL_ALIGN_TOP
||
2360 mAlignment
== FL_ALIGN_BOTTOM
2363 *x
-= mBoundsInParent
.x
;
2364 *y
-= mBoundsInParent
.y
;
2368 int rx
= *x
, ry
= *y
;
2370 *x
= ry
- mBoundsInParent
.y
;
2372 *y
= rx
- mBoundsInParent
.x
;
2376 void cbDockPane::PaneToFrame( int* x
, int* y
)
2378 if ( mAlignment
== FL_ALIGN_TOP
||
2379 mAlignment
== FL_ALIGN_BOTTOM
2382 *x
+= mBoundsInParent
.x
;
2383 *y
+= mBoundsInParent
.y
;
2387 int rx
= *x
, ry
= *y
;
2389 *x
= ry
+ mBoundsInParent
.x
;
2391 *y
= mBoundsInParent
.y
+ rx
;
2398 void cbDockPane::FrameToPane( wxRect
* pRect
)
2400 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2401 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2402 pRect
->y
+ pRect
->height
);
2404 FrameToPane( &upperLeft
.x
, &upperLeft
.y
);
2405 FrameToPane( &lowerRight
.x
, &lowerRight
.y
);
2407 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2408 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2410 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2411 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2414 void cbDockPane::PaneToFrame( wxRect
* pRect
)
2416 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2417 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2418 pRect
->y
+ pRect
->height
);
2420 PaneToFrame( &upperLeft
.x
, &upperLeft
.y
);
2421 PaneToFrame( &lowerRight
.x
, &lowerRight
.y
);
2423 //wxRect newRect = wxRect( upperLeft, lowerRight );
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 int cbDockPane::GetRowAt( int paneY
)
2434 if ( paneY
< 0 ) return -1;
2440 for( ; i
!= mRows
.Count(); ++i
)
2442 int rowHeight
= mRows
[i
]->mRowHeight
;
2444 int third
= rowHeight
/3;
2446 if ( paneY
>= curY
&& paneY
< curY
+ third
)
2449 if ( paneY
>= curY
+ third
&& paneY
< curY
+ rowHeight
- third
)
2458 int cbDockPane::GetRowAt( int upperY
, int lowerY
)
2462 int range = lowerY - upperY;
2463 int oneThird = range / 3;
2465 wxNode* pRow = mRows.First();
2469 if ( lowerY <= 0 ) return -1;
2473 int rowHeight = GetRowHeight( (wxList*)pRow->Data() );
2475 if ( upperY >= curY &&
2476 lowerY < curY ) return row;
2478 if ( upperY <= curY &&
2480 curY - upperY >= oneThird ) return row-1;
2482 if ( ( upperY < curY + rowHeight &&
2483 lowerY >= curY + rowHeight &&
2484 curY + rowHeight - lowerY >= oneThird )
2488 if ( lowerY <= curY + rowHeight ) return row;
2492 pRow = pRow->Next();
2496 int mid
= upperY
+ (lowerY
- upperY
)/2;
2498 if ( mid
< 0 ) return -1;
2503 for( ; i
!= mRows
.Count(); ++i
)
2505 int rowHeight
= mRows
[i
]->mRowHeight
;
2507 if ( mid
>= curY
&& mid
< curY
+ rowHeight
) return i
;
2515 int cbDockPane::GetRowY( cbRowInfo
* pRow
)
2519 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2521 if ( mRows
[i
] == pRow
) break;
2523 curY
+= mRows
[i
]->mRowHeight
;
2529 bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo
* pRow
)
2531 while ( pRow
->mpPrev
)
2533 pRow
= pRow
->mpPrev
;
2535 if ( pRow
->mHasOnlyFixedBars
)
2543 bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo
* pRow
)
2545 while( pRow
->mpNext
)
2547 pRow
= pRow
->mpNext
;
2549 if ( pRow
->mHasOnlyFixedBars
)
2557 bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo
* pBar
)
2559 while( pBar
->mpPrev
)
2561 pBar
= pBar
->mpPrev
;
2563 if ( pBar
->IsFixed() )
2571 bool cbDockPane::HasNotFixedBarsRight( cbBarInfo
* pBar
)
2573 while( pBar
->mpNext
)
2575 pBar
= pBar
->mpNext
;
2577 if ( pBar
->IsFixed() )
2585 void cbDockPane::CalcLengthRatios( cbRowInfo
* pInRow
)
2591 // clac current-maximal-total-length of all maximized bars
2593 for( i
= 0; i
!= pInRow
->mBars
.GetCount(); ++i
)
2595 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2597 if ( !bar
.IsFixed() )
2599 totalWidth
+= bar
.mBounds
.width
;
2602 // set up persentages of occupied space for each maximized bar
2604 for( i
= 0; i
!= pInRow
->mBars
.Count(); ++i
)
2606 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2608 if ( !bar
.IsFixed() )
2610 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalWidth
);
2614 void cbDockPane::RecalcRowLayout( cbRowInfo
* pRow
)
2616 cbLayoutRowEvent
evt( pRow
, this );
2618 mpLayout
->FirePluginEvent( evt
);
2621 void cbDockPane::ExpandBar( cbBarInfo
* pBar
)
2623 mpLayout
->GetUpdatesManager().OnStartChanges();
2625 if ( !pBar
->mpRow
->mpExpandedBar
)
2627 // save ratios only when there arent any bars expanded yet
2629 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2632 ratios
.Alloc( pBar
->mpRow
->mNotFixedBarsCnt
);
2634 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2638 if ( !pCur
->IsFixed() )
2641 ratios
[ ratios
.GetCount() - 1 ] = pCur
->mLenRatio
;
2644 pCur
= pCur
->mpNext
;
2648 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2652 pCur
->mLenRatio
= 0.0; // minimize the rest
2654 pCur
= pCur
->mpNext
;
2657 pBar
->mLenRatio
= 1.0; // 100%
2658 pBar
->mBounds
.width
= 0;
2660 pBar
->mpRow
->mpExpandedBar
= pBar
;
2662 mpLayout
->RecalcLayout( FALSE
);
2664 mpLayout
->GetUpdatesManager().OnFinishChanges();
2665 mpLayout
->GetUpdatesManager().UpdateNow();
2668 void cbDockPane::ContractBar( cbBarInfo
* pBar
)
2670 mpLayout
->GetUpdatesManager().OnStartChanges();
2672 // FIXME: What's the purpose of this???
2673 // double ratio = 1.0/ double( pBar->mpRow->mNotFixedBarsCnt );
2675 // restore ratios which were present before expansion
2677 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2679 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2685 if ( !pCur
->IsFixed() )
2687 pCur
->mLenRatio
= ratios
[i
];
2691 pCur
= pCur
->mpNext
;
2697 pBar
->mpRow
->mpExpandedBar
= NULL
;
2699 mpLayout
->RecalcLayout( FALSE
);
2701 mpLayout
->GetUpdatesManager().OnFinishChanges();
2702 mpLayout
->GetUpdatesManager().UpdateNow();
2705 void cbDockPane::InitLinksForRow( cbRowInfo
* pRow
)
2707 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2709 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2715 bar
.mpPrev
= pRow
->mBars
[i
-1];
2717 if ( i
== pRow
->mBars
.Count() - 1 )
2721 bar
.mpNext
= pRow
->mBars
[i
+1];
2725 void cbDockPane::InitLinksForRows()
2727 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2729 cbRowInfo
& row
= *mRows
[i
];
2735 row
.mpPrev
= mRows
[i
-1];
2737 if ( i
== mRows
.Count() - 1 )
2741 row
.mpNext
= mRows
[i
+1];
2745 void cbDockPane::DoInsertBar( cbBarInfo
* pBar
, int rowNo
)
2747 cbRowInfo
* pRow
= NULL
;
2749 if ( rowNo
== -1 || rowNo
>= (int)mRows
.Count() )
2751 pRow
= new cbRowInfo();
2753 if ( rowNo
== -1 && mRows
.Count() )
2755 mRows
.Insert( pRow
, 0 );
2763 pRow
= mRows
[rowNo
];
2765 if ( mProps
.mNonDestructFirctionOn
== TRUE
)
2767 // store original shape of the row (before the bar is inserted)
2771 GetRowShapeData( mpStoredRow
, &mRowShapeData
);
2775 if ( pRow
->mBars
.Count() )
2777 pRow
->mpExpandedBar
= NULL
;
2779 cbInsertBarEvent
insEvt( pBar
, pRow
, this );
2781 mpLayout
->FirePluginEvent( insEvt
);
2783 mpLayout
->GetUpdatesManager().OnRowWillChange( pRow
, this );
2786 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
, const wxRect
& atRect
)
2788 wxRect rect
= atRect
;
2789 FrameToPane( &rect
);
2791 pBarInfo
->mBounds
.x
= rect
.x
;
2792 pBarInfo
->mBounds
.width
= rect
.width
;
2793 pBarInfo
->mBounds
.height
= rect
.height
;
2795 int row
= GetRowAt( rect
.y
, rect
.y
+ rect
.height
);
2797 DoInsertBar( pBarInfo
, row
);
2800 void cbDockPane::InsertBar( cbBarInfo
* pBar
, cbRowInfo
* pIntoRow
)
2802 cbInsertBarEvent
insEvt( pBar
, pIntoRow
, this );
2804 mpLayout
->FirePluginEvent( insEvt
);
2806 mpLayout
->GetUpdatesManager().OnRowWillChange( pIntoRow
, this );
2809 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
)
2811 // set transient properties
2813 pBarInfo
->mpRow
= NULL
;
2814 pBarInfo
->mHasLeftHandle
= FALSE
;
2815 pBarInfo
->mHasRightHandle
= FALSE
;
2816 pBarInfo
->mLenRatio
= 0.0;
2818 // set preferred bar dimensions, according to the state in which
2819 // the bar is being inserted
2821 pBarInfo
->mBounds
.width
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].x
;
2822 pBarInfo
->mBounds
.height
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].y
;
2824 DoInsertBar( pBarInfo
, pBarInfo
->mRowNo
);
2827 void cbDockPane::RemoveRow( cbRowInfo
* pRow
)
2829 // first, hide all bar-windows in the removed row
2830 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2832 if ( pRow
->mBars
[i
]->mpBarWnd
)
2834 pRow
->mBars
[i
]->mpBarWnd
->Show( FALSE
);
2836 mRows
.Remove( pRow
);
2838 pRow
->mUMgrData
.SetDirty(TRUE
);
2841 void cbDockPane::InsertRow( cbRowInfo
* pRow
, cbRowInfo
* pBeforeRow
)
2847 mRows
.Insert( pRow
, mRows
.Index( pBeforeRow
) );
2851 pRow
->mUMgrData
.SetDirty(TRUE
);
2853 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2855 pRow
->mBars
[i
]->mUMgrData
.SetDirty( TRUE
);
2857 SyncRowFlags( pRow
);
2860 void cbDockPane::SetPaneWidth(int width
)
2862 if ( IsHorizontal() )
2864 mPaneWidth
= width
- mLeftMargin
- mRightMargin
;
2866 mPaneWidth
= width
- mTopMargin
- mBottomMargin
;
2870 void cbDockPane::SetBoundsInParent( const wxRect
& rect
)
2873 mBoundsInParent
= rect
;
2875 // set pane dimensions in local coordinates
2877 if ( IsHorizontal() )
2879 mPaneWidth
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2880 mPaneHeight
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2884 mPaneWidth
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2885 mPaneHeight
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2888 // convert bounding rectangles of all pane items into parent frame's coordinates
2890 wxBarIterator
i( mRows
);
2892 wxRect noMarginsRect
= mBoundsInParent
;
2894 noMarginsRect
.x
+= mLeftMargin
;
2895 noMarginsRect
.y
+= mTopMargin
;
2896 noMarginsRect
.width
-= ( mLeftMargin
+ mRightMargin
);
2897 noMarginsRect
.height
-= ( mTopMargin
+ mBottomMargin
);
2899 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2901 if ( mBoundsInParent
.width
< 0 ||
2902 mBoundsInParent
.height
< 0 )
2904 hide_rect( mBoundsInParent
);
2906 if ( noMarginsRect
.width
< 0 ||
2907 noMarginsRect
.height
< 0 )
2909 hide_rect( noMarginsRect
);
2911 // calculate mBoundsInParent for each item in the pane
2915 cbBarInfo
& bar
= i
.BarInfo();
2917 cbRowInfo
* pRowInfo
= bar
.mpRow
;
2919 // set up row info, if this is first bar in the row
2921 if ( pRowInfo
&& bar
.mpPrev
== NULL
)
2923 pRowInfo
->mBoundsInParent
.y
= pRowInfo
->mRowY
;
2924 pRowInfo
->mBoundsInParent
.x
= 0;
2925 pRowInfo
->mBoundsInParent
.width
= mPaneWidth
;
2926 pRowInfo
->mBoundsInParent
.height
= pRowInfo
->mRowHeight
;
2928 PaneToFrame( &pRowInfo
->mBoundsInParent
);
2930 clip_rect_against_rect( pRowInfo
->mBoundsInParent
, noMarginsRect
);
2933 wxRect bounds
= bar
.mBounds
;
2935 // exclude dimensions of handles, when calculating
2936 // bar's bounds in parent (i.e. "visual bounds")
2938 if ( bar
.mHasLeftHandle
)
2940 bounds
.x
+= mProps
.mResizeHandleSize
;
2941 bounds
.width
-= mProps
.mResizeHandleSize
;
2944 if ( bar
.mHasRightHandle
)
2946 bounds
.width
-= mProps
.mResizeHandleSize
;
2948 PaneToFrame( &bounds
);
2950 clip_rect_against_rect( bounds
, noMarginsRect
);
2952 bar
.mBoundsInParent
= bounds
;
2956 bool cbDockPane::BarPresent( cbBarInfo
* pBar
)
2958 wxBarIterator
iter( mRows
);
2960 while( iter
.Next() )
2962 if ( &iter
.BarInfo() == pBar
) return TRUE
;
2967 cbRowInfo
* cbDockPane::GetRow( int row
)
2969 if ( row
>= (int)mRows
.Count() ) return NULL
;
2971 return mRows
[ row
];
2974 int cbDockPane::GetRowIndex( cbRowInfo
* pRow
)
2976 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2978 if ( mRows
[i
] == pRow
)
2982 int avoidCompilerWarning
= 0;
2983 wxASSERT(avoidCompilerWarning
); // DBG:: row should be present
2988 int cbDockPane::GetPaneHeight()
2990 // first, recalculate row heights and the Y-positions
2992 cbLayoutRowsEvent
evt( this );
2993 mpLayout
->FirePluginEvent( evt
);
2997 if ( IsHorizontal() )
2999 height
+= mTopMargin
+ mBottomMargin
;
3001 height
+= mLeftMargin
+ mRightMargin
;
3003 int count
= mRows
.Count();
3007 height
+= mRows
[count
-1]->mRowY
+ mRows
[count
-1]->mRowHeight
;
3012 int cbDockPane::GetAlignment()
3017 bool cbDockPane::MatchesMask( int paneMask
)
3021 // FIXME:: use array instead of switch()
3025 case FL_ALIGN_TOP
: thisMask
= FL_ALIGN_TOP_PANE
; break;
3026 case FL_ALIGN_BOTTOM
: thisMask
= FL_ALIGN_BOTTOM_PANE
;break;
3027 case FL_ALIGN_LEFT
: thisMask
= FL_ALIGN_LEFT_PANE
; break;
3028 case FL_ALIGN_RIGHT
: thisMask
= FL_ALIGN_RIGHT_PANE
; break;
3031 int avoidCompilerWarning
= 0;
3032 wxASSERT(avoidCompilerWarning
); // DBG:: bogus alignment type
3035 return ( thisMask
& paneMask
) != 0;
3038 void cbDockPane::RecalcLayout()
3040 // first, reposition rows and items vertically
3042 cbLayoutRowsEvent
evt( this );
3043 mpLayout
->FirePluginEvent( evt
);
3045 // then horizontally in each row
3047 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
3049 RecalcRowLayout( mRows
[i
] );
3052 int cbDockPane::GetDockingState()
3054 if ( mAlignment
== FL_ALIGN_TOP
||
3055 mAlignment
== FL_ALIGN_BOTTOM
)
3057 return wxCBAR_DOCKED_HORIZONTALLY
;
3060 return wxCBAR_DOCKED_VERTICALLY
;
3063 inline bool cbDockPane::HasPoint( const wxPoint
& pos
, int x
, int y
,
3064 int width
, int height
)
3066 return ( pos
.x
>= x
&&
3068 pos
.x
< x
+ width
&&
3069 pos
.y
< y
+ height
);
3072 int cbDockPane::HitTestPaneItems( const wxPoint
& pos
,
3080 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
3082 cbRowInfo
& row
= *mRows
[i
];
3086 // hit-test handles of the row, if present
3088 if ( row
.mHasUpperHandle
)
3090 if ( HasPoint( pos
, 0, row
.mRowY
,
3091 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3093 return CB_UPPER_ROW_HANDLE_HITTED
;
3096 if ( row
.mHasLowerHandle
)
3098 if ( HasPoint( pos
, 0, row
.mRowY
+ row
.mRowHeight
- mProps
.mResizeHandleSize
,
3099 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3101 return CB_LOWER_ROW_HANDLE_HITTED
;
3104 // hit-test bar handles and bar content
3106 for( size_t k
= 0; k
!= row
.mBars
.Count(); ++k
)
3108 cbBarInfo
& bar
= *row
.mBars
[k
];
3109 wxRect
& bounds
= bar
.mBounds
;
3113 if ( bar
.mHasLeftHandle
)
3115 if ( HasPoint( pos
, bounds
.x
, bounds
.y
,
3116 mProps
.mResizeHandleSize
, bounds
.height
) )
3118 return CB_LEFT_BAR_HANDLE_HITTED
;
3121 if ( bar
.mHasRightHandle
)
3123 if ( HasPoint( pos
, bounds
.x
+ bounds
.width
- mProps
.mResizeHandleSize
, bounds
.y
,
3124 mProps
.mResizeHandleSize
, bounds
.height
) )
3126 return CB_RIGHT_BAR_HANDLE_HITTED
;
3129 if ( HasPoint( pos
, bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
) )
3131 return CB_BAR_CONTENT_HITTED
;
3133 } // hit-test next bar
3137 return CB_NO_ITEMS_HITTED
;
3140 void cbDockPane::GetBarResizeRange( cbBarInfo
* pBar
, int* from
, int *till
,
3141 bool forLeftHandle
)
3143 cbBarInfo
* pGivenBar
= pBar
;
3147 // calc unavailable space from the left
3149 while( pBar
->mpPrev
)
3151 pBar
= pBar
->mpPrev
;
3153 if ( !pBar
->IsFixed() ) notFree
+= mProps
.mMinCBarDim
.x
;
3154 else notFree
+= pBar
->mBounds
.width
;
3163 // calc unavailable space from the right
3165 while( pBar
->mpNext
)
3167 pBar
= pBar
->mpNext
;
3169 if ( pBar
->mBounds
.x
>= mPaneWidth
) break;
3171 // treat not-fixed bars as minimized
3173 if ( !pBar
->IsFixed() )
3175 notFree
+= mProps
.mMinCBarDim
.x
;
3178 if ( pBar
->mBounds
.x
+ pBar
->mBounds
.width
>= mPaneWidth
)
3180 notFree
+= mPaneWidth
- pBar
->mBounds
.x
;
3184 notFree
+= pBar
->mBounds
.width
;
3189 *till
= mPaneWidth
- notFree
;
3191 // do not let resizing totally deform the bar itself
3193 if ( forLeftHandle
)
3195 (*till
) -= mProps
.mMinCBarDim
.x
;
3198 (*from
) += mProps
.mMinCBarDim
.x
;
3201 int cbDockPane::GetMinimalRowHeight( cbRowInfo
* pRow
)
3203 int height
= mProps
.mMinCBarDim
.y
;
3205 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3207 if ( pRow
->mBars
[i
]->IsFixed() )
3209 height
= wxMax( height
, pRow
->mBars
[i
]->mBounds
.height
);
3211 if ( pRow
->mHasUpperHandle
)
3213 height
+= mProps
.mResizeHandleSize
;
3215 if ( pRow
->mHasLowerHandle
)
3217 height
+= mProps
.mResizeHandleSize
;
3222 void cbDockPane::SetRowHeight( cbRowInfo
* pRow
, int newHeight
)
3224 if ( pRow
->mHasUpperHandle
)
3226 newHeight
-= mProps
.mResizeHandleSize
;
3228 if ( pRow
->mHasLowerHandle
)
3230 newHeight
-= mProps
.mResizeHandleSize
;
3232 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3234 if ( !pRow
->mBars
[i
]->IsFixed() )
3236 pRow
->mBars
[i
]->mBounds
.height
= newHeight
;
3239 void cbDockPane::GetRowResizeRange( cbRowInfo
* pRow
, int* from
, int* till
,
3240 bool forUpperHandle
)
3242 cbRowInfo
* pGivenRow
= pRow
;
3244 // calc unavailable space from above
3248 while( pRow
->mpPrev
)
3250 pRow
= pRow
->mpPrev
;
3252 notFree
+= GetMinimalRowHeight( pRow
);
3258 // allow accupy the client window space by resizing pane rows
3259 if ( mAlignment
== FL_ALIGN_BOTTOM
)
3261 *from
-= mpLayout
->GetClientHeight();
3263 if ( mAlignment
== FL_ALIGN_RIGHT
)
3265 *from
-= mpLayout
->GetClientWidth();
3267 // calc unavailable space from below
3273 while( pRow
->mpNext
)
3275 pRow
= pRow
->mpNext
;
3277 notFree
+= GetMinimalRowHeight( pRow
);
3281 *till
= mPaneHeight
- notFree
;
3283 // allow adjustinig pane space vs. client window space by resizing pane row heights
3285 if ( mAlignment
== FL_ALIGN_TOP
)
3287 *till
+= mpLayout
->GetClientHeight();
3289 if ( mAlignment
== FL_ALIGN_LEFT
)
3291 *till
+= mpLayout
->GetClientWidth();
3293 // do not let the resizing of the row totally squeeze the row itself
3295 cbRowInfo
& row
= *pGivenRow
;
3297 if ( forUpperHandle
)
3299 *till
= row
.mRowY
+ row
.mRowHeight
- GetMinimalRowHeight( pGivenRow
);
3301 if ( row
.mHasUpperHandle
)
3303 *till
-= mProps
.mResizeHandleSize
;
3307 *from
+= GetMinimalRowHeight( pGivenRow
);
3309 if ( row
.mHasLowerHandle
)
3311 *from
-= mProps
.mResizeHandleSize
;
3315 void cbDockPane::ResizeRow( cbRowInfo
* pRow
, int ofs
,
3316 bool forUpperHandle
)
3318 cbResizeRowEvent
evt( pRow
, ofs
, forUpperHandle
, this );
3320 mpLayout
->FirePluginEvent( evt
);
3323 void cbDockPane::ResizeBar( cbBarInfo
* pBar
, int ofs
,
3324 bool forLeftHandle
)
3326 pBar
->mpRow
->mpExpandedBar
= NULL
;
3328 mpLayout
->GetUpdatesManager().OnStartChanges();
3330 wxRect
& bounds
= pBar
->mBounds
;
3332 if ( forLeftHandle
)
3334 // do not allow bar width become less then minimal
3335 if ( bounds
.x
+ ofs
> bounds
.x
+ bounds
.width
- mProps
.mMinCBarDim
.x
)
3337 bounds
.width
= mProps
.mMinCBarDim
.x
;
3343 bounds
.width
-= ofs
;
3348 // move bar left if necessary
3349 if ( bounds
.width
+ ofs
< mProps
.mMinCBarDim
.x
)
3351 bounds
.x
= bounds
.x
+ bounds
.width
+ ofs
- mProps
.mMinCBarDim
.x
;
3352 bounds
.width
= mProps
.mMinCBarDim
.x
;
3355 // resize right border only
3356 bounds
.width
+= ofs
;
3360 cbRowInfo
* pToRow
= pBar
->mpRow
;
3362 this->RemoveBar( pBar
);
3364 InsertBar( pBar
, pToRow
);
3366 mpLayout
->RecalcLayout(FALSE
);
3368 mpLayout
->GetUpdatesManager().OnFinishChanges();
3369 mpLayout
->GetUpdatesManager().UpdateNow();
3373 /*** row/bar resizing related methods ***/
3375 void cbDockPane::DrawVertHandle( wxDC
& dc
, int x
, int y
, int height
)
3377 int lower
= y
+ height
;
3379 dc
.SetPen( mpLayout
->mLightPen
);
3380 dc
.DrawLine( x
,y
, x
, lower
);
3382 dc
.SetPen( mpLayout
->mGrayPen
);
3383 for( int i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3386 dc
.DrawLine( x
,y
, x
, lower
);
3389 dc
.SetPen( mpLayout
->mDarkPen
);
3391 dc
.DrawLine( x
,y
, x
, lower
);
3393 dc
.SetPen( mpLayout
->mBlackPen
);
3395 dc
.DrawLine( x
,y
, x
, lower
);
3398 void cbDockPane::DrawHorizHandle( wxDC
& dc
, int x
, int y
, int width
)
3400 int right
= x
+ width
;
3402 dc
.SetPen( mpLayout
->mLightPen
);
3403 dc
.DrawLine( x
,y
, right
, y
);
3405 dc
.SetPen( mpLayout
->mGrayPen
);
3407 for( int i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3410 dc
.DrawLine( x
,y
, right
, y
);
3413 dc
.SetPen( mpLayout
->mDarkPen
);
3414 dc
.DrawLine( x
,y
, right
, ++y
);
3416 dc
.SetPen( mpLayout
->mBlackPen
);
3417 dc
.DrawLine( x
,y
, right
, ++y
);
3420 cbBarInfo
* cbDockPane::GetBarInfoByWindow( wxWindow
* pBarWnd
)
3422 wxBarIterator
i( mRows
);
3426 if ( i
.BarInfo().mpBarWnd
== pBarWnd
)
3428 return &i
.BarInfo();
3433 void cbDockPane::GetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3435 pLst
->DeleteContents( TRUE
);
3438 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3440 cbBarInfo
& bar
= *pRow
->mBars
[i
];
3442 cbBarShapeData
* pData
= new cbBarShapeData();
3444 pLst
->Append( (wxObject
*)pData
);
3446 pData
->mBounds
= bar
.mBounds
;
3447 pData
->mLenRatio
= bar
.mLenRatio
;
3451 void cbDockPane::SetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3453 if ( pLst
->First() == NULL
) return;
3455 wxNode
* pData
= pLst
->First();
3457 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3459 wxASSERT( pData
); // DBG::
3461 cbBarInfo
& bar
= *pRow
->mBars
[i
];;
3463 cbBarShapeData
& data
= *((cbBarShapeData
*)pData
->Data());
3465 bar
.mBounds
= data
.mBounds
;
3466 bar
.mLenRatio
= data
.mLenRatio
;
3468 pData
= pData
->Next();
3472 /***** Implementation for class cbUpdatesManagerBase *****/
3474 IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase
, wxObject
)
3476 /***** Implementation for class cbPluginBase *****/
3478 IMPLEMENT_ABSTRACT_CLASS( cbPluginBase
, wxEvtHandler
)
3480 cbPluginBase::~cbPluginBase()
3485 bool cbPluginBase::ProcessEvent(wxEvent
& event
)
3487 if ( mPaneMask
== wxALL_PANES
)
3489 return wxEvtHandler::ProcessEvent( event
);
3491 // extract mask info. from received event
3493 cbPluginEvent
& evt
= *( (cbPluginEvent
*)&event
);
3495 if ( evt
.mpPane
== 0 &&
3496 mPaneMask
== wxALL_PANES
)
3498 return wxEvtHandler::ProcessEvent( event
);
3502 switch ( evt
.mpPane
->mAlignment
)
3504 case FL_ALIGN_TOP
: mask
= FL_ALIGN_TOP_PANE
; break;
3505 case FL_ALIGN_BOTTOM
: mask
= FL_ALIGN_BOTTOM_PANE
;break;
3506 case FL_ALIGN_LEFT
: mask
= FL_ALIGN_LEFT_PANE
; break;
3507 case FL_ALIGN_RIGHT
: mask
= FL_ALIGN_RIGHT_PANE
; break;
3510 // if event's pane maks matches the plugin's mask
3512 if ( mPaneMask
& mask
)
3514 return wxEvtHandler::ProcessEvent( event
);
3516 // otherwise pass to the next handler if present
3518 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event
) )