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();
1204 if ( this == mpFrame
->GetEventHandler() )
1206 mpFrame
->SetEventHandler( this->GetNextHandler() );
1210 wxEvtHandler
* pCur
= mpFrame
->GetEventHandler();
1217 pCur
= pCur
->GetNextHandler();
1220 // do not try to unhook ourselves if we're not hooked yet
1225 if ( GetPreviousHandler() )
1226 GetPreviousHandler()->SetNextHandler( GetNextHandler() );
1229 mpFrame
->PopEventHandler();
1233 if ( GetNextHandler() )
1234 GetNextHandler()->SetPreviousHandler( GetPreviousHandler() );
1236 SetNextHandler( NULL
);
1237 SetPreviousHandler( NULL
);
1241 void wxFrameLayout::HookUpToFrame()
1243 // unhook us first, we're already hooked up
1247 // put ourselves on top
1249 mpFrame
->PushEventHandler( this );
1252 cbDockPane
* wxFrameLayout::GetBarPane( cbBarInfo
* pBar
)
1254 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1256 if ( mPanes
[i
]->BarPresent( pBar
) ) return mPanes
[i
];
1261 void wxFrameLayout::CreateCursors()
1264 // FIXME:: The below code somehow doesn't work - cursors remain unchanged
1267 set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
1269 mpHorizCursor = new wxCursor( bits, 32, 16 );
1271 set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
1273 mpVertCursor = new wxCursor( bits, 32, 16 );
1276 // FOR NOW:: use standard ones
1278 mpHorizCursor
= new wxCursor(wxCURSOR_SIZEWE
);
1279 mpVertCursor
= new wxCursor(wxCURSOR_SIZENS
);
1280 mpNormalCursor
= new wxCursor(wxCURSOR_ARROW
);
1281 mpDragCursor
= new wxCursor(wxCURSOR_CROSS
);
1282 mpNECursor
= new wxCursor(wxCURSOR_NO_ENTRY
);
1284 mFloatingPosStep
.x
= 25;
1285 mFloatingPosStep
.y
= 25;
1287 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
1288 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
1291 bool wxFrameLayout::HitTestPane( cbDockPane
* pPane
, int x
, int y
)
1293 return rect_contains_point( pPane
->GetRealRect(), x
, y
);
1296 cbDockPane
* wxFrameLayout::HitTestPanes( const wxRect
& rect
,
1297 cbDockPane
* pCurPane
)
1299 // first, give the privilege to the current pane
1301 if ( pCurPane
&& rect_hits_rect( pCurPane
->GetRealRect(), rect
) )
1305 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1307 if ( pCurPane
!= mPanes
[i
] &&
1308 rect_hits_rect( mPanes
[i
]->GetRealRect(), rect
) )
1315 void wxFrameLayout::ForwardMouseEvent( wxMouseEvent
& event
,
1316 cbDockPane
* pToPane
,
1319 wxPoint
pos( event
.m_x
, event
.m_y
);
1320 pToPane
->FrameToPane( &pos
.x
, &pos
.y
);
1322 #if wxCHECK_VERSION(2,3,0)
1323 if ( eventType
== cbEVT_PL_LEFT_DOWN
)
1325 cbLeftDownEvent
evt( pos
, pToPane
);
1326 FirePluginEvent( evt
);
1328 else if ( eventType
== cbEVT_PL_LEFT_DCLICK
)
1330 cbLeftDClickEvent
evt( pos
, pToPane
);
1331 FirePluginEvent( evt
);
1333 else if ( eventType
== cbEVT_PL_LEFT_UP
)
1335 cbLeftUpEvent
evt( pos
, pToPane
);
1336 FirePluginEvent( evt
);
1338 else if ( eventType
== cbEVT_PL_RIGHT_DOWN
)
1340 cbRightDownEvent
evt( pos
, pToPane
);
1341 FirePluginEvent( evt
);
1343 else if ( eventType
== cbEVT_PL_RIGHT_UP
)
1345 cbRightUpEvent
evt( pos
, pToPane
);
1346 FirePluginEvent( evt
);
1348 else if ( eventType
== cbEVT_PL_MOTION
)
1350 cbMotionEvent
evt( pos
, pToPane
);
1351 FirePluginEvent( evt
);
1355 int avoidCompilerWarning
= 0;
1356 wxASSERT(avoidCompilerWarning
); // DBG::
1359 switch ( eventType
)
1361 case cbEVT_PL_LEFT_DOWN
: { cbLeftDownEvent
evt( pos
, pToPane
);
1362 FirePluginEvent( evt
); break;
1365 case cbEVT_PL_LEFT_DCLICK
:{ cbLeftDClickEvent
evt( pos
, pToPane
);
1366 FirePluginEvent( evt
); break;
1369 case cbEVT_PL_LEFT_UP
: { cbLeftUpEvent
evt( pos
, pToPane
);
1370 FirePluginEvent( evt
); break;
1373 case cbEVT_PL_RIGHT_DOWN
: { cbRightDownEvent
evt( pos
, pToPane
);
1374 FirePluginEvent( evt
); break;
1377 case cbEVT_PL_RIGHT_UP
: { cbRightUpEvent
evt( pos
, pToPane
);
1378 FirePluginEvent( evt
); break;
1381 case cbEVT_PL_MOTION
: { cbMotionEvent
evt( pos
, pToPane
);
1382 FirePluginEvent( evt
); break;
1385 default : wxASSERT(0); // DBG::
1387 #endif // #if wxCHECK_VERSION(2,3,0)
1388 } // wxFrameLayout::ForwardMouseEvent()
1391 void wxFrameLayout::RouteMouseEvent( wxMouseEvent
& event
, int pluginEvtType
)
1393 if ( mpPaneInFocus
)
1395 ForwardMouseEvent( event
, mpPaneInFocus
, pluginEvtType
);
1397 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1399 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1401 ForwardMouseEvent( event
, mPanes
[i
], pluginEvtType
);
1407 /*** event handlers ***/
1409 void wxFrameLayout::OnRButtonDown( wxMouseEvent
& event
)
1411 RouteMouseEvent( event
, cbEVT_PL_RIGHT_DOWN
);
1414 void wxFrameLayout::OnRButtonUp( wxMouseEvent
& event
)
1416 RouteMouseEvent( event
, cbEVT_PL_RIGHT_UP
);
1419 void wxFrameLayout::OnLButtonDown( wxMouseEvent
& event
)
1421 RouteMouseEvent( event
, cbEVT_PL_LEFT_DOWN
);
1424 void wxFrameLayout::OnLDblClick( wxMouseEvent
& event
)
1426 RouteMouseEvent( event
, cbEVT_PL_LEFT_DCLICK
);
1429 void wxFrameLayout::OnLButtonUp( wxMouseEvent
& event
)
1431 RouteMouseEvent( event
, cbEVT_PL_LEFT_UP
);
1434 void wxFrameLayout::OnMouseMove( wxMouseEvent
& event
)
1436 if ( mpPaneInFocus
)
1438 ForwardMouseEvent( event
, mpPaneInFocus
, cbEVT_PL_MOTION
);
1440 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1442 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1444 if ( mpLRUPane
&& mpLRUPane
!= mPanes
[i
] )
1446 // simulate "mouse-leave" event
1447 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1450 ForwardMouseEvent( event
, mPanes
[i
], cbEVT_PL_MOTION
);
1452 mpLRUPane
= mPanes
[i
];
1459 // simulate "mouse-leave" event
1460 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1465 void wxFrameLayout::OnPaint( wxPaintEvent
& event
)
1467 if ( mRecalcPending
)
1469 RecalcLayout( TRUE
);
1471 wxPaintDC
dc(mpFrame
);
1473 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1475 wxRect
& rect
= mPanes
[i
]->mBoundsInParent
;
1477 dc
.SetClippingRegion( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1479 mPanes
[i
]->PaintPane(dc
);
1481 dc
.DestroyClippingRegion();
1487 void wxFrameLayout::OnEraseBackground( wxEraseEvent
& event
)
1492 void wxFrameLayout::OnIdle( wxIdleEvent
& event
)
1494 wxWindow
* focus
= wxWindow::FindFocus();
1496 if ( !focus
&& mCheckFocusWhenIdle
)
1498 wxMessageBox( "Hi, no more focus in this app!" );
1500 mCheckFocusWhenIdle
= FALSE
;
1501 //ShowFloatedWindows( FALSE );
1504 mCheckFocusWhenIdle
= FALSE
;
1510 void wxFrameLayout::OnKillFocus( wxFocusEvent
& event
)
1512 //wxMessageBox( "wxFrameLayoutGot Kill Focus!" );
1513 //ShowFloatedWindows( FALSE );
1516 void wxFrameLayout::OnSetFocus( wxFocusEvent
& event
)
1518 //ShowFloatedWindows( TRUE );
1521 void wxFrameLayout::OnActivate( wxActivateEvent
& event
)
1524 if ( event
.GetActive() == FALSE
)
1526 wxWindow
* focus
= wxWindow::FindFocus();
1528 if ( !focus
|| focus
== &GetParentFrame() )
1530 mCheckFocusWhenIdle
= TRUE
;
1534 wxMessageBox("Deactivated!" );
1541 void wxFrameLayout::GetPaneProperties( cbCommonPaneProperties
& props
, int alignment
)
1543 props
= mPanes
[alignment
]->mProps
;
1546 void wxFrameLayout::SetPaneProperties( const cbCommonPaneProperties
& props
, int paneMask
)
1548 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1550 if ( mPanes
[i
]->MatchesMask( paneMask
) )
1552 mPanes
[i
]->mProps
= props
;
1555 void wxFrameLayout::SetMargins( int top
, int bottom
, int left
, int right
,
1558 for( int i
= 0; i
!= MAX_PANES
; ++i
)
1560 cbDockPane
& pane
= *mPanes
[i
];
1562 if ( pane
.MatchesMask( paneMask
) )
1564 pane
.mTopMargin
= top
;
1565 pane
.mBottomMargin
= bottom
;
1566 pane
.mLeftMargin
= left
;
1567 pane
.mRightMargin
= right
;
1572 void wxFrameLayout::SetPaneBackground( const wxColour
& colour
)
1574 mBorderPen
.SetColour( colour
);
1577 void wxFrameLayout::RefreshNow( bool recalcLayout
)
1579 if ( recalcLayout
) RecalcLayout( TRUE
);
1581 if ( mpFrame
) mpFrame
->Refresh();
1584 /*** plugin-related methods ***/
1586 void wxFrameLayout::FirePluginEvent( cbPluginEvent
& event
)
1588 // check state of input capture, before processing the event
1590 if ( mpCaputesInput
)
1592 bool isInputEvt
= TRUE
;
1593 #if wxCHECK_VERSION(2,3,0)
1594 if ( event
.m_eventType
!= cbEVT_PL_LEFT_DOWN
&&
1595 event
.m_eventType
!= cbEVT_PL_LEFT_UP
&&
1596 event
.m_eventType
!= cbEVT_PL_RIGHT_DOWN
&&
1597 event
.m_eventType
!= cbEVT_PL_RIGHT_UP
&&
1598 event
.m_eventType
!= cbEVT_PL_MOTION
)
1601 switch ( event
.m_eventType
)
1603 case cbEVT_PL_LEFT_DOWN
: break;
1604 case cbEVT_PL_LEFT_UP
: break;
1605 case cbEVT_PL_RIGHT_DOWN
: break;
1606 case cbEVT_PL_RIGHT_UP
: break;
1607 case cbEVT_PL_MOTION
: break;
1609 default : isInputEvt
= FALSE
; break;
1611 #endif // #if wxCHECK_VERSION(2,3,0)
1615 mpCaputesInput
->ProcessEvent( event
);
1620 GetTopPlugin().ProcessEvent( event
);
1623 void wxFrameLayout::CaptureEventsForPlugin ( cbPluginBase
* pPlugin
)
1625 // cannot capture events for more than one plugin at a time
1626 wxASSERT( mpCaputesInput
== NULL
);
1628 mpCaputesInput
= pPlugin
;
1632 void wxFrameLayout::ReleaseEventsFromPlugin( cbPluginBase
* pPlugin
)
1634 // events should be captured first
1635 wxASSERT( mpCaputesInput
!= NULL
);
1637 mpCaputesInput
= NULL
;
1640 void wxFrameLayout::CaptureEventsForPane( cbDockPane
* toPane
)
1642 // cannot capture events twice (without releasing)
1643 wxASSERT( mpPaneInFocus
== NULL
);
1645 mpFrame
->CaptureMouse();
1647 mpPaneInFocus
= toPane
;
1650 void wxFrameLayout::ReleaseEventsFromPane( cbDockPane
* fromPane
)
1652 // cannot release events without capturing them
1653 wxASSERT( mpPaneInFocus
!= NULL
);
1655 mpFrame
->ReleaseMouse();
1657 mpPaneInFocus
= NULL
;
1660 cbPluginBase
& wxFrameLayout::GetTopPlugin()
1664 PushDefaultPlugins(); // automatic configuration
1666 return *mpTopPlugin
;
1669 void wxFrameLayout::SetTopPlugin( cbPluginBase
* pPlugin
)
1671 mpTopPlugin
= pPlugin
;
1674 bool wxFrameLayout::HasTopPlugin()
1676 return ( mpTopPlugin
!= NULL
);
1679 void wxFrameLayout::PushPlugin( cbPluginBase
* pPlugin
)
1683 mpTopPlugin
= pPlugin
;
1686 pPlugin
->SetNextHandler( mpTopPlugin
);
1688 mpTopPlugin
->SetPreviousHandler( pPlugin
);
1690 mpTopPlugin
= pPlugin
;
1693 mpTopPlugin
->OnInitPlugin(); // notification
1696 void wxFrameLayout::PopPlugin()
1698 wxASSERT( mpTopPlugin
); // DBG:: at least one plugin should be present
1700 cbPluginBase
* pPopped
= mpTopPlugin
;
1702 mpTopPlugin
= (cbPluginBase
*)mpTopPlugin
->GetNextHandler();
1707 void wxFrameLayout::PopAllPlugins()
1709 while( mpTopPlugin
) PopPlugin();
1712 void wxFrameLayout::PushDefaultPlugins()
1714 // FIXME:: to much of the stuff for the default...
1716 AddPlugin( CLASSINFO( cbRowLayoutPlugin
) );
1717 AddPlugin( CLASSINFO( cbBarDragPlugin
) );
1718 AddPlugin( CLASSINFO( cbPaneDrawPlugin
) );
1721 void wxFrameLayout::AddPlugin( wxClassInfo
* pPlInfo
, int paneMask
)
1723 if ( FindPlugin ( pPlInfo
) ) return; // same type of plugin cannot be added twice
1725 cbPluginBase
* pObj
= (cbPluginBase
*)pPlInfo
->CreateObject();
1727 wxASSERT(pObj
); // DBG:: plugin's class should be dynamic
1729 pObj
->mPaneMask
= paneMask
;
1730 pObj
->mpLayout
= this;
1735 void wxFrameLayout::AddPluginBefore( wxClassInfo
* pNextPlInfo
, wxClassInfo
* pPlInfo
,
1738 wxASSERT( pNextPlInfo
!= pPlInfo
); // DBG:: no sence
1740 cbPluginBase
* pNextPl
= FindPlugin( pNextPlInfo
);
1744 AddPlugin( pPlInfo
, paneMask
);
1749 // remove existing one if present
1751 cbPluginBase
* pExistingPl
= FindPlugin( pPlInfo
);
1753 if ( pExistingPl
) RemovePlugin( pPlInfo
);
1755 // create an instance
1757 cbPluginBase
* pNewPl
= (cbPluginBase
*)pPlInfo
->CreateObject();
1759 wxASSERT(pNewPl
); // DBG:: plugin's class should be dynamic
1761 // insert it to the chain
1763 if ( pNextPl
->GetPreviousHandler() )
1765 pNextPl
->GetPreviousHandler()->SetNextHandler( pNewPl
);
1767 mpTopPlugin
= pNewPl
;
1769 pNewPl
->SetNextHandler( pNextPl
);
1771 pNewPl
->SetPreviousHandler( pNextPl
->GetPreviousHandler() );
1773 pNextPl
->SetPreviousHandler( pNewPl
);
1777 pNewPl
->mPaneMask
= paneMask
;
1778 pNewPl
->mpLayout
= this;
1780 pNewPl
->OnInitPlugin();
1783 void wxFrameLayout::RemovePlugin( wxClassInfo
* pPlInfo
)
1785 cbPluginBase
* pPlugin
= FindPlugin( pPlInfo
);
1787 if ( !pPlugin
) return; // it's OK to remove not-existing plugin ;-)
1789 if ( pPlugin
->GetPreviousHandler() == NULL
)
1791 mpTopPlugin
= (cbPluginBase
*)pPlugin
->GetNextHandler();
1796 cbPluginBase
* wxFrameLayout::FindPlugin( wxClassInfo
* pPlInfo
)
1798 cbPluginBase
*pCur
= mpTopPlugin
;
1802 // NOTE:: it might appear useful matching plugin
1803 // classes "polymorphically":
1805 if ( pCur
->GetClassInfo()->IsKindOf( pPlInfo
) )
1809 pCur
= (cbPluginBase
*)pCur
->GetNextHandler();
1815 /***** Implementation for class cbUpdateMgrData *****/
1817 IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData
, wxObject
)
1819 cbUpdateMgrData::cbUpdateMgrData()
1821 : mPrevBounds( -1,-1,0,0 ),
1822 mIsDirty( TRUE
) // inidicate initial change
1825 void cbUpdateMgrData::StoreItemState( const wxRect
& boundsInParent
)
1827 mPrevBounds
= boundsInParent
;
1830 void cbUpdateMgrData::SetDirty( bool isDirty
)
1835 void cbUpdateMgrData::SetCustomData( wxObject
* pCustomData
)
1837 mpCustomData
= pCustomData
;
1840 /***** Implementation for class cbDockPane *****/
1842 void wxBarIterator::Reset()
1844 mpRow
= ( mpRows
->Count() ) ? (*mpRows
)[0] : NULL
;
1848 wxBarIterator::wxBarIterator( RowArrayT
& rows
)
1857 bool wxBarIterator::Next()
1862 mpBar
= mpBar
->mpNext
;
1865 if ( mpRow
->mBars
.GetCount() == 0 )
1870 mpBar
= mpRow
->mBars
[0];
1875 // skip to the next row
1877 mpRow
= mpRow
->mpNext
;
1881 mpBar
= mpRow
->mBars
[0];
1892 cbBarInfo
& wxBarIterator::BarInfo()
1897 cbRowInfo
& wxBarIterator::RowInfo()
1902 /***** Implementation for class cbBarDimHandlerBase *****/
1904 IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase
, wxObject
)
1906 cbBarDimHandlerBase::cbBarDimHandlerBase()
1910 void cbBarDimHandlerBase::AddRef()
1915 void cbBarDimHandlerBase::RemoveRef()
1917 if ( --mRefCount
<= 0 ) delete this;
1920 /***** Implementation for class cbDimInfo *****/
1922 IMPLEMENT_DYNAMIC_CLASS( cbDimInfo
, wxObject
)
1924 cbDimInfo::cbDimInfo()
1932 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1937 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1941 cbDimInfo::cbDimInfo( cbBarDimHandlerBase
* pDimHandler
,
1946 mIsFixed ( isFixed
),
1948 mpHandler( pDimHandler
)
1952 // int vtad = *((int*)mpHandler);
1953 mpHandler
->AddRef();
1956 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1961 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1965 cbDimInfo::cbDimInfo( int dh_x
, int dh_y
,
1973 cbBarDimHandlerBase
* pDimHandler
1975 : mVertGap ( vertGap
),
1976 mHorizGap ( horizGap
),
1977 mIsFixed ( isFixed
),
1978 mpHandler( pDimHandler
)
1982 // int vtad = *((int*)mpHandler);
1983 mpHandler
->AddRef();
1986 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= dh_x
;
1987 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= dh_y
;
1988 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= dv_x
;
1989 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= dv_y
;
1990 mSizes
[wxCBAR_FLOATING
].x
= f_x
;
1991 mSizes
[wxCBAR_FLOATING
].y
= f_y
;
1993 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1994 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1997 cbDimInfo::cbDimInfo( int x
, int y
,
1998 bool isFixed
, int gap
,
1999 cbBarDimHandlerBase
* pDimHandler
)
2002 mIsFixed ( isFixed
),
2003 mpHandler( pDimHandler
)
2007 // int vtad = *((int*)mpHandler);
2008 mpHandler
->AddRef();
2011 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= x
;
2012 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= y
;
2013 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= x
;
2014 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= y
;
2015 mSizes
[wxCBAR_FLOATING
].x
= x
;
2016 mSizes
[wxCBAR_FLOATING
].y
= y
;
2018 for( size_t i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2019 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
2022 cbDimInfo::~cbDimInfo()
2026 mpHandler
->RemoveRef();
2029 const cbDimInfo
& cbDimInfo::operator=( const cbDimInfo
& other
)
2031 if ( this == &other
) return *this;
2033 for( int i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2035 mSizes
[i
] = other
.mSizes
[i
];
2037 mIsFixed
= other
.mIsFixed
;
2038 mpHandler
= other
.mpHandler
;
2040 mVertGap
= other
.mVertGap
;
2041 mHorizGap
= other
.mHorizGap
;
2045 mpHandler
->AddRef();
2050 /***** Implementation for structure cbCommonPaneProperties *****/
2052 IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties
, wxObject
)
2054 cbCommonPaneProperties::cbCommonPaneProperties(void)
2056 : mRealTimeUpdatesOn ( TRUE
),
2057 mOutOfPaneDragOn ( TRUE
),
2058 mExactDockPredictionOn( FALSE
),
2059 mNonDestructFirctionOn( FALSE
),
2060 mShow3DPaneBorderOn ( TRUE
),
2061 mBarFloatingOn ( FALSE
),
2062 mRowProportionsOn ( FALSE
),
2063 mColProportionsOn ( TRUE
),
2064 mBarCollapseIconsOn ( FALSE
),
2065 mBarDragHintsOn ( FALSE
),
2067 mMinCBarDim( 16, 16 ),
2068 mResizeHandleSize( 4 )
2071 /***** Implementation for class cbRowInfo *****/
2073 IMPLEMENT_DYNAMIC_CLASS( cbRowInfo
, wxObject
)
2075 cbRowInfo::cbRowInfo(void)
2077 : mNotFixedBarsCnt( FALSE
),
2080 mpExpandedBar ( NULL
)
2083 cbRowInfo::~cbRowInfo()
2085 // nothing! all bars are removed using global bar
2086 // list in wxFrameLayout class
2089 /***** Implementation for class cbBarInfo *****/
2091 IMPLEMENT_DYNAMIC_CLASS( cbBarInfo
, wxObject
)
2093 cbBarInfo::cbBarInfo(void)
2101 cbBarInfo::~cbBarInfo()
2106 /***** Implementation for class cbDockPane *****/
2108 IMPLEMENT_DYNAMIC_CLASS( cbDockPane
, wxObject
)
2110 // FIXME:: how to eliminate these cut&pasted constructors?
2112 cbDockPane::cbDockPane(void)
2113 : mLeftMargin ( 1 ),
2117 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2118 // since the real dimensions of the pane may not
2119 // be known, while inserting bars initially
2120 mPaneHeight( 32768 ),
2126 cbDockPane::cbDockPane( int alignment
, wxFrameLayout
* pPanel
)
2128 : mLeftMargin ( 1 ),
2132 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2133 // since the real dimensions of the pane may not
2134 // be known, while inserting bars initially
2135 mPaneHeight( 32768 ),
2136 mAlignment ( alignment
),
2137 mpLayout ( pPanel
),
2141 cbDockPane::~cbDockPane()
2143 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2147 mRowShapeData
.DeleteContents( TRUE
);
2149 // NOTE:: control bar infromation structures are cleaned-up
2150 // in wxFrameLayout's destructor, using global control-bar list
2153 void cbDockPane::SetMargins( int top
, int bottom
, int left
, int right
)
2156 mBottomMargin
= bottom
;
2158 mRightMargin
= right
;
2161 /*** helpers of cbDockPane ***/
2163 void cbDockPane::PaintBarDecorations( cbBarInfo
* pBar
, wxDC
& dc
)
2165 cbDrawBarDecorEvent
evt( pBar
, dc
, this );
2167 mpLayout
->FirePluginEvent( evt
);
2170 void cbDockPane::PaintBarHandles( cbBarInfo
* pBar
, wxDC
& dc
)
2172 cbDrawBarHandlesEvent
evt( pBar
, dc
, this );
2174 mpLayout
->FirePluginEvent( evt
);
2177 void cbDockPane::PaintBar( cbBarInfo
* pBar
, wxDC
& dc
)
2179 PaintBarDecorations( pBar
, dc
);
2180 PaintBarHandles( pBar
, dc
);
2183 void cbDockPane::PaintRowHandles( cbRowInfo
* pRow
, wxDC
& dc
)
2185 cbDrawRowHandlesEvent
evt( pRow
, dc
, this );
2187 mpLayout
->FirePluginEvent( evt
);
2189 cbDrawRowDecorEvent
evt1( pRow
, dc
, this );
2191 mpLayout
->FirePluginEvent( evt1
);
2194 void cbDockPane::PaintRowBackground ( cbRowInfo
* pRow
, wxDC
& dc
)
2196 cbDrawRowBkGroundEvent
evt( pRow
, dc
, this );
2198 mpLayout
->FirePluginEvent( evt
);
2201 void cbDockPane::PaintRowDecorations( cbRowInfo
* pRow
, wxDC
& dc
)
2205 // decorations first
2206 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2208 PaintBarDecorations( pRow
->mBars
[i
], dc
);
2210 // then handles if present
2211 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2213 PaintBarHandles( pRow
->mBars
[i
], dc
);
2216 void cbDockPane::PaintRow( cbRowInfo
* pRow
, wxDC
& dc
)
2218 PaintRowBackground ( pRow
, dc
);
2219 PaintRowDecorations( pRow
, dc
);
2220 PaintRowHandles ( pRow
, dc
);
2223 void cbDockPane::PaintPaneBackground( wxDC
& dc
)
2225 cbDrawPaneBkGroundEvent
evt( dc
, this );
2227 mpLayout
->FirePluginEvent( evt
);
2230 void cbDockPane::PaintPaneDecorations( wxDC
& dc
)
2232 cbDrawPaneDecorEvent
evt( dc
, this );
2234 mpLayout
->FirePluginEvent( evt
);
2237 void cbDockPane::PaintPane( wxDC
& dc
)
2239 PaintPaneBackground( dc
);
2243 // first decorations
2244 for( i
= 0; i
!= mRows
.Count(); ++i
)
2246 PaintRowBackground( mRows
[i
], dc
);
2247 PaintRowDecorations( mRows
[i
], dc
);
2251 for( i
= 0; i
!= mRows
.Count(); ++i
)
2253 PaintRowHandles( mRows
[i
], dc
);
2256 PaintPaneDecorations( dc
);
2259 void cbDockPane::SizeBar( cbBarInfo
* pBar
)
2261 cbSizeBarWndEvent
evt( pBar
, this );
2263 mpLayout
->FirePluginEvent( evt
);
2267 void cbDockPane::SizeRowObjects( cbRowInfo
* pRow
)
2269 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2271 SizeBar( pRow
->mBars
[i
] );
2274 void cbDockPane::SizePaneObjects()
2276 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2278 SizeRowObjects( mRows
[i
] );
2281 wxDC
* cbDockPane::StartDrawInArea( const wxRect
& area
)
2285 cbStartDrawInAreaEvent
evt( area
, &pDc
, this );
2287 mpLayout
->FirePluginEvent( evt
);
2292 void cbDockPane::FinishDrawInArea( const wxRect
& area
)
2294 cbFinishDrawInAreaEvent
evt( area
, this );
2296 mpLayout
->FirePluginEvent( evt
);
2299 bool cbDockPane::IsFixedSize( cbBarInfo
* pInfo
)
2301 return ( pInfo
->mDimInfo
.mIsFixed
);
2304 int cbDockPane::GetNotFixedBarsCount( cbRowInfo
* pRow
)
2308 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2310 if ( !pRow
->mBars
[i
]->IsFixed() ) ++cnt
;
2315 void cbDockPane::RemoveBar( cbBarInfo
* pBar
)
2317 bool needsRestoring
= mProps
.mNonDestructFirctionOn
&&
2318 mpStoredRow
== pBar
->mpRow
;
2320 cbRemoveBarEvent
evt( pBar
, this );
2322 mpLayout
->FirePluginEvent( evt
);
2324 if ( needsRestoring
)
2326 SetRowShapeData( mpStoredRow
, &mRowShapeData
);
2332 void cbDockPane::SyncRowFlags( cbRowInfo
* pRow
)
2334 // setup mHasOnlyFixedBars flag for the row information
2335 pRow
->mHasOnlyFixedBars
= TRUE
;
2337 pRow
->mNotFixedBarsCnt
= 0;
2339 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2341 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2345 if ( !bar
.IsFixed() )
2347 pRow
->mHasOnlyFixedBars
= FALSE
;
2348 ++pRow
->mNotFixedBarsCnt
;
2353 void cbDockPane::FrameToPane( int* x
, int* y
)
2358 if ( mAlignment
== FL_ALIGN_TOP
||
2359 mAlignment
== FL_ALIGN_BOTTOM
2362 *x
-= mBoundsInParent
.x
;
2363 *y
-= mBoundsInParent
.y
;
2367 int rx
= *x
, ry
= *y
;
2369 *x
= ry
- mBoundsInParent
.y
;
2371 *y
= rx
- mBoundsInParent
.x
;
2375 void cbDockPane::PaneToFrame( int* x
, int* y
)
2377 if ( mAlignment
== FL_ALIGN_TOP
||
2378 mAlignment
== FL_ALIGN_BOTTOM
2381 *x
+= mBoundsInParent
.x
;
2382 *y
+= mBoundsInParent
.y
;
2386 int rx
= *x
, ry
= *y
;
2388 *x
= ry
+ mBoundsInParent
.x
;
2390 *y
= mBoundsInParent
.y
+ rx
;
2397 void cbDockPane::FrameToPane( wxRect
* pRect
)
2399 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2400 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2401 pRect
->y
+ pRect
->height
);
2403 FrameToPane( &upperLeft
.x
, &upperLeft
.y
);
2404 FrameToPane( &lowerRight
.x
, &lowerRight
.y
);
2406 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2407 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2409 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2410 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2413 void cbDockPane::PaneToFrame( wxRect
* pRect
)
2415 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2416 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2417 pRect
->y
+ pRect
->height
);
2419 PaneToFrame( &upperLeft
.x
, &upperLeft
.y
);
2420 PaneToFrame( &lowerRight
.x
, &lowerRight
.y
);
2422 //wxRect newRect = wxRect( upperLeft, lowerRight );
2424 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2425 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2427 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2428 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2431 int cbDockPane::GetRowAt( int paneY
)
2433 if ( paneY
< 0 ) return -1;
2439 for( ; i
!= mRows
.Count(); ++i
)
2441 int rowHeight
= mRows
[i
]->mRowHeight
;
2443 int third
= rowHeight
/3;
2445 if ( paneY
>= curY
&& paneY
< curY
+ third
)
2448 if ( paneY
>= curY
+ third
&& paneY
< curY
+ rowHeight
- third
)
2457 int cbDockPane::GetRowAt( int upperY
, int lowerY
)
2461 int range = lowerY - upperY;
2462 int oneThird = range / 3;
2464 wxNode* pRow = mRows.First();
2468 if ( lowerY <= 0 ) return -1;
2472 int rowHeight = GetRowHeight( (wxList*)pRow->Data() );
2474 if ( upperY >= curY &&
2475 lowerY < curY ) return row;
2477 if ( upperY <= curY &&
2479 curY - upperY >= oneThird ) return row-1;
2481 if ( ( upperY < curY + rowHeight &&
2482 lowerY >= curY + rowHeight &&
2483 curY + rowHeight - lowerY >= oneThird )
2487 if ( lowerY <= curY + rowHeight ) return row;
2491 pRow = pRow->Next();
2495 int mid
= upperY
+ (lowerY
- upperY
)/2;
2497 if ( mid
< 0 ) return -1;
2502 for( ; i
!= mRows
.Count(); ++i
)
2504 int rowHeight
= mRows
[i
]->mRowHeight
;
2506 if ( mid
>= curY
&& mid
< curY
+ rowHeight
) return i
;
2514 int cbDockPane::GetRowY( cbRowInfo
* pRow
)
2518 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2520 if ( mRows
[i
] == pRow
) break;
2522 curY
+= mRows
[i
]->mRowHeight
;
2528 bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo
* pRow
)
2530 while ( pRow
->mpPrev
)
2532 pRow
= pRow
->mpPrev
;
2534 if ( pRow
->mHasOnlyFixedBars
)
2542 bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo
* pRow
)
2544 while( pRow
->mpNext
)
2546 pRow
= pRow
->mpNext
;
2548 if ( pRow
->mHasOnlyFixedBars
)
2556 bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo
* pBar
)
2558 while( pBar
->mpPrev
)
2560 pBar
= pBar
->mpPrev
;
2562 if ( pBar
->IsFixed() )
2570 bool cbDockPane::HasNotFixedBarsRight( cbBarInfo
* pBar
)
2572 while( pBar
->mpNext
)
2574 pBar
= pBar
->mpNext
;
2576 if ( pBar
->IsFixed() )
2584 void cbDockPane::CalcLengthRatios( cbRowInfo
* pInRow
)
2590 // clac current-maximal-total-length of all maximized bars
2592 for( i
= 0; i
!= pInRow
->mBars
.GetCount(); ++i
)
2594 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2596 if ( !bar
.IsFixed() )
2598 totalWidth
+= bar
.mBounds
.width
;
2601 // set up persentages of occupied space for each maximized bar
2603 for( i
= 0; i
!= pInRow
->mBars
.Count(); ++i
)
2605 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2607 if ( !bar
.IsFixed() )
2609 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalWidth
);
2613 void cbDockPane::RecalcRowLayout( cbRowInfo
* pRow
)
2615 cbLayoutRowEvent
evt( pRow
, this );
2617 mpLayout
->FirePluginEvent( evt
);
2620 void cbDockPane::ExpandBar( cbBarInfo
* pBar
)
2622 mpLayout
->GetUpdatesManager().OnStartChanges();
2624 if ( !pBar
->mpRow
->mpExpandedBar
)
2626 // save ratios only when there arent any bars expanded yet
2628 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2631 ratios
.Alloc( pBar
->mpRow
->mNotFixedBarsCnt
);
2633 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2637 if ( !pCur
->IsFixed() )
2640 ratios
[ ratios
.GetCount() - 1 ] = pCur
->mLenRatio
;
2643 pCur
= pCur
->mpNext
;
2647 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2651 pCur
->mLenRatio
= 0.0; // minimize the rest
2653 pCur
= pCur
->mpNext
;
2656 pBar
->mLenRatio
= 1.0; // 100%
2657 pBar
->mBounds
.width
= 0;
2659 pBar
->mpRow
->mpExpandedBar
= pBar
;
2661 mpLayout
->RecalcLayout( FALSE
);
2663 mpLayout
->GetUpdatesManager().OnFinishChanges();
2664 mpLayout
->GetUpdatesManager().UpdateNow();
2667 void cbDockPane::ContractBar( cbBarInfo
* pBar
)
2669 mpLayout
->GetUpdatesManager().OnStartChanges();
2671 // FIXME: What's the purpose of this???
2672 // double ratio = 1.0/ double( pBar->mpRow->mNotFixedBarsCnt );
2674 // restore ratios which were present before expansion
2676 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2678 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2684 if ( !pCur
->IsFixed() )
2686 pCur
->mLenRatio
= ratios
[i
];
2690 pCur
= pCur
->mpNext
;
2696 pBar
->mpRow
->mpExpandedBar
= NULL
;
2698 mpLayout
->RecalcLayout( FALSE
);
2700 mpLayout
->GetUpdatesManager().OnFinishChanges();
2701 mpLayout
->GetUpdatesManager().UpdateNow();
2704 void cbDockPane::InitLinksForRow( cbRowInfo
* pRow
)
2706 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2708 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2714 bar
.mpPrev
= pRow
->mBars
[i
-1];
2716 if ( i
== pRow
->mBars
.Count() - 1 )
2720 bar
.mpNext
= pRow
->mBars
[i
+1];
2724 void cbDockPane::InitLinksForRows()
2726 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2728 cbRowInfo
& row
= *mRows
[i
];
2734 row
.mpPrev
= mRows
[i
-1];
2736 if ( i
== mRows
.Count() - 1 )
2740 row
.mpNext
= mRows
[i
+1];
2744 void cbDockPane::DoInsertBar( cbBarInfo
* pBar
, int rowNo
)
2746 cbRowInfo
* pRow
= NULL
;
2748 if ( rowNo
== -1 || rowNo
>= (int)mRows
.Count() )
2750 pRow
= new cbRowInfo();
2752 if ( rowNo
== -1 && mRows
.Count() )
2754 mRows
.Insert( pRow
, 0 );
2762 pRow
= mRows
[rowNo
];
2764 if ( mProps
.mNonDestructFirctionOn
== TRUE
)
2766 // store original shape of the row (before the bar is inserted)
2770 GetRowShapeData( mpStoredRow
, &mRowShapeData
);
2774 if ( pRow
->mBars
.Count() )
2776 pRow
->mpExpandedBar
= NULL
;
2778 cbInsertBarEvent
insEvt( pBar
, pRow
, this );
2780 mpLayout
->FirePluginEvent( insEvt
);
2782 mpLayout
->GetUpdatesManager().OnRowWillChange( pRow
, this );
2785 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
, const wxRect
& atRect
)
2787 wxRect rect
= atRect
;
2788 FrameToPane( &rect
);
2790 pBarInfo
->mBounds
.x
= rect
.x
;
2791 pBarInfo
->mBounds
.width
= rect
.width
;
2792 pBarInfo
->mBounds
.height
= rect
.height
;
2794 int row
= GetRowAt( rect
.y
, rect
.y
+ rect
.height
);
2796 DoInsertBar( pBarInfo
, row
);
2799 void cbDockPane::InsertBar( cbBarInfo
* pBar
, cbRowInfo
* pIntoRow
)
2801 cbInsertBarEvent
insEvt( pBar
, pIntoRow
, this );
2803 mpLayout
->FirePluginEvent( insEvt
);
2805 mpLayout
->GetUpdatesManager().OnRowWillChange( pIntoRow
, this );
2808 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
)
2810 // set transient properties
2812 pBarInfo
->mpRow
= NULL
;
2813 pBarInfo
->mHasLeftHandle
= FALSE
;
2814 pBarInfo
->mHasRightHandle
= FALSE
;
2815 pBarInfo
->mLenRatio
= 0.0;
2817 // set preferred bar dimensions, according to the state in which
2818 // the bar is being inserted
2820 pBarInfo
->mBounds
.width
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].x
;
2821 pBarInfo
->mBounds
.height
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].y
;
2823 DoInsertBar( pBarInfo
, pBarInfo
->mRowNo
);
2826 void cbDockPane::RemoveRow( cbRowInfo
* pRow
)
2828 // first, hide all bar-windows in the removed row
2829 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2831 if ( pRow
->mBars
[i
]->mpBarWnd
)
2833 pRow
->mBars
[i
]->mpBarWnd
->Show( FALSE
);
2835 mRows
.Remove( pRow
);
2837 pRow
->mUMgrData
.SetDirty(TRUE
);
2840 void cbDockPane::InsertRow( cbRowInfo
* pRow
, cbRowInfo
* pBeforeRow
)
2846 mRows
.Insert( pRow
, mRows
.Index( pBeforeRow
) );
2850 pRow
->mUMgrData
.SetDirty(TRUE
);
2852 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2854 pRow
->mBars
[i
]->mUMgrData
.SetDirty( TRUE
);
2856 SyncRowFlags( pRow
);
2859 void cbDockPane::SetPaneWidth(int width
)
2861 if ( IsHorizontal() )
2863 mPaneWidth
= width
- mLeftMargin
- mRightMargin
;
2865 mPaneWidth
= width
- mTopMargin
- mBottomMargin
;
2869 void cbDockPane::SetBoundsInParent( const wxRect
& rect
)
2872 mBoundsInParent
= rect
;
2874 // set pane dimensions in local coordinates
2876 if ( IsHorizontal() )
2878 mPaneWidth
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2879 mPaneHeight
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2883 mPaneWidth
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2884 mPaneHeight
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2887 // convert bounding rectangles of all pane items into parent frame's coordinates
2889 wxBarIterator
i( mRows
);
2891 wxRect noMarginsRect
= mBoundsInParent
;
2893 noMarginsRect
.x
+= mLeftMargin
;
2894 noMarginsRect
.y
+= mTopMargin
;
2895 noMarginsRect
.width
-= ( mLeftMargin
+ mRightMargin
);
2896 noMarginsRect
.height
-= ( mTopMargin
+ mBottomMargin
);
2898 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2900 if ( mBoundsInParent
.width
< 0 ||
2901 mBoundsInParent
.height
< 0 )
2903 hide_rect( mBoundsInParent
);
2905 if ( noMarginsRect
.width
< 0 ||
2906 noMarginsRect
.height
< 0 )
2908 hide_rect( noMarginsRect
);
2910 // calculate mBoundsInParent for each item in the pane
2914 cbBarInfo
& bar
= i
.BarInfo();
2916 cbRowInfo
* pRowInfo
= bar
.mpRow
;
2918 // set up row info, if this is first bar in the row
2920 if ( pRowInfo
&& bar
.mpPrev
== NULL
)
2922 pRowInfo
->mBoundsInParent
.y
= pRowInfo
->mRowY
;
2923 pRowInfo
->mBoundsInParent
.x
= 0;
2924 pRowInfo
->mBoundsInParent
.width
= mPaneWidth
;
2925 pRowInfo
->mBoundsInParent
.height
= pRowInfo
->mRowHeight
;
2927 PaneToFrame( &pRowInfo
->mBoundsInParent
);
2929 clip_rect_against_rect( pRowInfo
->mBoundsInParent
, noMarginsRect
);
2932 wxRect bounds
= bar
.mBounds
;
2934 // exclude dimensions of handles, when calculating
2935 // bar's bounds in parent (i.e. "visual bounds")
2937 if ( bar
.mHasLeftHandle
)
2939 bounds
.x
+= mProps
.mResizeHandleSize
;
2940 bounds
.width
-= mProps
.mResizeHandleSize
;
2943 if ( bar
.mHasRightHandle
)
2945 bounds
.width
-= mProps
.mResizeHandleSize
;
2947 PaneToFrame( &bounds
);
2949 clip_rect_against_rect( bounds
, noMarginsRect
);
2951 bar
.mBoundsInParent
= bounds
;
2955 bool cbDockPane::BarPresent( cbBarInfo
* pBar
)
2957 wxBarIterator
iter( mRows
);
2959 while( iter
.Next() )
2961 if ( &iter
.BarInfo() == pBar
) return TRUE
;
2966 cbRowInfo
* cbDockPane::GetRow( int row
)
2968 if ( row
>= (int)mRows
.Count() ) return NULL
;
2970 return mRows
[ row
];
2973 int cbDockPane::GetRowIndex( cbRowInfo
* pRow
)
2975 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
2977 if ( mRows
[i
] == pRow
)
2981 int avoidCompilerWarning
= 0;
2982 wxASSERT(avoidCompilerWarning
); // DBG:: row should be present
2987 int cbDockPane::GetPaneHeight()
2989 // first, recalculate row heights and the Y-positions
2991 cbLayoutRowsEvent
evt( this );
2992 mpLayout
->FirePluginEvent( evt
);
2996 if ( IsHorizontal() )
2998 height
+= mTopMargin
+ mBottomMargin
;
3000 height
+= mLeftMargin
+ mRightMargin
;
3002 int count
= mRows
.Count();
3006 height
+= mRows
[count
-1]->mRowY
+ mRows
[count
-1]->mRowHeight
;
3011 int cbDockPane::GetAlignment()
3016 bool cbDockPane::MatchesMask( int paneMask
)
3020 // FIXME:: use array instead of switch()
3024 case FL_ALIGN_TOP
: thisMask
= FL_ALIGN_TOP_PANE
; break;
3025 case FL_ALIGN_BOTTOM
: thisMask
= FL_ALIGN_BOTTOM_PANE
;break;
3026 case FL_ALIGN_LEFT
: thisMask
= FL_ALIGN_LEFT_PANE
; break;
3027 case FL_ALIGN_RIGHT
: thisMask
= FL_ALIGN_RIGHT_PANE
; break;
3030 int avoidCompilerWarning
= 0;
3031 wxASSERT(avoidCompilerWarning
); // DBG:: bogus alignment type
3034 return ( thisMask
& paneMask
) != 0;
3037 void cbDockPane::RecalcLayout()
3039 // first, reposition rows and items vertically
3041 cbLayoutRowsEvent
evt( this );
3042 mpLayout
->FirePluginEvent( evt
);
3044 // then horizontally in each row
3046 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
3048 RecalcRowLayout( mRows
[i
] );
3051 int cbDockPane::GetDockingState()
3053 if ( mAlignment
== FL_ALIGN_TOP
||
3054 mAlignment
== FL_ALIGN_BOTTOM
)
3056 return wxCBAR_DOCKED_HORIZONTALLY
;
3059 return wxCBAR_DOCKED_VERTICALLY
;
3062 inline bool cbDockPane::HasPoint( const wxPoint
& pos
, int x
, int y
,
3063 int width
, int height
)
3065 return ( pos
.x
>= x
&&
3067 pos
.x
< x
+ width
&&
3068 pos
.y
< y
+ height
);
3071 int cbDockPane::HitTestPaneItems( const wxPoint
& pos
,
3079 for( size_t i
= 0; i
!= mRows
.Count(); ++i
)
3081 cbRowInfo
& row
= *mRows
[i
];
3085 // hit-test handles of the row, if present
3087 if ( row
.mHasUpperHandle
)
3089 if ( HasPoint( pos
, 0, row
.mRowY
,
3090 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3092 return CB_UPPER_ROW_HANDLE_HITTED
;
3095 if ( row
.mHasLowerHandle
)
3097 if ( HasPoint( pos
, 0, row
.mRowY
+ row
.mRowHeight
- mProps
.mResizeHandleSize
,
3098 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3100 return CB_LOWER_ROW_HANDLE_HITTED
;
3103 // hit-test bar handles and bar content
3105 for( size_t k
= 0; k
!= row
.mBars
.Count(); ++k
)
3107 cbBarInfo
& bar
= *row
.mBars
[k
];
3108 wxRect
& bounds
= bar
.mBounds
;
3112 if ( bar
.mHasLeftHandle
)
3114 if ( HasPoint( pos
, bounds
.x
, bounds
.y
,
3115 mProps
.mResizeHandleSize
, bounds
.height
) )
3117 return CB_LEFT_BAR_HANDLE_HITTED
;
3120 if ( bar
.mHasRightHandle
)
3122 if ( HasPoint( pos
, bounds
.x
+ bounds
.width
- mProps
.mResizeHandleSize
, bounds
.y
,
3123 mProps
.mResizeHandleSize
, bounds
.height
) )
3125 return CB_RIGHT_BAR_HANDLE_HITTED
;
3128 if ( HasPoint( pos
, bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
) )
3130 return CB_BAR_CONTENT_HITTED
;
3132 } // hit-test next bar
3136 return CB_NO_ITEMS_HITTED
;
3139 void cbDockPane::GetBarResizeRange( cbBarInfo
* pBar
, int* from
, int *till
,
3140 bool forLeftHandle
)
3142 cbBarInfo
* pGivenBar
= pBar
;
3146 // calc unavailable space from the left
3148 while( pBar
->mpPrev
)
3150 pBar
= pBar
->mpPrev
;
3152 if ( !pBar
->IsFixed() ) notFree
+= mProps
.mMinCBarDim
.x
;
3153 else notFree
+= pBar
->mBounds
.width
;
3162 // calc unavailable space from the right
3164 while( pBar
->mpNext
)
3166 pBar
= pBar
->mpNext
;
3168 if ( pBar
->mBounds
.x
>= mPaneWidth
) break;
3170 // treat not-fixed bars as minimized
3172 if ( !pBar
->IsFixed() )
3174 notFree
+= mProps
.mMinCBarDim
.x
;
3177 if ( pBar
->mBounds
.x
+ pBar
->mBounds
.width
>= mPaneWidth
)
3179 notFree
+= mPaneWidth
- pBar
->mBounds
.x
;
3183 notFree
+= pBar
->mBounds
.width
;
3188 *till
= mPaneWidth
- notFree
;
3190 // do not let resizing totally deform the bar itself
3192 if ( forLeftHandle
)
3194 (*till
) -= mProps
.mMinCBarDim
.x
;
3197 (*from
) += mProps
.mMinCBarDim
.x
;
3200 int cbDockPane::GetMinimalRowHeight( cbRowInfo
* pRow
)
3202 int height
= mProps
.mMinCBarDim
.y
;
3204 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3206 if ( pRow
->mBars
[i
]->IsFixed() )
3208 height
= wxMax( height
, pRow
->mBars
[i
]->mBounds
.height
);
3210 if ( pRow
->mHasUpperHandle
)
3212 height
+= mProps
.mResizeHandleSize
;
3214 if ( pRow
->mHasLowerHandle
)
3216 height
+= mProps
.mResizeHandleSize
;
3221 void cbDockPane::SetRowHeight( cbRowInfo
* pRow
, int newHeight
)
3223 if ( pRow
->mHasUpperHandle
)
3225 newHeight
-= mProps
.mResizeHandleSize
;
3227 if ( pRow
->mHasLowerHandle
)
3229 newHeight
-= mProps
.mResizeHandleSize
;
3231 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3233 if ( !pRow
->mBars
[i
]->IsFixed() )
3235 pRow
->mBars
[i
]->mBounds
.height
= newHeight
;
3238 void cbDockPane::GetRowResizeRange( cbRowInfo
* pRow
, int* from
, int* till
,
3239 bool forUpperHandle
)
3241 cbRowInfo
* pGivenRow
= pRow
;
3243 // calc unavailable space from above
3247 while( pRow
->mpPrev
)
3249 pRow
= pRow
->mpPrev
;
3251 notFree
+= GetMinimalRowHeight( pRow
);
3257 // allow accupy the client window space by resizing pane rows
3258 if ( mAlignment
== FL_ALIGN_BOTTOM
)
3260 *from
-= mpLayout
->GetClientHeight();
3262 if ( mAlignment
== FL_ALIGN_RIGHT
)
3264 *from
-= mpLayout
->GetClientWidth();
3266 // calc unavailable space from below
3272 while( pRow
->mpNext
)
3274 pRow
= pRow
->mpNext
;
3276 notFree
+= GetMinimalRowHeight( pRow
);
3280 *till
= mPaneHeight
- notFree
;
3282 // allow adjustinig pane space vs. client window space by resizing pane row heights
3284 if ( mAlignment
== FL_ALIGN_TOP
)
3286 *till
+= mpLayout
->GetClientHeight();
3288 if ( mAlignment
== FL_ALIGN_LEFT
)
3290 *till
+= mpLayout
->GetClientWidth();
3292 // do not let the resizing of the row totally squeeze the row itself
3294 cbRowInfo
& row
= *pGivenRow
;
3296 if ( forUpperHandle
)
3298 *till
= row
.mRowY
+ row
.mRowHeight
- GetMinimalRowHeight( pGivenRow
);
3300 if ( row
.mHasUpperHandle
)
3302 *till
-= mProps
.mResizeHandleSize
;
3306 *from
+= GetMinimalRowHeight( pGivenRow
);
3308 if ( row
.mHasLowerHandle
)
3310 *from
-= mProps
.mResizeHandleSize
;
3314 void cbDockPane::ResizeRow( cbRowInfo
* pRow
, int ofs
,
3315 bool forUpperHandle
)
3317 cbResizeRowEvent
evt( pRow
, ofs
, forUpperHandle
, this );
3319 mpLayout
->FirePluginEvent( evt
);
3322 void cbDockPane::ResizeBar( cbBarInfo
* pBar
, int ofs
,
3323 bool forLeftHandle
)
3325 pBar
->mpRow
->mpExpandedBar
= NULL
;
3327 mpLayout
->GetUpdatesManager().OnStartChanges();
3329 wxRect
& bounds
= pBar
->mBounds
;
3331 if ( forLeftHandle
)
3333 // do not allow bar width become less then minimal
3334 if ( bounds
.x
+ ofs
> bounds
.x
+ bounds
.width
- mProps
.mMinCBarDim
.x
)
3336 bounds
.width
= mProps
.mMinCBarDim
.x
;
3342 bounds
.width
-= ofs
;
3347 // move bar left if necessary
3348 if ( bounds
.width
+ ofs
< mProps
.mMinCBarDim
.x
)
3350 bounds
.x
= bounds
.x
+ bounds
.width
+ ofs
- mProps
.mMinCBarDim
.x
;
3351 bounds
.width
= mProps
.mMinCBarDim
.x
;
3354 // resize right border only
3355 bounds
.width
+= ofs
;
3359 cbRowInfo
* pToRow
= pBar
->mpRow
;
3361 this->RemoveBar( pBar
);
3363 InsertBar( pBar
, pToRow
);
3365 mpLayout
->RecalcLayout(FALSE
);
3367 mpLayout
->GetUpdatesManager().OnFinishChanges();
3368 mpLayout
->GetUpdatesManager().UpdateNow();
3372 /*** row/bar resizing related methods ***/
3374 void cbDockPane::DrawVertHandle( wxDC
& dc
, int x
, int y
, int height
)
3376 int lower
= y
+ height
;
3378 dc
.SetPen( mpLayout
->mLightPen
);
3379 dc
.DrawLine( x
,y
, x
, lower
);
3381 dc
.SetPen( mpLayout
->mGrayPen
);
3382 for( int i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3385 dc
.DrawLine( x
,y
, x
, lower
);
3388 dc
.SetPen( mpLayout
->mDarkPen
);
3390 dc
.DrawLine( x
,y
, x
, lower
);
3392 dc
.SetPen( mpLayout
->mBlackPen
);
3394 dc
.DrawLine( x
,y
, x
, lower
);
3397 void cbDockPane::DrawHorizHandle( wxDC
& dc
, int x
, int y
, int width
)
3399 int right
= x
+ width
;
3401 dc
.SetPen( mpLayout
->mLightPen
);
3402 dc
.DrawLine( x
,y
, right
, y
);
3404 dc
.SetPen( mpLayout
->mGrayPen
);
3406 for( int i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3409 dc
.DrawLine( x
,y
, right
, y
);
3412 dc
.SetPen( mpLayout
->mDarkPen
);
3413 dc
.DrawLine( x
,y
, right
, ++y
);
3415 dc
.SetPen( mpLayout
->mBlackPen
);
3416 dc
.DrawLine( x
,y
, right
, ++y
);
3419 cbBarInfo
* cbDockPane::GetBarInfoByWindow( wxWindow
* pBarWnd
)
3421 wxBarIterator
i( mRows
);
3425 if ( i
.BarInfo().mpBarWnd
== pBarWnd
)
3427 return &i
.BarInfo();
3432 void cbDockPane::GetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3434 pLst
->DeleteContents( TRUE
);
3437 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3439 cbBarInfo
& bar
= *pRow
->mBars
[i
];
3441 cbBarShapeData
* pData
= new cbBarShapeData();
3443 pLst
->Append( (wxObject
*)pData
);
3445 pData
->mBounds
= bar
.mBounds
;
3446 pData
->mLenRatio
= bar
.mLenRatio
;
3450 void cbDockPane::SetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3452 if ( pLst
->First() == NULL
) return;
3454 wxNode
* pData
= pLst
->First();
3456 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3458 wxASSERT( pData
); // DBG::
3460 cbBarInfo
& bar
= *pRow
->mBars
[i
];;
3462 cbBarShapeData
& data
= *((cbBarShapeData
*)pData
->Data());
3464 bar
.mBounds
= data
.mBounds
;
3465 bar
.mLenRatio
= data
.mLenRatio
;
3467 pData
= pData
->Next();
3471 /***** Implementation for class cbUpdatesManagerBase *****/
3473 IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase
, wxObject
)
3475 /***** Implementation for class cbPluginBase *****/
3477 IMPLEMENT_ABSTRACT_CLASS( cbPluginBase
, wxEvtHandler
)
3479 cbPluginBase::~cbPluginBase()
3484 bool cbPluginBase::ProcessEvent(wxEvent
& event
)
3486 if ( mPaneMask
== wxALL_PANES
)
3488 return wxEvtHandler::ProcessEvent( event
);
3490 // extract mask info. from received event
3492 cbPluginEvent
& evt
= *( (cbPluginEvent
*)&event
);
3494 if ( evt
.mpPane
== 0 &&
3495 mPaneMask
== wxALL_PANES
)
3497 return wxEvtHandler::ProcessEvent( event
);
3501 switch ( evt
.mpPane
->mAlignment
)
3503 case FL_ALIGN_TOP
: mask
= FL_ALIGN_TOP_PANE
; break;
3504 case FL_ALIGN_BOTTOM
: mask
= FL_ALIGN_BOTTOM_PANE
;break;
3505 case FL_ALIGN_LEFT
: mask
= FL_ALIGN_LEFT_PANE
; break;
3506 case FL_ALIGN_RIGHT
: mask
= FL_ALIGN_RIGHT_PANE
; break;
3509 // if event's pane maks matches the plugin's mask
3511 if ( mPaneMask
& mask
)
3513 return wxEvtHandler::ProcessEvent( event
);
3515 // otherwise pass to the next handler if present
3517 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event
) )