1 /////////////////////////////////////////////////////////////////////////////
2 // Name: controlbar.cpp
3 // Purpose: Implementation for main controlbar classes.
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "controlbar.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
30 #include "wx/string.h"
31 #include "wx/utils.h" // import wxMin,wxMax macros
32 #include "wx/minifram.h"
34 #include "wx/fl/controlbar.h"
36 // import classes of default plugins
38 #include "wx/fl/panedrawpl.h"
39 #include "wx/fl/rowlayoutpl.h"
40 #include "wx/fl/antiflickpl.h"
41 #include "wx/fl/bardragpl.h"
42 #include "wx/fl/cbcustom.h"
44 #include "wx/fl/gcupdatesmgr.h" // import default updates manager class ("garbage-collecting" one)
45 #include "wx/fl/updatesmgr.h"
47 #include "wx/fl/toolwnd.h"
49 // These are the event IDs being initialized to a value to
50 // meet the new event paradigm as of wx2.3.0. Probably we
51 // should find a way to make these be non-global, but this
52 // works for right now.
53 wxEventType cbEVT_PL_LEFT_DOWN
= wxNewEventType();
54 wxEventType cbEVT_PL_LEFT_UP
= wxNewEventType();
55 wxEventType cbEVT_PL_RIGHT_DOWN
= wxNewEventType();
56 wxEventType cbEVT_PL_RIGHT_UP
= wxNewEventType();
57 wxEventType cbEVT_PL_MOTION
= wxNewEventType();
59 wxEventType cbEVT_PL_LEFT_DCLICK
= wxNewEventType();
61 wxEventType cbEVT_PL_LAYOUT_ROW
= wxNewEventType();
62 wxEventType cbEVT_PL_RESIZE_ROW
= wxNewEventType();
63 wxEventType cbEVT_PL_LAYOUT_ROWS
= wxNewEventType();
64 wxEventType cbEVT_PL_INSERT_BAR
= wxNewEventType();
65 wxEventType cbEVT_PL_RESIZE_BAR
= wxNewEventType();
66 wxEventType cbEVT_PL_REMOVE_BAR
= wxNewEventType();
67 wxEventType cbEVT_PL_SIZE_BAR_WND
= wxNewEventType();
69 wxEventType cbEVT_PL_DRAW_BAR_DECOR
= wxNewEventType();
70 wxEventType cbEVT_PL_DRAW_ROW_DECOR
= wxNewEventType();
71 wxEventType cbEVT_PL_DRAW_PANE_DECOR
= wxNewEventType();
72 wxEventType cbEVT_PL_DRAW_BAR_HANDLES
= wxNewEventType();
73 wxEventType cbEVT_PL_DRAW_ROW_HANDLES
= wxNewEventType();
74 wxEventType cbEVT_PL_DRAW_ROW_BKGROUND
= wxNewEventType();
75 wxEventType cbEVT_PL_DRAW_PANE_BKGROUND
= wxNewEventType();
77 wxEventType cbEVT_PL_START_BAR_DRAGGING
= wxNewEventType();
78 wxEventType cbEVT_PL_DRAW_HINT_RECT
= wxNewEventType();
80 wxEventType cbEVT_PL_START_DRAW_IN_AREA
= wxNewEventType();
81 wxEventType cbEVT_PL_FINISH_DRAW_IN_AREA
= wxNewEventType();
83 wxEventType cbEVT_PL_CUSTOMIZE_BAR
= wxNewEventType();
84 wxEventType cbEVT_PL_CUSTOMIZE_LAYOUT
= wxNewEventType();
86 wxEventType wxCUSTOM_CB_PLUGIN_EVENTS_START_AT
= wxNewEventType();
88 // some ascii-art, still can't get these *nice* cursors working on wx... :-(
91 // FIXME:: see places where _gHorizCursorImg is used
93 static const char* _gHorizCursorImg[] =
95 "............XX....XX............",
96 "............XX....XX............",
97 "............XX....XX............",
98 "............XX....XX............",
99 "............XX....XX............",
100 "...X........XX....XX........X...",
101 "..XX........XX....XX........XX..",
102 ".XXX........XX....XX........XXX.",
103 "XXXXXXXXXXXXXX....XXXXXXXXXXXXXX",
104 ".XXX........XX....XX........XXX.",
105 "..XX........XX....XX........XX..",
106 "...X........XX....XX........X...",
107 "............XX....XX............",
108 "............XX....XX............",
109 "............XX....XX............",
110 "............XX....XX............"
113 static const char* _gVertCursorImg[] =
115 "................X...............",
116 "...............XXX..............",
117 "..............XXXXX.............",
118 ".............XXXXXXX............",
119 "................X...............",
120 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
121 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
122 "................................",
123 "................................",
124 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
125 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
126 "................X...............",
127 ".............XXXXXXX............",
128 "..............XXXXX.............",
129 "...............XXX..............",
130 "................X..............."
134 // helper inline functions
136 static inline bool rect_contains_point( const wxRect
& rect
, int x
, int y
)
138 return ( x
>= rect
.x
&&
140 x
< rect
.x
+ rect
.width
&&
141 y
< rect
.y
+ rect
.height
);
144 static inline bool rect_hits_rect( const wxRect
& r1
, const wxRect
& r2
)
146 if ( ( r2
.x
>= r1
.x
&& r2
.x
<= r1
.x
+ r1
.width
) ||
147 ( r1
.x
>= r2
.x
&& r1
.x
<= r2
.x
+ r2
.width
) )
149 if ( ( r2
.y
>= r1
.y
&& r2
.y
<= r1
.y
+ r1
.height
) ||
150 ( r1
.y
>= r2
.y
&& r1
.y
<= r2
.y
+ r2
.height
) )
157 static inline void hide_rect( wxRect
& r
)
165 static inline void clip_rect_against_rect( wxRect
& r1
, const wxRect
& r2
)
169 r1
.x
>= r2
.x
+ r2
.width
||
170 r1
.y
>= r2
.y
+ r2
.height
178 if ( r1
.x
+ r1
.width
> r2
.x
+ r2
.width
)
180 r1
.width
= r2
.x
+ r2
.width
- r1
.x
;
182 if ( r1
.y
+ r1
.height
> r2
.y
+ r2
.height
)
184 r1
.height
= r2
.y
+ r2
.height
- r1
.y
;
188 /***** Implementation for class cbBarSpy *****/
190 IMPLEMENT_DYNAMIC_CLASS( cbBarSpy
, wxEvtHandler
)
192 cbBarSpy::cbBarSpy(void)
197 cbBarSpy::cbBarSpy( wxFrameLayout
* pPanel
)
203 void cbBarSpy::SetBarWindow( wxWindow
* pWnd
)
208 bool cbBarSpy::ProcessEvent(wxEvent
& event
)
210 bool handled
= wxEvtHandler::ProcessEvent( event
);
212 int type
= event
.GetEventType();
214 if ( !handled
&& ( type
== wxEVT_LEFT_DOWN
||
215 type
== wxEVT_LEFT_DCLICK
) )
217 wxMouseEvent
& mevent
= *((wxMouseEvent
*)&event
);
222 mpBarWnd
->ClientToScreen( &x
, &y
);
223 mpLayout
->GetParentFrame().ScreenToClient( &x
, &y
);
228 // forwared not-handled event to frame-layout
230 if ( type
== wxEVT_LEFT_DOWN
)
232 //mpLayout->OnLButtonDown( mevent );
236 mpLayout
->OnLDblClick( mevent
);
244 /***** Implementation for class wxFrameLayout *****/
246 IMPLEMENT_DYNAMIC_CLASS( wxFrameLayout
, wxEvtHandler
)
248 BEGIN_EVENT_TABLE( wxFrameLayout
, wxEvtHandler
)
250 EVT_PAINT ( wxFrameLayout::OnPaint
)
251 EVT_SIZE ( wxFrameLayout::OnSize
)
252 EVT_LEFT_DOWN ( wxFrameLayout::OnLButtonDown
)
253 EVT_LEFT_UP ( wxFrameLayout::OnLButtonUp
)
254 EVT_RIGHT_DOWN ( wxFrameLayout::OnRButtonDown
)
255 EVT_RIGHT_UP ( wxFrameLayout::OnRButtonUp
)
256 EVT_MOTION ( wxFrameLayout::OnMouseMove
)
258 EVT_LEFT_DCLICK( wxFrameLayout::OnLDblClick
)
260 EVT_IDLE ( wxFrameLayout::OnIdle
)
262 EVT_ERASE_BACKGROUND( wxFrameLayout::OnEraseBackground
)
266 // FIXME:: how to eliminate these cut&pasted constructors?
268 wxFrameLayout::wxFrameLayout(void)
271 mpFrameClient( NULL
),
273 mDarkPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
274 mLightPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT
), 1, wxSOLID
),
275 mGrayPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
276 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID
),
277 mBorderPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
279 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT
),
281 mpPaneInFocus( NULL
),
285 mpTopPlugin ( NULL
),
286 mpCaputesInput( NULL
),
288 mClientWndRefreshPending( false ),
289 mRecalcPending( true ),
290 mCheckFocusWhenIdle( false )
295 for ( i
= 0; i
!= MAX_PANES
; ++i
)
298 mFloatingOn
= CanReparent();
301 wxFrameLayout::wxFrameLayout( wxWindow
* pParentFrame
, wxWindow
* pFrameClient
, bool activateNow
)
303 : mpFrame( pParentFrame
),
304 mpFrameClient(pFrameClient
),
306 mDarkPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
307 mLightPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT
), 1, wxSOLID
),
308 mGrayPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
309 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID
),
310 mBorderPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
312 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT
),
314 mpPaneInFocus( NULL
),
317 mFloatingOn ( true ),
319 mpTopPlugin ( NULL
),
320 mpCaputesInput( NULL
),
322 mClientWndRefreshPending( false ),
323 mRecalcPending( true ),
324 mCheckFocusWhenIdle( false ),
331 for ( i
= 0; i
!= MAX_PANES
; ++i
)
332 mPanes
[i
] = new cbDockPane( i
, this );
339 // DBG:: set RED color of frame's background for the
340 // prurpose of tracking engine bugs "visually"
342 GetParentFrame().SetBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
) );
345 mFloatingOn
= CanReparent();
348 // NOTE:: below are the only platform-check "ifdef"s in the docking system!
350 bool wxFrameLayout::CanReparent()
354 #elif defined(__WXGTK20__)
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(__WXGTK20__)
393 pChild
->Reparent(pNewParent
);
396 #elif defined(__WXGTK__) || defined(__WXX11__)
397 // FOR NOW:: floating with wxGtk still very buggy
401 //pChild->ReParent( pNewParent );
405 wxMessageBox( "Sorry, docking is not supported for ports other than MSW and wxGTK" );
409 void wxFrameLayout::DestroyBarWindows()
411 wxObjectList::compatibility_iterator pSpy
= mBarSpyList
.GetFirst();
415 cbBarSpy
& spy
= *((cbBarSpy
*)pSpy
->GetData());
417 if ( spy
.mpBarWnd
->GetEventHandler() == &spy
)
419 spy
.mpBarWnd
->PopEventHandler();
423 pSpy
= pSpy
->GetNext();
429 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
431 if ( mAllBars
[i
]->mpBarWnd
)
433 mAllBars
[i
]->mpBarWnd
->Destroy();
434 mAllBars
[i
]->mpBarWnd
= NULL
;
439 void wxFrameLayout::ShowFloatedWindows( bool show
)
441 wxObjectList::compatibility_iterator pNode
= mFloatedFrames
.GetFirst();
445 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->GetData());
449 pNode
= pNode
->GetNext();
453 wxFrameLayout::~wxFrameLayout()
464 // destoy the chain of plugins from left to right
466 wxEvtHandler
* pCur
= mpTopPlugin
;
470 while ( pCur
->GetPreviousHandler() )
472 pCur
= pCur
->GetPreviousHandler();
476 wxEvtHandler
* pNext
= pCur
->GetNextHandler();
483 // destroy contents of arrays and lists
485 for ( i
= 0; i
!= MAX_PANES
; ++i
)
491 delete mpHorizCursor
;
494 if ( mpNormalCursor
)
495 delete mpNormalCursor
;
501 wxObjectList::compatibility_iterator pSpy
= mBarSpyList
.GetFirst();
505 cbBarSpy
& spy
= *((cbBarSpy
*)pSpy
->GetData());
507 if ( spy
.mpBarWnd
->GetEventHandler() == &spy
)
509 spy
.mpBarWnd
->PopEventHandler();
513 pSpy
= pSpy
->GetNext();
516 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
520 void wxFrameLayout::EnableFloating( bool enable
)
522 mFloatingOn
= enable
&& CanReparent();
525 void wxFrameLayout::Activate()
531 ShowFloatedWindows( true );
534 void wxFrameLayout::Deactivate()
536 ShowFloatedWindows( false );
543 void wxFrameLayout::SetFrameClient( wxWindow
* pFrameClient
)
545 mpFrameClient
= pFrameClient
;
548 wxWindow
* wxFrameLayout::GetFrameClient()
550 return mpFrameClient
;
553 cbUpdatesManagerBase
& wxFrameLayout::GetUpdatesManager()
556 mpUpdatesMgr
= CreateUpdatesManager();
558 return *mpUpdatesMgr
;
561 void wxFrameLayout::SetUpdatesManager( cbUpdatesManagerBase
* pUMgr
)
566 mpUpdatesMgr
= pUMgr
;
568 mpUpdatesMgr
->SetLayout( this );
571 cbUpdatesManagerBase
* wxFrameLayout::CreateUpdatesManager()
573 return new cbGCUpdatesMgr( this );
574 //return new cbSimpleUpdatesMgr( this );
577 void wxFrameLayout::AddBar( wxWindow
* pBarWnd
,
578 const cbDimInfo
& dimInfo
,
582 const wxString
& name
,
587 if ( pBarWnd
&& spyEvents
)
589 // hook up spy to bar window
590 cbBarSpy
* pSpy
= new cbBarSpy( this );
592 pSpy
->SetBarWindow( pBarWnd
);
593 pBarWnd
->PushEventHandler( pSpy
);
595 mBarSpyList
.Append( pSpy
);
598 cbBarInfo
* pInfo
= new cbBarInfo();
601 pInfo
->mpBarWnd
= pBarWnd
;
602 pInfo
->mDimInfo
= dimInfo
;
603 pInfo
->mDimInfo
.mLRUPane
= alignment
;
604 pInfo
->mState
= state
;
605 pInfo
->mAlignment
= alignment
;
606 pInfo
->mRowNo
= rowNo
;
607 pInfo
->mBounds
.x
= columnPos
;
609 mAllBars
.Add( pInfo
);
611 DoSetBarState( pInfo
);
614 bool wxFrameLayout::RedockBar( cbBarInfo
* pBar
,
615 const wxRect
& shapeInParent
,
621 pToPane
= HitTestPanes( shapeInParent
, NULL
);
625 return false; // bar's shape does not hit any pane
626 // - redocking is NOT possible
628 cbDockPane
* pBarPane
= GetBarPane( pBar
);
632 GetUpdatesManager().OnStartChanges();
634 pBarPane
->RemoveBar( pBar
);
636 // FIXME FIXME:: the recalculation below may be a *huge* performance
637 // hit, it could be eliminated though...
638 // but first the "pane-postion-changed" problem
641 RecalcLayout( false );
643 pToPane
->InsertBar( pBar
, shapeInParent
);
645 RecalcLayout( false );
647 // finish update "transaction"
651 GetUpdatesManager().OnFinishChanges();
652 GetUpdatesManager().UpdateNow();
658 cbBarInfo
* wxFrameLayout::FindBarByName( const wxString
& name
)
661 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
662 if ( mAllBars
[i
]->mName
== name
)
668 cbBarInfo
* wxFrameLayout::FindBarByWindow( const wxWindow
* pWnd
)
671 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
672 if ( mAllBars
[i
]->mpBarWnd
== pWnd
)
678 BarArrayT
& wxFrameLayout::GetBars()
683 void wxFrameLayout::SetBarState( cbBarInfo
* pBar
, int newState
, bool updateNow
)
685 if ( newState
== wxCBAR_FLOATING
&& !(mFloatingOn
&& pBar
->mFloatingOn
))
691 GetUpdatesManager().OnStartChanges();
693 pBar
->mUMgrData
.SetDirty(true);
695 // check bar's previous state
697 if ( pBar
->mState
!= wxCBAR_HIDDEN
&& pBar
->mState
!= wxCBAR_FLOATING
)
705 LocateBar( pBar
, &pRow
, &pPane
);
707 wxASSERT( success
); // DBG::
709 // save LRU-dim info before removing bar
711 pBar
->mDimInfo
.mLRUPane
= pPane
->GetAlignment();
712 pBar
->mDimInfo
.mBounds
[ pPane
->GetAlignment() ] = pBar
->mBounds
;
714 // remove it from the pane it was docked on
716 pPane
->RemoveBar( pBar
);
720 if ( pBar
->mState
== wxCBAR_FLOATING
&& newState
!= wxCBAR_FLOATING
)
722 // remove bar's window from the containing mini-frame
723 // and set its parent to be layout's parent frame
725 if ( pBar
->mpBarWnd
)
727 pBar
->mpBarWnd
->Show(false); // to avoid flicker upon reparenting
729 wxObjectList::compatibility_iterator pNode
= mFloatedFrames
.GetFirst();
733 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->GetData());
735 if ( pFFrm
->GetBar() == pBar
)
737 pFFrm
->Show( false ); // reduces flicker sligthly
739 ReparentWindow( pBar
->mpBarWnd
, &GetParentFrame() );
741 pBar
->mBounds
= pBar
->mDimInfo
.mBounds
[ pBar
->mDimInfo
.mLRUPane
];
743 if ( newState
!= wxCBAR_HIDDEN
)
745 pBar
->mAlignment
= pBar
->mDimInfo
.mLRUPane
;
747 mFloatedFrames
.Erase( pNode
);
749 pFFrm
->Show( false );
750 pFFrm
->Destroy(); break;
753 pNode
= pNode
->GetNext();
756 // FOR NOW:: excessive!
757 //if ( mpFrameClient ) mpFrameClient->Refresh();
759 mClientWndRefreshPending
= true;
763 if ( pBar
->mDimInfo
.GetDimHandler() )
765 pBar
->mDimInfo
.GetDimHandler()->OnChangeBarState( pBar
, newState
);
768 pBar
->mState
= newState
;
770 DoSetBarState( pBar
);
776 GetUpdatesManager().OnFinishChanges();
777 GetUpdatesManager().UpdateNow();
781 void wxFrameLayout::InverseVisibility( cbBarInfo
* pBar
)
783 wxASSERT( pBar
); // DBG::
785 // "inverse" bar-visibility of the selected bar
789 if ( pBar
->mState
== wxCBAR_HIDDEN
)
791 if ( pBar
->mAlignment
== -1 )
793 pBar
->mAlignment
= 0; // just remove "-1" marking
794 newState
= wxCBAR_FLOATING
;
797 if ( pBar
->mAlignment
== FL_ALIGN_TOP
||
798 pBar
->mAlignment
== FL_ALIGN_BOTTOM
)
800 newState
= wxCBAR_DOCKED_HORIZONTALLY
;
802 newState
= wxCBAR_DOCKED_VERTICALLY
;
806 newState
= wxCBAR_HIDDEN
;
808 if ( pBar
->mState
== wxCBAR_FLOATING
)
810 pBar
->mAlignment
= -1;
813 this->SetBarState( pBar
, newState
, true );
815 if ( newState
== wxCBAR_FLOATING
)
817 this->RepositionFloatedBar( pBar
);
820 void wxFrameLayout::ApplyBarProperties( cbBarInfo
* pBar
)
822 if ( pBar
->mState
== wxCBAR_FLOATING
)
824 RepositionFloatedBar( pBar
);
827 if ( pBar
->mState
== wxCBAR_DOCKED_HORIZONTALLY
||
828 pBar
->mState
== wxCBAR_DOCKED_VERTICALLY
836 void wxFrameLayout::RepositionFloatedBar( cbBarInfo
* pBar
)
838 if ( !(mFloatingOn
&& pBar
->mFloatingOn
)) return;
840 wxObjectList::compatibility_iterator pNode
= mFloatedFrames
.GetFirst();
844 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->GetData());
846 if ( pFFrm
->GetBar() == pBar
)
848 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
853 GetParentFrame().ClientToScreen( &x
, &y
);
855 pFFrm
->PositionFloatedWnd( x
,y
,
862 pNode
= pNode
->GetNext();
866 void wxFrameLayout::DoSetBarState( cbBarInfo
* pBar
)
868 if ( pBar
->mState
!= wxCBAR_FLOATING
&&
869 pBar
->mState
!= wxCBAR_HIDDEN
)
873 mPanes
[pBar
->mAlignment
]->InsertBar( pBar
);
875 if ( pBar
->mState
== wxCBAR_HIDDEN
)
879 if ( pBar
->mpBarWnd
)
881 pBar
->mpBarWnd
->Show( false );
885 if ( !(mFloatingOn
&& pBar
->mFloatingOn
) )
890 if ( pBar
->mpBarWnd
== NULL
|| !CanReparent() )
892 // FOR NOW:: just hide it
894 if ( pBar
->mpBarWnd
)
896 pBar
->mpBarWnd
->Show( false );
898 pBar
->mState
= wxCBAR_HIDDEN
;
903 cbFloatedBarWindow
* pMiniFrm
= new cbFloatedBarWindow();
905 pMiniFrm
->SetBar( pBar
);
906 pMiniFrm
->SetLayout( this );
908 pMiniFrm
->Create( &GetParentFrame(), wxID_ANY
, pBar
->mName
,
911 wxFRAME_FLOAT_ON_PARENT
|
916 pMiniFrm
->SetClient( pBar
->mpBarWnd
);
918 ReparentWindow( pBar
->mpBarWnd
, pMiniFrm
);
920 mFloatedFrames
.Append( pMiniFrm
);
922 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
924 // check if it wasn't floated anytime before
926 if ( bounds
.width
== -1 )
928 wxRect
& clntRect
= GetClientRect();
930 // adjust position into which the next floated bar will be placed
932 if ( mNextFloatedWndPos
.x
+ bounds
.width
> clntRect
.width
)
934 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
936 if ( mNextFloatedWndPos
.y
+ bounds
.height
> clntRect
.height
)
938 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
940 bounds
.x
= mNextFloatedWndPos
.x
+ clntRect
.x
;
941 bounds
.y
= mNextFloatedWndPos
.y
+ clntRect
.y
;
943 bounds
.width
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].x
;
944 bounds
.height
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].y
;
946 mNextFloatedWndPos
.x
+= mFloatingPosStep
.x
;
947 mNextFloatedWndPos
.y
+= mFloatingPosStep
.y
;
950 pMiniFrm
->Show( true );
951 RepositionFloatedBar(pMiniFrm
->GetBar());
953 // FIXME:: this is excessive
954 pBar
->mpBarWnd
->Show(true);
958 void wxFrameLayout::RemoveBar( cbBarInfo
* pBarInfo
)
960 // first, try to "guess" what was the perviouse state of the bar
965 if ( LocateBar( pBarInfo
, &pRow
, &pPane
) )
967 // ...aha, bar was docked into one of the panes,
968 // remove it from there
970 pPane
->RemoveBar( pBarInfo
);
974 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
976 if ( mAllBars
[i
] == pBarInfo
)
978 #if wxCHECK_VERSION(2,3,2)
979 mAllBars
.RemoveAt(i
);
983 if ( pBarInfo
->mpBarWnd
) // hides it's window
985 pBarInfo
->mpBarWnd
->Show( false );
992 wxFAIL_MSG(wxT("bar info should be present in the list of all bars of all panes"));
995 bool wxFrameLayout::LocateBar( cbBarInfo
* pBarInfo
,
997 cbDockPane
** ppPane
)
1003 for ( n
= 0; n
!= MAX_PANES
; ++n
)
1005 wxBarIterator
i( mPanes
[n
]->GetRowList() );
1009 if ( &i
.BarInfo() == pBarInfo
)
1011 (*ppPane
) = mPanes
[n
];
1012 (*ppRow
) = &i
.RowInfo();
1021 void wxFrameLayout::RecalcLayout( bool repositionBarsNow
)
1023 mRecalcPending
= false;
1025 int frmWidth
, frmHeight
;
1026 mpFrame
->GetClientSize( &frmWidth
, &frmHeight
);
1032 // pane positioning priorities in decreasing order:
1033 // top, bottom, left, right
1037 cbDockPane
* pPane
= mPanes
[ FL_ALIGN_TOP
];
1039 pPane
->SetPaneWidth( frmWidth
);
1040 pPane
->RecalcLayout();
1042 int paneHeight
= pPane
->GetPaneHeight();
1046 rect
.width
= frmWidth
;
1047 rect
.height
= wxMin( paneHeight
, frmHeight
- curY
);
1049 pPane
->SetBoundsInParent( rect
);
1053 // setup BOTTOM pane
1055 pPane
= mPanes
[ FL_ALIGN_BOTTOM
];
1057 pPane
->SetPaneWidth( frmWidth
);
1058 pPane
->RecalcLayout();
1060 paneHeight
= pPane
->GetPaneHeight();
1063 rect
.y
= wxMax( frmHeight
- paneHeight
, curY
);
1064 rect
.width
= frmWidth
;
1065 rect
.height
= frmHeight
- rect
.y
;
1067 pPane
->SetBoundsInParent( rect
);
1071 pPane
= mPanes
[ FL_ALIGN_LEFT
];
1074 pPane
->SetPaneWidth( rect
.y
- curY
);
1076 pPane
->RecalcLayout();
1077 paneHeight
= pPane
->GetPaneHeight();
1080 rect
.height
= rect
.y
- curY
;
1083 rect
.width
= wxMin( paneHeight
, frmWidth
);
1085 pPane
->SetBoundsInParent( rect
);
1091 pPane
= mPanes
[ FL_ALIGN_RIGHT
];
1093 // left pane's height
1094 pPane
->SetPaneWidth( rect
.height
);
1096 pPane
->RecalcLayout();
1097 paneHeight
= pPane
->GetPaneHeight();
1099 // left pane's height
1100 rect
.height
= rect
.height
;
1101 rect
.x
= wxMax( frmWidth
- paneHeight
, curX
);
1103 rect
.width
= frmWidth
- rect
.x
;
1105 pPane
->SetBoundsInParent( rect
);
1107 // recalc bounds of the client-window
1109 mClntWndBounds
.x
= mPanes
[FL_ALIGN_LEFT
]->mBoundsInParent
.x
+
1110 mPanes
[FL_ALIGN_LEFT
]->mBoundsInParent
.width
;
1111 mClntWndBounds
.y
= mPanes
[FL_ALIGN_TOP
]->mBoundsInParent
.y
+
1112 mPanes
[FL_ALIGN_TOP
]->mBoundsInParent
.height
;
1114 mClntWndBounds
.width
= mPanes
[FL_ALIGN_RIGHT
]->mBoundsInParent
.x
-
1116 mClntWndBounds
.height
= mPanes
[FL_ALIGN_BOTTOM
]->mBoundsInParent
.y
-
1119 if ( repositionBarsNow
)
1124 int wxFrameLayout::GetClientHeight()
1126 // for better portablility wxWindow::GetSzie() is not used here
1128 return mClntWndBounds
.height
;
1131 int wxFrameLayout::GetClientWidth()
1133 // for better portablility wxWindow::GetSzie() is not used here
1135 return mClntWndBounds
.width
;
1138 void wxFrameLayout::PositionClientWindow()
1140 if ( mpFrameClient
)
1142 if ( mClntWndBounds
.width
>= 1 && mClntWndBounds
.height
>= 1 )
1144 mpFrameClient
->SetSize( mClntWndBounds
.x
, mClntWndBounds
.y
,
1145 mClntWndBounds
.width
, mClntWndBounds
.height
, 0 );
1147 if ( !mpFrameClient
->IsShown() )
1149 mpFrameClient
->Show( true );
1152 mpFrameClient
->Show( false );
1156 void wxFrameLayout::PositionPanes()
1158 PositionClientWindow();
1160 // FOR NOW:: excessive updates!
1161 // reposition bars within all panes
1164 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1165 mPanes
[i
]->SizePaneObjects();
1168 void wxFrameLayout::OnSize( wxSizeEvent
& event
)
1170 mpFrame
->ProcessEvent( event
);
1171 event
.Skip( false ); // stop its progpagation
1173 if ( event
.GetEventObject() == (wxObject
*) mpFrame
)
1175 GetUpdatesManager().OnStartChanges();
1177 GetUpdatesManager().OnFinishChanges();
1178 GetUpdatesManager().UpdateNow();
1183 /*** protected members ***/
1185 void wxFrameLayout::HideBarWindows()
1188 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
1189 if ( mAllBars
[i
]->mpBarWnd
&& mAllBars
[i
]->mState
!= wxCBAR_FLOATING
)
1190 mAllBars
[i
]->mpBarWnd
->Show( false );
1192 // then floated frames
1194 ShowFloatedWindows( false );
1196 if ( mpFrameClient
)
1198 mpFrameClient
->Show( false );
1201 void wxFrameLayout::UnhookFromFrame()
1203 // NOTE:: the SetEvtHandlerEnabled() method is not used
1204 // here, since it is assumed that unhooking layout
1205 // from window may result destroying of the layout itself
1207 // BUG BUG BUG (wx):: this would not be a problem if
1208 // wxEvtHandler's destructor checked if
1209 // this handler is currently the top-most
1210 // handler of some window, and additionally
1211 // to the reconnecting itself from the chain.
1212 // It would also re-setup current event handler
1213 // of the window using wxWindow::SetEventHandler()
1217 if ( mpFrame
->GetEventHandler() == this )
1219 mpFrame
->PopEventHandler();
1225 if ( this == mpFrame
->GetEventHandler() )
1227 mpFrame
->SetEventHandler( this->GetNextHandler() );
1231 wxEvtHandler
* pCur
= mpFrame
->GetEventHandler();
1238 pCur
= pCur
->GetNextHandler();
1241 // do not try to unhook ourselves if we're not hooked yet
1246 if ( GetPreviousHandler() )
1247 GetPreviousHandler()->SetNextHandler( GetNextHandler() );
1250 mpFrame
->PopEventHandler();
1254 if ( GetNextHandler() )
1255 GetNextHandler()->SetPreviousHandler( GetPreviousHandler() );
1257 SetNextHandler( NULL
);
1258 SetPreviousHandler( NULL
);
1262 void wxFrameLayout::HookUpToFrame()
1264 // unhook us first, we're already hooked up
1268 // put ourselves on top
1270 mpFrame
->PushEventHandler( this );
1273 cbDockPane
* wxFrameLayout::GetBarPane( cbBarInfo
* pBar
)
1276 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1277 if ( mPanes
[i
]->BarPresent( pBar
) )
1283 void wxFrameLayout::CreateCursors()
1286 // FIXME:: The below code somehow doesn't work - cursors remain unchanged
1289 set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
1291 mpHorizCursor = new wxCursor( bits, 32, 16 );
1293 set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
1295 mpVertCursor = new wxCursor( bits, 32, 16 );
1298 // FOR NOW:: use standard ones
1300 mpHorizCursor
= new wxCursor(wxCURSOR_SIZEWE
);
1301 mpVertCursor
= new wxCursor(wxCURSOR_SIZENS
);
1302 mpNormalCursor
= new wxCursor(wxCURSOR_ARROW
);
1303 mpDragCursor
= new wxCursor(wxCURSOR_CROSS
);
1304 mpNECursor
= new wxCursor(wxCURSOR_NO_ENTRY
);
1306 mFloatingPosStep
.x
= 25;
1307 mFloatingPosStep
.y
= 25;
1309 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
1310 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
1313 bool wxFrameLayout::HitTestPane( cbDockPane
* pPane
, int x
, int y
)
1315 return rect_contains_point( pPane
->GetRealRect(), x
, y
);
1318 cbDockPane
* wxFrameLayout::HitTestPanes( const wxRect
& rect
,
1319 cbDockPane
* pCurPane
)
1321 // first, give the privilege to the current pane
1323 if ( pCurPane
&& rect_hits_rect( pCurPane
->GetRealRect(), rect
) )
1328 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1330 if ( pCurPane
!= mPanes
[i
] &&
1331 rect_hits_rect( mPanes
[i
]->GetRealRect(), rect
) )
1339 void wxFrameLayout::ForwardMouseEvent( wxMouseEvent
& event
,
1340 cbDockPane
* pToPane
,
1343 wxPoint
pos( event
.m_x
, event
.m_y
);
1344 pToPane
->FrameToPane( &pos
.x
, &pos
.y
);
1346 if ( eventType
== cbEVT_PL_LEFT_DOWN
)
1348 cbLeftDownEvent
evt( pos
, pToPane
);
1349 FirePluginEvent( evt
);
1351 else if ( eventType
== cbEVT_PL_LEFT_DCLICK
)
1353 cbLeftDClickEvent
evt( pos
, pToPane
);
1354 FirePluginEvent( evt
);
1356 else if ( eventType
== cbEVT_PL_LEFT_UP
)
1358 cbLeftUpEvent
evt( pos
, pToPane
);
1359 FirePluginEvent( evt
);
1361 else if ( eventType
== cbEVT_PL_RIGHT_DOWN
)
1363 cbRightDownEvent
evt( pos
, pToPane
);
1364 FirePluginEvent( evt
);
1366 else if ( eventType
== cbEVT_PL_RIGHT_UP
)
1368 cbRightUpEvent
evt( pos
, pToPane
);
1369 FirePluginEvent( evt
);
1371 else if ( eventType
== cbEVT_PL_MOTION
)
1373 cbMotionEvent
evt( pos
, pToPane
);
1374 FirePluginEvent( evt
);
1376 } // wxFrameLayout::ForwardMouseEvent()
1379 void wxFrameLayout::RouteMouseEvent( wxMouseEvent
& event
, int pluginEvtType
)
1381 if ( mpPaneInFocus
)
1383 ForwardMouseEvent( event
, mpPaneInFocus
, pluginEvtType
);
1387 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1389 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1391 ForwardMouseEvent( event
, mPanes
[i
], pluginEvtType
);
1398 /*** event handlers ***/
1400 void wxFrameLayout::OnRButtonDown( wxMouseEvent
& event
)
1402 RouteMouseEvent( event
, cbEVT_PL_RIGHT_DOWN
);
1405 void wxFrameLayout::OnRButtonUp( wxMouseEvent
& event
)
1407 RouteMouseEvent( event
, cbEVT_PL_RIGHT_UP
);
1410 void wxFrameLayout::OnLButtonDown( wxMouseEvent
& event
)
1412 RouteMouseEvent( event
, cbEVT_PL_LEFT_DOWN
);
1415 void wxFrameLayout::OnLDblClick( wxMouseEvent
& event
)
1417 RouteMouseEvent( event
, cbEVT_PL_LEFT_DCLICK
);
1420 void wxFrameLayout::OnLButtonUp( wxMouseEvent
& event
)
1422 RouteMouseEvent( event
, cbEVT_PL_LEFT_UP
);
1425 void wxFrameLayout::OnMouseMove( wxMouseEvent
& event
)
1427 if ( mpPaneInFocus
)
1429 ForwardMouseEvent( event
, mpPaneInFocus
, cbEVT_PL_MOTION
);
1433 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1435 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1437 if ( mpLRUPane
&& mpLRUPane
!= mPanes
[i
] )
1439 // simulate "mouse-leave" event
1440 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1443 ForwardMouseEvent( event
, mPanes
[i
], cbEVT_PL_MOTION
);
1445 mpLRUPane
= mPanes
[i
];
1454 // simulate "mouse-leave" event
1455 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1460 void wxFrameLayout::OnPaint( wxPaintEvent
& event
)
1462 if ( mRecalcPending
)
1463 RecalcLayout( true );
1465 wxPaintDC
dc(mpFrame
);
1468 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1470 wxRect
& rect
= mPanes
[i
]->mBoundsInParent
;
1472 dc
.SetClippingRegion( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1474 mPanes
[i
]->PaintPane(dc
);
1476 dc
.DestroyClippingRegion();
1482 void wxFrameLayout::OnEraseBackground( wxEraseEvent
& WXUNUSED(event
) )
1487 void wxFrameLayout::OnIdle( wxIdleEvent
& event
)
1489 wxWindow
* focus
= wxWindow::FindFocus();
1491 if ( !focus
&& mCheckFocusWhenIdle
)
1493 wxMessageBox(wxT("Hi, no more focus in this app!"));
1495 mCheckFocusWhenIdle
= false;
1496 //ShowFloatedWindows( false );
1499 mCheckFocusWhenIdle
= false;
1504 void wxFrameLayout::GetPaneProperties( cbCommonPaneProperties
& props
, int alignment
)
1506 props
= mPanes
[alignment
]->mProps
;
1509 void wxFrameLayout::SetPaneProperties( const cbCommonPaneProperties
& props
, int paneMask
)
1512 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1514 if ( mPanes
[i
]->MatchesMask( paneMask
) )
1515 mPanes
[i
]->mProps
= props
;
1519 void wxFrameLayout::SetMargins( int top
, int bottom
, int left
, int right
,
1523 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1525 cbDockPane
& pane
= *mPanes
[i
];
1527 if ( pane
.MatchesMask( paneMask
) )
1529 pane
.mTopMargin
= top
;
1530 pane
.mBottomMargin
= bottom
;
1531 pane
.mLeftMargin
= left
;
1532 pane
.mRightMargin
= right
;
1537 void wxFrameLayout::SetPaneBackground( const wxColour
& colour
)
1539 mBorderPen
.SetColour( colour
);
1542 void wxFrameLayout::RefreshNow( bool recalcLayout
)
1545 RecalcLayout( true );
1551 /*** plugin-related methods ***/
1553 void wxFrameLayout::FirePluginEvent( cbPluginEvent
& event
)
1555 // check state of input capture, before processing the event
1557 if ( mpCaputesInput
)
1559 bool isInputEvt
= true;
1560 #if wxCHECK_VERSION(2,3,0)
1561 if ( event
.m_eventType
!= cbEVT_PL_LEFT_DOWN
&&
1562 event
.m_eventType
!= cbEVT_PL_LEFT_UP
&&
1563 event
.m_eventType
!= cbEVT_PL_RIGHT_DOWN
&&
1564 event
.m_eventType
!= cbEVT_PL_RIGHT_UP
&&
1565 event
.m_eventType
!= cbEVT_PL_MOTION
)
1568 switch ( event
.m_eventType
)
1570 case cbEVT_PL_LEFT_DOWN
: break;
1571 case cbEVT_PL_LEFT_UP
: break;
1572 case cbEVT_PL_RIGHT_DOWN
: break;
1573 case cbEVT_PL_RIGHT_UP
: break;
1574 case cbEVT_PL_MOTION
: break;
1576 default : isInputEvt
= false; break;
1578 #endif // #if wxCHECK_VERSION(2,3,0)
1582 mpCaputesInput
->ProcessEvent( event
);
1587 GetTopPlugin().ProcessEvent( event
);
1590 void wxFrameLayout::CaptureEventsForPlugin ( cbPluginBase
* pPlugin
)
1592 // cannot capture events for more than one plugin at a time
1593 wxASSERT( mpCaputesInput
== NULL
);
1595 mpCaputesInput
= pPlugin
;
1599 void wxFrameLayout::ReleaseEventsFromPlugin( cbPluginBase
* WXUNUSED(pPlugin
) )
1601 // events should be captured first
1602 wxASSERT( mpCaputesInput
!= NULL
);
1604 mpCaputesInput
= NULL
;
1607 void wxFrameLayout::CaptureEventsForPane( cbDockPane
* toPane
)
1609 // cannot capture events twice (without releasing)
1610 wxASSERT( mpPaneInFocus
== NULL
);
1612 mpFrame
->CaptureMouse();
1614 mpPaneInFocus
= toPane
;
1617 void wxFrameLayout::ReleaseEventsFromPane( cbDockPane
* WXUNUSED(fromPane
) )
1619 // cannot release events without capturing them
1620 wxASSERT( mpPaneInFocus
!= NULL
);
1622 mpFrame
->ReleaseMouse();
1624 mpPaneInFocus
= NULL
;
1627 cbPluginBase
& wxFrameLayout::GetTopPlugin()
1631 PushDefaultPlugins(); // automatic configuration
1633 return *mpTopPlugin
;
1636 void wxFrameLayout::SetTopPlugin( cbPluginBase
* pPlugin
)
1638 mpTopPlugin
= pPlugin
;
1641 bool wxFrameLayout::HasTopPlugin()
1643 return ( mpTopPlugin
!= NULL
);
1646 void wxFrameLayout::PushPlugin( cbPluginBase
* pPlugin
)
1650 mpTopPlugin
= pPlugin
;
1653 pPlugin
->SetNextHandler( mpTopPlugin
);
1655 mpTopPlugin
->SetPreviousHandler( pPlugin
);
1657 mpTopPlugin
= pPlugin
;
1660 mpTopPlugin
->OnInitPlugin(); // notification
1663 void wxFrameLayout::PopPlugin()
1665 wxASSERT( mpTopPlugin
); // DBG:: at least one plugin should be present
1667 cbPluginBase
* pPopped
= mpTopPlugin
;
1669 mpTopPlugin
= (cbPluginBase
*)mpTopPlugin
->GetNextHandler();
1674 void wxFrameLayout::PopAllPlugins()
1676 while( mpTopPlugin
) PopPlugin();
1679 void wxFrameLayout::PushDefaultPlugins()
1681 // FIXME:: to much of the stuff for the default...
1683 AddPlugin( CLASSINFO( cbRowLayoutPlugin
) );
1684 AddPlugin( CLASSINFO( cbBarDragPlugin
) );
1685 AddPlugin( CLASSINFO( cbPaneDrawPlugin
) );
1688 void wxFrameLayout::AddPlugin( wxClassInfo
* pPlInfo
, int paneMask
)
1690 if ( FindPlugin ( pPlInfo
) ) return; // same type of plugin cannot be added twice
1692 cbPluginBase
* pObj
= (cbPluginBase
*)pPlInfo
->CreateObject();
1694 wxASSERT(pObj
); // DBG:: plugin's class should be dynamic
1696 pObj
->mPaneMask
= paneMask
;
1697 pObj
->mpLayout
= this;
1702 void wxFrameLayout::AddPluginBefore( wxClassInfo
* pNextPlInfo
, wxClassInfo
* pPlInfo
,
1705 wxASSERT( pNextPlInfo
!= pPlInfo
); // DBG:: no sense
1707 cbPluginBase
* pNextPl
= FindPlugin( pNextPlInfo
);
1711 AddPlugin( pPlInfo
, paneMask
);
1716 // remove existing one if present
1718 cbPluginBase
* pExistingPl
= FindPlugin( pPlInfo
);
1720 if ( pExistingPl
) RemovePlugin( pPlInfo
);
1722 // create an instance
1724 cbPluginBase
* pNewPl
= (cbPluginBase
*)pPlInfo
->CreateObject();
1726 wxASSERT(pNewPl
); // DBG:: plugin's class should be dynamic
1728 // insert it to the chain
1730 if ( pNextPl
->GetPreviousHandler() )
1732 pNextPl
->GetPreviousHandler()->SetNextHandler( pNewPl
);
1734 mpTopPlugin
= pNewPl
;
1736 pNewPl
->SetNextHandler( pNextPl
);
1738 pNewPl
->SetPreviousHandler( pNextPl
->GetPreviousHandler() );
1740 pNextPl
->SetPreviousHandler( pNewPl
);
1744 pNewPl
->mPaneMask
= paneMask
;
1745 pNewPl
->mpLayout
= this;
1747 pNewPl
->OnInitPlugin();
1750 void wxFrameLayout::RemovePlugin( wxClassInfo
* pPlInfo
)
1752 cbPluginBase
* pPlugin
= FindPlugin( pPlInfo
);
1754 if ( !pPlugin
) return; // it's OK to remove not-existing plugin ;-)
1756 if ( pPlugin
->GetPreviousHandler() == NULL
)
1758 mpTopPlugin
= (cbPluginBase
*)pPlugin
->GetNextHandler();
1763 cbPluginBase
* wxFrameLayout::FindPlugin( wxClassInfo
* pPlInfo
)
1765 cbPluginBase
*pCur
= mpTopPlugin
;
1769 // NOTE:: it might appear useful matching plugin
1770 // classes "polymorphically":
1772 if ( pCur
->GetClassInfo()->IsKindOf( pPlInfo
) )
1776 pCur
= (cbPluginBase
*)pCur
->GetNextHandler();
1782 /***** Implementation for class cbUpdateMgrData *****/
1784 IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData
, wxObject
)
1786 cbUpdateMgrData::cbUpdateMgrData()
1788 : mPrevBounds( -1,-1,0,0 ),
1789 mIsDirty( true ), // inidicate initial change
1793 void cbUpdateMgrData::StoreItemState( const wxRect
& boundsInParent
)
1795 mPrevBounds
= boundsInParent
;
1798 void cbUpdateMgrData::SetDirty( bool isDirty
)
1803 void cbUpdateMgrData::SetCustomData( wxObject
* pCustomData
)
1805 mpCustomData
= pCustomData
;
1808 /***** Implementation for class cbDockPane *****/
1810 void wxBarIterator::Reset()
1812 mpRow
= ( mpRows
->Count() ) ? (*mpRows
)[0] : NULL
;
1816 wxBarIterator::wxBarIterator( RowArrayT
& rows
)
1825 bool wxBarIterator::Next()
1830 mpBar
= mpBar
->mpNext
;
1833 if ( mpRow
->mBars
.GetCount() == 0 )
1838 mpBar
= mpRow
->mBars
[0];
1843 // skip to the next row
1845 mpRow
= mpRow
->mpNext
;
1849 mpBar
= mpRow
->mBars
[0];
1860 cbBarInfo
& wxBarIterator::BarInfo()
1865 cbRowInfo
& wxBarIterator::RowInfo()
1870 /***** Implementation for class cbBarDimHandlerBase *****/
1872 IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase
, wxObject
)
1874 cbBarDimHandlerBase::cbBarDimHandlerBase()
1878 void cbBarDimHandlerBase::AddRef()
1883 void cbBarDimHandlerBase::RemoveRef()
1885 if ( --mRefCount
<= 0 ) delete this;
1888 /***** Implementation for class cbDimInfo *****/
1890 IMPLEMENT_DYNAMIC_CLASS( cbDimInfo
, wxObject
)
1892 cbDimInfo::cbDimInfo()
1901 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1906 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1910 cbDimInfo::cbDimInfo( cbBarDimHandlerBase
* pDimHandler
,
1915 mIsFixed ( isFixed
),
1917 mpHandler( pDimHandler
)
1921 // int vtad = *((int*)mpHandler);
1922 mpHandler
->AddRef();
1926 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1931 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1935 cbDimInfo::cbDimInfo( int dh_x
, int dh_y
,
1943 cbBarDimHandlerBase
* pDimHandler
1945 : mVertGap ( vertGap
),
1946 mHorizGap ( horizGap
),
1947 mIsFixed ( isFixed
),
1948 mpHandler( pDimHandler
)
1952 // int vtad = *((int*)mpHandler);
1953 mpHandler
->AddRef();
1956 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= dh_x
;
1957 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= dh_y
;
1958 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= dv_x
;
1959 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= dv_y
;
1960 mSizes
[wxCBAR_FLOATING
].x
= f_x
;
1961 mSizes
[wxCBAR_FLOATING
].y
= f_y
;
1964 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1965 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1968 cbDimInfo::cbDimInfo( int x
, int y
,
1969 bool isFixed
, int gap
,
1970 cbBarDimHandlerBase
* pDimHandler
)
1973 mIsFixed ( isFixed
),
1974 mpHandler( pDimHandler
)
1978 // int vtad = *((int*)mpHandler);
1979 mpHandler
->AddRef();
1982 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= x
;
1983 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= y
;
1984 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= x
;
1985 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= y
;
1986 mSizes
[wxCBAR_FLOATING
].x
= x
;
1987 mSizes
[wxCBAR_FLOATING
].y
= y
;
1990 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1991 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1994 cbDimInfo::~cbDimInfo()
1998 mpHandler
->RemoveRef();
2001 const cbDimInfo
& cbDimInfo::operator=( const cbDimInfo
& other
)
2003 if ( this == &other
)
2007 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2008 mSizes
[i
] = other
.mSizes
[i
];
2010 mIsFixed
= other
.mIsFixed
;
2011 mpHandler
= other
.mpHandler
;
2013 mVertGap
= other
.mVertGap
;
2014 mHorizGap
= other
.mHorizGap
;
2018 mpHandler
->AddRef();
2023 /***** Implementation for structure cbCommonPaneProperties *****/
2025 IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties
, wxObject
)
2027 cbCommonPaneProperties::cbCommonPaneProperties(void)
2029 : mRealTimeUpdatesOn ( true ),
2030 mOutOfPaneDragOn ( true ),
2031 mExactDockPredictionOn( false ),
2032 mNonDestructFrictionOn( false ),
2033 mShow3DPaneBorderOn ( true ),
2034 mBarFloatingOn ( false ),
2035 mRowProportionsOn ( false ),
2036 mColProportionsOn ( true ),
2037 mBarCollapseIconsOn ( false ),
2038 mBarDragHintsOn ( false ),
2040 mMinCBarDim( 16, 16 ),
2041 mResizeHandleSize( 4 )
2044 cbCommonPaneProperties::cbCommonPaneProperties(const cbCommonPaneProperties
& props
)
2047 mRealTimeUpdatesOn (props
.mRealTimeUpdatesOn
),
2048 mOutOfPaneDragOn (props
.mOutOfPaneDragOn
),
2049 mExactDockPredictionOn(props
.mExactDockPredictionOn
),
2050 mNonDestructFrictionOn(props
.mNonDestructFrictionOn
),
2051 mShow3DPaneBorderOn (props
.mShow3DPaneBorderOn
),
2052 mBarFloatingOn (props
.mBarFloatingOn
),
2053 mRowProportionsOn (props
.mRowProportionsOn
),
2054 mColProportionsOn (props
.mColProportionsOn
),
2055 mBarCollapseIconsOn (props
.mBarCollapseIconsOn
),
2056 mBarDragHintsOn (props
.mBarDragHintsOn
),
2058 mMinCBarDim(props
.mMinCBarDim
),
2059 mResizeHandleSize(props
.mResizeHandleSize
)
2062 cbCommonPaneProperties
& cbCommonPaneProperties::operator=(const cbCommonPaneProperties
& props
)
2064 mRealTimeUpdatesOn
= props
.mRealTimeUpdatesOn
;
2065 mOutOfPaneDragOn
= props
.mOutOfPaneDragOn
;
2066 mExactDockPredictionOn
= props
.mExactDockPredictionOn
;
2067 mNonDestructFrictionOn
= props
.mNonDestructFrictionOn
;
2068 mShow3DPaneBorderOn
= props
.mShow3DPaneBorderOn
;
2069 mBarFloatingOn
= props
.mBarFloatingOn
;
2070 mRowProportionsOn
= props
.mRowProportionsOn
;
2071 mColProportionsOn
= props
.mColProportionsOn
;
2072 mBarCollapseIconsOn
= props
.mBarCollapseIconsOn
;
2073 mBarDragHintsOn
= props
.mBarDragHintsOn
;
2075 mMinCBarDim
= props
.mMinCBarDim
;
2076 mResizeHandleSize
= props
.mResizeHandleSize
;
2081 /***** Implementation for class cbRowInfo *****/
2083 IMPLEMENT_DYNAMIC_CLASS( cbRowInfo
, wxObject
)
2085 cbRowInfo::cbRowInfo(void)
2087 : mNotFixedBarsCnt( false ),
2090 mpExpandedBar ( NULL
)
2093 cbRowInfo::~cbRowInfo()
2095 // nothing! all bars are removed using global bar
2096 // list in wxFrameLayout class
2099 /***** Implementation for class cbBarInfo *****/
2101 IMPLEMENT_DYNAMIC_CLASS( cbBarInfo
, wxObject
)
2103 cbBarInfo::cbBarInfo(void)
2106 mFloatingOn( true ),
2111 cbBarInfo::~cbBarInfo()
2116 /***** Implementation for class cbDockPane *****/
2118 IMPLEMENT_DYNAMIC_CLASS( cbDockPane
, wxObject
)
2120 // FIXME:: how to eliminate these cut&pasted constructors?
2122 cbDockPane::cbDockPane(void)
2123 : mLeftMargin ( 1 ),
2127 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2128 // since the real dimensions of the pane may not
2129 // be known, while inserting bars initially
2130 mPaneHeight( 32768 ),
2136 cbDockPane::cbDockPane( int alignment
, wxFrameLayout
* pPanel
)
2138 : mLeftMargin ( 1 ),
2142 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2143 // since the real dimensions of the pane may not
2144 // be known, while inserting bars initially
2145 mPaneHeight( 32768 ),
2146 mAlignment ( alignment
),
2147 mpLayout ( pPanel
),
2151 cbDockPane::~cbDockPane()
2154 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2157 WX_CLEAR_LIST(wxList
,mRowShapeData
)
2159 // NOTE:: control bar infromation structures are cleaned-up
2160 // in wxFrameLayout's destructor, using global control-bar list
2163 void cbDockPane::SetMargins( int top
, int bottom
, int left
, int right
)
2166 mBottomMargin
= bottom
;
2168 mRightMargin
= right
;
2171 /*** helpers of cbDockPane ***/
2173 void cbDockPane::PaintBarDecorations( cbBarInfo
* pBar
, wxDC
& dc
)
2175 cbDrawBarDecorEvent
evt( pBar
, dc
, this );
2177 mpLayout
->FirePluginEvent( evt
);
2180 void cbDockPane::PaintBarHandles( cbBarInfo
* pBar
, wxDC
& dc
)
2182 cbDrawBarHandlesEvent
evt( pBar
, dc
, this );
2184 mpLayout
->FirePluginEvent( evt
);
2187 void cbDockPane::PaintBar( cbBarInfo
* pBar
, wxDC
& dc
)
2189 PaintBarDecorations( pBar
, dc
);
2190 PaintBarHandles( pBar
, dc
);
2193 void cbDockPane::PaintRowHandles( cbRowInfo
* pRow
, wxDC
& dc
)
2195 cbDrawRowHandlesEvent
evt( pRow
, dc
, this );
2197 mpLayout
->FirePluginEvent( evt
);
2199 cbDrawRowDecorEvent
evt1( pRow
, dc
, this );
2201 mpLayout
->FirePluginEvent( evt1
);
2204 void cbDockPane::PaintRowBackground ( cbRowInfo
* pRow
, wxDC
& dc
)
2206 cbDrawRowBkGroundEvent
evt( pRow
, dc
, this );
2208 mpLayout
->FirePluginEvent( evt
);
2211 void cbDockPane::PaintRowDecorations( cbRowInfo
* pRow
, wxDC
& dc
)
2215 // decorations first
2216 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2218 PaintBarDecorations( pRow
->mBars
[i
], dc
);
2220 // then handles if present
2221 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2223 PaintBarHandles( pRow
->mBars
[i
], dc
);
2226 void cbDockPane::PaintRow( cbRowInfo
* pRow
, wxDC
& dc
)
2228 PaintRowBackground ( pRow
, dc
);
2229 PaintRowDecorations( pRow
, dc
);
2230 PaintRowHandles ( pRow
, dc
);
2233 void cbDockPane::PaintPaneBackground( wxDC
& dc
)
2235 cbDrawPaneBkGroundEvent
evt( dc
, this );
2237 mpLayout
->FirePluginEvent( evt
);
2240 void cbDockPane::PaintPaneDecorations( wxDC
& dc
)
2242 cbDrawPaneDecorEvent
evt( dc
, this );
2244 mpLayout
->FirePluginEvent( evt
);
2247 void cbDockPane::PaintPane( wxDC
& dc
)
2251 PaintPaneBackground( dc
);
2253 // first decorations
2254 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2256 PaintRowBackground( mRows
[i
], dc
);
2257 PaintRowDecorations( mRows
[i
], dc
);
2261 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2262 PaintRowHandles( mRows
[i
], dc
);
2265 PaintPaneDecorations( dc
);
2268 void cbDockPane::SizeBar( cbBarInfo
* pBar
)
2270 cbSizeBarWndEvent
evt( pBar
, this );
2272 mpLayout
->FirePluginEvent( evt
);
2276 void cbDockPane::SizeRowObjects( cbRowInfo
* pRow
)
2279 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2280 SizeBar( pRow
->mBars
[i
] );
2283 void cbDockPane::SizePaneObjects()
2286 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2287 SizeRowObjects( mRows
[i
] );
2290 wxDC
* cbDockPane::StartDrawInArea( const wxRect
& area
)
2294 cbStartDrawInAreaEvent
evt( area
, &pDc
, this );
2296 mpLayout
->FirePluginEvent( evt
);
2301 void cbDockPane::FinishDrawInArea( const wxRect
& area
)
2303 cbFinishDrawInAreaEvent
evt( area
, this );
2305 mpLayout
->FirePluginEvent( evt
);
2308 bool cbDockPane::IsFixedSize( cbBarInfo
* pInfo
)
2310 return ( pInfo
->mDimInfo
.mIsFixed
);
2313 int cbDockPane::GetNotFixedBarsCount( cbRowInfo
* pRow
)
2318 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2320 if ( !pRow
->mBars
[i
]->IsFixed() )
2327 void cbDockPane::RemoveBar( cbBarInfo
* pBar
)
2329 bool needsRestoring
= mProps
.mNonDestructFrictionOn
&&
2330 mpStoredRow
== pBar
->mpRow
;
2332 cbRemoveBarEvent
evt( pBar
, this );
2334 mpLayout
->FirePluginEvent( evt
);
2336 if ( needsRestoring
)
2338 SetRowShapeData( mpStoredRow
, &mRowShapeData
);
2344 void cbDockPane::SyncRowFlags( cbRowInfo
* pRow
)
2346 // setup mHasOnlyFixedBars flag for the row information
2347 pRow
->mHasOnlyFixedBars
= true;
2349 pRow
->mNotFixedBarsCnt
= 0;
2352 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2354 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2358 if ( !bar
.IsFixed() )
2360 pRow
->mHasOnlyFixedBars
= false;
2361 ++pRow
->mNotFixedBarsCnt
;
2366 void cbDockPane::FrameToPane( int* x
, int* y
)
2371 if ( mAlignment
== FL_ALIGN_TOP
||
2372 mAlignment
== FL_ALIGN_BOTTOM
2375 *x
-= mBoundsInParent
.x
;
2376 *y
-= mBoundsInParent
.y
;
2380 int rx
= *x
, ry
= *y
;
2382 *x
= ry
- mBoundsInParent
.y
;
2384 *y
= rx
- mBoundsInParent
.x
;
2388 void cbDockPane::PaneToFrame( int* x
, int* y
)
2390 if ( mAlignment
== FL_ALIGN_TOP
||
2391 mAlignment
== FL_ALIGN_BOTTOM
2394 *x
+= mBoundsInParent
.x
;
2395 *y
+= mBoundsInParent
.y
;
2399 int rx
= *x
, ry
= *y
;
2401 *x
= ry
+ mBoundsInParent
.x
;
2403 *y
= mBoundsInParent
.y
+ rx
;
2410 void cbDockPane::FrameToPane( wxRect
* pRect
)
2412 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2413 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2414 pRect
->y
+ pRect
->height
);
2416 FrameToPane( &upperLeft
.x
, &upperLeft
.y
);
2417 FrameToPane( &lowerRight
.x
, &lowerRight
.y
);
2419 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2420 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2422 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2423 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2426 void cbDockPane::PaneToFrame( wxRect
* pRect
)
2428 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2429 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2430 pRect
->y
+ pRect
->height
);
2432 PaneToFrame( &upperLeft
.x
, &upperLeft
.y
);
2433 PaneToFrame( &lowerRight
.x
, &lowerRight
.y
);
2435 //wxRect newRect = wxRect( upperLeft, lowerRight );
2437 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2438 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2440 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2441 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2444 int cbDockPane::GetRowAt( int paneY
)
2453 for ( ; i
!= mRows
.Count(); ++i
)
2455 int rowHeight
= mRows
[i
]->mRowHeight
;
2457 int third
= rowHeight
/3;
2459 if ( paneY
>= curY
&& paneY
< curY
+ third
)
2462 if ( paneY
>= curY
+ third
&& paneY
< curY
+ rowHeight
- third
)
2471 int cbDockPane::GetRowAt( int upperY
, int lowerY
)
2475 int range = lowerY - upperY;
2476 int oneThird = range / 3;
2478 wxNode* pRow = mRows.GetFirst();
2482 if ( lowerY <= 0 ) return -1;
2486 int rowHeight = GetRowHeight( (wxList*)pRow->GetData() );
2488 if ( upperY >= curY &&
2489 lowerY < curY ) return row;
2491 if ( upperY <= curY &&
2493 curY - upperY >= oneThird ) return row-1;
2495 if ( ( upperY < curY + rowHeight &&
2496 lowerY >= curY + rowHeight &&
2497 curY + rowHeight - lowerY >= oneThird )
2501 if ( lowerY <= curY + rowHeight ) return row;
2505 pRow = pRow->GetNext();
2509 int mid
= upperY
+ (lowerY
- upperY
)/2;
2517 for ( ; i
!= mRows
.Count(); ++i
)
2519 int rowHeight
= mRows
[i
]->mRowHeight
;
2521 if ( mid
>= curY
&& mid
< curY
+ rowHeight
) return i
;
2529 int cbDockPane::GetRowY( cbRowInfo
* pRow
)
2534 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2536 if ( mRows
[i
] == pRow
)
2539 curY
+= mRows
[i
]->mRowHeight
;
2545 bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo
* pRow
)
2547 while ( pRow
->mpPrev
)
2549 pRow
= pRow
->mpPrev
;
2551 if ( pRow
->mHasOnlyFixedBars
)
2559 bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo
* pRow
)
2561 while( pRow
->mpNext
)
2563 pRow
= pRow
->mpNext
;
2565 if ( pRow
->mHasOnlyFixedBars
)
2573 bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo
* pBar
)
2575 while( pBar
->mpPrev
)
2577 pBar
= pBar
->mpPrev
;
2579 if ( pBar
->IsFixed() )
2587 bool cbDockPane::HasNotFixedBarsRight( cbBarInfo
* pBar
)
2589 while( pBar
->mpNext
)
2591 pBar
= pBar
->mpNext
;
2593 if ( pBar
->IsFixed() )
2601 void cbDockPane::CalcLengthRatios( cbRowInfo
* pInRow
)
2607 // calc current-maximal-total-length of all maximized bars
2609 for ( i
= 0; i
!= pInRow
->mBars
.GetCount(); ++i
)
2611 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2613 if ( !bar
.IsFixed() )
2614 totalWidth
+= bar
.mBounds
.width
;
2617 // set up percentages of occupied space for each maximized bar
2619 for ( i
= 0; i
!= pInRow
->mBars
.Count(); ++i
)
2621 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2623 if ( !bar
.IsFixed() )
2624 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalWidth
);
2628 void cbDockPane::RecalcRowLayout( cbRowInfo
* pRow
)
2630 cbLayoutRowEvent
evt( pRow
, this );
2632 mpLayout
->FirePluginEvent( evt
);
2635 void cbDockPane::ExpandBar( cbBarInfo
* pBar
)
2637 mpLayout
->GetUpdatesManager().OnStartChanges();
2639 if ( !pBar
->mpRow
->mpExpandedBar
)
2641 // save ratios only when there arent any bars expanded yet
2643 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2646 ratios
.Alloc( pBar
->mpRow
->mNotFixedBarsCnt
);
2648 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2652 if ( !pCur
->IsFixed() )
2655 ratios
[ ratios
.GetCount() - 1 ] = pCur
->mLenRatio
;
2658 pCur
= pCur
->mpNext
;
2662 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2666 pCur
->mLenRatio
= 0.0; // minimize the rest
2668 pCur
= pCur
->mpNext
;
2671 pBar
->mLenRatio
= 1.0; // 100%
2672 pBar
->mBounds
.width
= 0;
2674 pBar
->mpRow
->mpExpandedBar
= pBar
;
2676 mpLayout
->RecalcLayout( false );
2678 mpLayout
->GetUpdatesManager().OnFinishChanges();
2679 mpLayout
->GetUpdatesManager().UpdateNow();
2682 void cbDockPane::ContractBar( cbBarInfo
* pBar
)
2684 mpLayout
->GetUpdatesManager().OnStartChanges();
2686 // FIXME: What's the purpose of this???
2687 // double ratio = 1.0/ double( pBar->mpRow->mNotFixedBarsCnt );
2689 // restore ratios which were present before expansion
2691 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2693 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2699 if ( !pCur
->IsFixed() )
2701 pCur
->mLenRatio
= ratios
[i
];
2705 pCur
= pCur
->mpNext
;
2711 pBar
->mpRow
->mpExpandedBar
= NULL
;
2713 mpLayout
->RecalcLayout( false );
2715 mpLayout
->GetUpdatesManager().OnFinishChanges();
2716 mpLayout
->GetUpdatesManager().UpdateNow();
2719 void cbDockPane::InitLinksForRow( cbRowInfo
* pRow
)
2722 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2724 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2729 bar
.mpPrev
= pRow
->mBars
[i
-1];
2731 if ( i
== pRow
->mBars
.Count() - 1 )
2734 bar
.mpNext
= pRow
->mBars
[i
+1];
2738 void cbDockPane::InitLinksForRows()
2741 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2743 cbRowInfo
& row
= *mRows
[i
];
2748 row
.mpPrev
= mRows
[i
-1];
2750 if ( i
== mRows
.Count() - 1 )
2753 row
.mpNext
= mRows
[i
+1];
2757 void cbDockPane::DoInsertBar( cbBarInfo
* pBar
, int rowNo
)
2761 if ( rowNo
== -1 || rowNo
>= (int)mRows
.Count() )
2763 pRow
= new cbRowInfo();
2765 if ( rowNo
== -1 && mRows
.Count() )
2767 mRows
.Insert( pRow
, 0 );
2775 pRow
= mRows
[rowNo
];
2777 if ( mProps
.mNonDestructFrictionOn
== true )
2779 // store original shape of the row (before the bar is inserted)
2783 GetRowShapeData( mpStoredRow
, &mRowShapeData
);
2787 if ( pRow
->mBars
.Count() )
2789 pRow
->mpExpandedBar
= NULL
;
2791 cbInsertBarEvent
insEvt( pBar
, pRow
, this );
2793 mpLayout
->FirePluginEvent( insEvt
);
2795 mpLayout
->GetUpdatesManager().OnRowWillChange( pRow
, this );
2798 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
, const wxRect
& atRect
)
2800 wxRect rect
= atRect
;
2801 FrameToPane( &rect
);
2803 pBarInfo
->mBounds
.x
= rect
.x
;
2804 pBarInfo
->mBounds
.width
= rect
.width
;
2805 pBarInfo
->mBounds
.height
= rect
.height
;
2807 int row
= GetRowAt( rect
.y
, rect
.y
+ rect
.height
);
2809 DoInsertBar( pBarInfo
, row
);
2812 void cbDockPane::InsertBar( cbBarInfo
* pBar
, cbRowInfo
* pIntoRow
)
2814 cbInsertBarEvent
insEvt( pBar
, pIntoRow
, this );
2816 mpLayout
->FirePluginEvent( insEvt
);
2818 mpLayout
->GetUpdatesManager().OnRowWillChange( pIntoRow
, this );
2821 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
)
2823 // set transient properties
2825 pBarInfo
->mpRow
= NULL
;
2826 pBarInfo
->mHasLeftHandle
= false;
2827 pBarInfo
->mHasRightHandle
= false;
2828 pBarInfo
->mLenRatio
= 0.0;
2830 // set preferred bar dimensions, according to the state in which
2831 // the bar is being inserted
2833 pBarInfo
->mBounds
.width
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].x
;
2834 pBarInfo
->mBounds
.height
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].y
;
2836 DoInsertBar( pBarInfo
, pBarInfo
->mRowNo
);
2839 void cbDockPane::RemoveRow( cbRowInfo
* pRow
)
2842 // first, hide all bar-windows in the removed row
2843 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2845 if ( pRow
->mBars
[i
]->mpBarWnd
)
2846 pRow
->mBars
[i
]->mpBarWnd
->Show( false );
2849 mRows
.Remove( pRow
);
2851 pRow
->mUMgrData
.SetDirty(true);
2854 void cbDockPane::InsertRow( cbRowInfo
* pRow
, cbRowInfo
* pBeforeRow
)
2860 mRows
.Insert( pRow
, mRows
.Index( pBeforeRow
) );
2864 pRow
->mUMgrData
.SetDirty(true);
2867 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2868 pRow
->mBars
[i
]->mUMgrData
.SetDirty( true );
2870 SyncRowFlags( pRow
);
2873 void cbDockPane::SetPaneWidth(int width
)
2875 if ( IsHorizontal() )
2876 mPaneWidth
= width
- mLeftMargin
- mRightMargin
;
2878 mPaneWidth
= width
- mTopMargin
- mBottomMargin
;
2882 void cbDockPane::SetBoundsInParent( const wxRect
& rect
)
2884 mBoundsInParent
= rect
;
2886 // set pane dimensions in local coordinates
2888 if ( IsHorizontal() )
2890 mPaneWidth
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2891 mPaneHeight
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2895 mPaneWidth
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2896 mPaneHeight
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2899 // convert bounding rectangles of all pane items into parent frame's coordinates
2901 wxBarIterator
i( mRows
);
2903 wxRect noMarginsRect
= mBoundsInParent
;
2905 noMarginsRect
.x
+= mLeftMargin
;
2906 noMarginsRect
.y
+= mTopMargin
;
2907 noMarginsRect
.width
-= ( mLeftMargin
+ mRightMargin
);
2908 noMarginsRect
.height
-= ( mTopMargin
+ mBottomMargin
);
2910 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2912 if ( mBoundsInParent
.width
< 0 ||
2913 mBoundsInParent
.height
< 0 )
2915 hide_rect( mBoundsInParent
);
2917 if ( noMarginsRect
.width
< 0 ||
2918 noMarginsRect
.height
< 0 )
2920 hide_rect( noMarginsRect
);
2922 // calculate mBoundsInParent for each item in the pane
2926 cbBarInfo
& bar
= i
.BarInfo();
2928 cbRowInfo
* pRowInfo
= bar
.mpRow
;
2930 // set up row info, if this is first bar in the row
2932 if ( pRowInfo
&& bar
.mpPrev
== NULL
)
2934 pRowInfo
->mBoundsInParent
.y
= pRowInfo
->mRowY
;
2935 pRowInfo
->mBoundsInParent
.x
= 0;
2936 pRowInfo
->mBoundsInParent
.width
= mPaneWidth
;
2937 pRowInfo
->mBoundsInParent
.height
= pRowInfo
->mRowHeight
;
2939 PaneToFrame( &pRowInfo
->mBoundsInParent
);
2941 clip_rect_against_rect( pRowInfo
->mBoundsInParent
, noMarginsRect
);
2944 wxRect bounds
= bar
.mBounds
;
2946 // exclude dimensions of handles, when calculating
2947 // bar's bounds in parent (i.e. "visual bounds")
2949 if ( bar
.mHasLeftHandle
)
2951 bounds
.x
+= mProps
.mResizeHandleSize
;
2952 bounds
.width
-= mProps
.mResizeHandleSize
;
2955 if ( bar
.mHasRightHandle
)
2957 bounds
.width
-= mProps
.mResizeHandleSize
;
2959 PaneToFrame( &bounds
);
2961 clip_rect_against_rect( bounds
, noMarginsRect
);
2963 bar
.mBoundsInParent
= bounds
;
2967 bool cbDockPane::BarPresent( cbBarInfo
* pBar
)
2969 wxBarIterator
iter( mRows
);
2971 while( iter
.Next() )
2973 if ( &iter
.BarInfo() == pBar
) return true;
2978 cbRowInfo
* cbDockPane::GetRow( int row
)
2980 if ( row
>= (int)mRows
.Count() ) return NULL
;
2982 return mRows
[ row
];
2985 int cbDockPane::GetRowIndex( cbRowInfo
* pRow
)
2988 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2990 if ( mRows
[i
] == pRow
)
2994 wxFAIL_MSG(wxT("Row must be present to call cbDockPane::GetRowIndex()"));
2999 int cbDockPane::GetPaneHeight()
3001 // first, recalculate row heights and the Y-positions
3003 cbLayoutRowsEvent
evt( this );
3004 mpLayout
->FirePluginEvent( evt
);
3008 if ( IsHorizontal() )
3010 height
+= mTopMargin
+ mBottomMargin
;
3012 height
+= mLeftMargin
+ mRightMargin
;
3014 int count
= mRows
.Count();
3018 height
+= mRows
[count
-1]->mRowY
+ mRows
[count
-1]->mRowHeight
;
3023 int cbDockPane::GetAlignment()
3028 bool cbDockPane::MatchesMask( int paneMask
)
3032 // FIXME:: use array instead of switch()
3036 case FL_ALIGN_TOP
: thisMask
= FL_ALIGN_TOP_PANE
; break;
3037 case FL_ALIGN_BOTTOM
: thisMask
= FL_ALIGN_BOTTOM_PANE
;break;
3038 case FL_ALIGN_LEFT
: thisMask
= FL_ALIGN_LEFT_PANE
; break;
3039 case FL_ALIGN_RIGHT
: thisMask
= FL_ALIGN_RIGHT_PANE
; break;
3042 wxFAIL_MSG(wxT("Bad FL alignment type detected in cbDockPane::MatchesMask()"));
3045 return ( thisMask
& paneMask
) != 0;
3048 void cbDockPane::RecalcLayout()
3050 // first, reposition rows and items vertically
3052 cbLayoutRowsEvent
evt( this );
3053 mpLayout
->FirePluginEvent( evt
);
3055 // then horizontally in each row
3058 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3059 RecalcRowLayout( mRows
[i
] );
3062 int cbDockPane::GetDockingState()
3064 if ( mAlignment
== FL_ALIGN_TOP
||
3065 mAlignment
== FL_ALIGN_BOTTOM
)
3067 return wxCBAR_DOCKED_HORIZONTALLY
;
3070 return wxCBAR_DOCKED_VERTICALLY
;
3073 inline bool cbDockPane::HasPoint( const wxPoint
& pos
, int x
, int y
,
3074 int width
, int height
)
3076 return ( pos
.x
>= x
&&
3078 pos
.x
< x
+ width
&&
3079 pos
.y
< y
+ height
);
3082 int cbDockPane::HitTestPaneItems( const wxPoint
& pos
,
3091 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3093 cbRowInfo
& row
= *mRows
[i
];
3097 // hit-test handles of the row, if present
3099 if ( row
.mHasUpperHandle
)
3101 if ( HasPoint( pos
, 0, row
.mRowY
,
3102 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3104 return CB_UPPER_ROW_HANDLE_HITTED
;
3107 if ( row
.mHasLowerHandle
)
3109 if ( HasPoint( pos
, 0, row
.mRowY
+ row
.mRowHeight
- mProps
.mResizeHandleSize
,
3110 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3112 return CB_LOWER_ROW_HANDLE_HITTED
;
3115 // hit-test bar handles and bar content
3118 for ( k
= 0; k
!= row
.mBars
.Count(); ++k
)
3120 cbBarInfo
& bar
= *row
.mBars
[k
];
3121 wxRect
& bounds
= bar
.mBounds
;
3125 if ( bar
.mHasLeftHandle
)
3127 if ( HasPoint( pos
, bounds
.x
, bounds
.y
,
3128 mProps
.mResizeHandleSize
, bounds
.height
) )
3130 return CB_LEFT_BAR_HANDLE_HITTED
;
3133 if ( bar
.mHasRightHandle
)
3135 if ( HasPoint( pos
, bounds
.x
+ bounds
.width
- mProps
.mResizeHandleSize
, bounds
.y
,
3136 mProps
.mResizeHandleSize
, bounds
.height
) )
3138 return CB_RIGHT_BAR_HANDLE_HITTED
;
3141 if ( HasPoint( pos
, bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
) )
3142 return CB_BAR_CONTENT_HITTED
;
3144 } // hit-test next bar
3148 return CB_NO_ITEMS_HITTED
;
3151 void cbDockPane::GetBarResizeRange( cbBarInfo
* pBar
, int* from
, int *till
,
3152 bool forLeftHandle
)
3154 cbBarInfo
* pGivenBar
= pBar
;
3158 // calc unavailable space from the left
3160 while( pBar
->mpPrev
)
3162 pBar
= pBar
->mpPrev
;
3164 if ( !pBar
->IsFixed() ) notFree
+= mProps
.mMinCBarDim
.x
;
3165 else notFree
+= pBar
->mBounds
.width
;
3174 // calc unavailable space from the right
3176 while( pBar
->mpNext
)
3178 pBar
= pBar
->mpNext
;
3180 if ( pBar
->mBounds
.x
>= mPaneWidth
) break;
3182 // treat not-fixed bars as minimized
3184 if ( !pBar
->IsFixed() )
3186 notFree
+= mProps
.mMinCBarDim
.x
;
3189 if ( pBar
->mBounds
.x
+ pBar
->mBounds
.width
>= mPaneWidth
)
3191 notFree
+= mPaneWidth
- pBar
->mBounds
.x
;
3195 notFree
+= pBar
->mBounds
.width
;
3200 *till
= mPaneWidth
- notFree
;
3202 // do not let resizing totally deform the bar itself
3204 if ( forLeftHandle
)
3206 (*till
) -= mProps
.mMinCBarDim
.x
;
3209 (*from
) += mProps
.mMinCBarDim
.x
;
3212 int cbDockPane::GetMinimalRowHeight( cbRowInfo
* pRow
)
3214 int height
= mProps
.mMinCBarDim
.y
;
3217 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3219 if ( pRow
->mBars
[i
]->IsFixed() )
3220 height
= wxMax( height
, pRow
->mBars
[i
]->mBounds
.height
);
3223 if ( pRow
->mHasUpperHandle
)
3224 height
+= mProps
.mResizeHandleSize
;
3226 if ( pRow
->mHasLowerHandle
)
3227 height
+= mProps
.mResizeHandleSize
;
3232 void cbDockPane::SetRowHeight( cbRowInfo
* pRow
, int newHeight
)
3234 if ( pRow
->mHasUpperHandle
)
3236 newHeight
-= mProps
.mResizeHandleSize
;
3238 if ( pRow
->mHasLowerHandle
)
3240 newHeight
-= mProps
.mResizeHandleSize
;
3243 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3245 if ( !pRow
->mBars
[i
]->IsFixed() )
3246 pRow
->mBars
[i
]->mBounds
.height
= newHeight
;
3250 void cbDockPane::GetRowResizeRange( cbRowInfo
* pRow
, int* from
, int* till
,
3251 bool forUpperHandle
)
3253 cbRowInfo
* pGivenRow
= pRow
;
3255 // calc unavailable space from above
3259 while( pRow
->mpPrev
)
3261 pRow
= pRow
->mpPrev
;
3263 notFree
+= GetMinimalRowHeight( pRow
);
3269 // allow accupy the client window space by resizing pane rows
3270 if ( mAlignment
== FL_ALIGN_BOTTOM
)
3272 *from
-= mpLayout
->GetClientHeight();
3274 if ( mAlignment
== FL_ALIGN_RIGHT
)
3276 *from
-= mpLayout
->GetClientWidth();
3278 // calc unavailable space from below
3284 while( pRow
->mpNext
)
3286 pRow
= pRow
->mpNext
;
3288 notFree
+= GetMinimalRowHeight( pRow
);
3292 *till
= mPaneHeight
- notFree
;
3294 // allow adjustinig pane space vs. client window space by resizing pane row heights
3296 if ( mAlignment
== FL_ALIGN_TOP
)
3298 *till
+= mpLayout
->GetClientHeight();
3300 if ( mAlignment
== FL_ALIGN_LEFT
)
3302 *till
+= mpLayout
->GetClientWidth();
3304 // do not let the resizing of the row totally squeeze the row itself
3306 cbRowInfo
& row
= *pGivenRow
;
3308 if ( forUpperHandle
)
3310 *till
= row
.mRowY
+ row
.mRowHeight
- GetMinimalRowHeight( pGivenRow
);
3312 if ( row
.mHasUpperHandle
)
3314 *till
-= mProps
.mResizeHandleSize
;
3318 *from
+= GetMinimalRowHeight( pGivenRow
);
3320 if ( row
.mHasLowerHandle
)
3322 *from
-= mProps
.mResizeHandleSize
;
3326 void cbDockPane::ResizeRow( cbRowInfo
* pRow
, int ofs
,
3327 bool forUpperHandle
)
3329 cbResizeRowEvent
evt( pRow
, ofs
, forUpperHandle
, this );
3331 mpLayout
->FirePluginEvent( evt
);
3334 void cbDockPane::ResizeBar( cbBarInfo
* pBar
, int ofs
,
3335 bool forLeftHandle
)
3337 pBar
->mpRow
->mpExpandedBar
= NULL
;
3339 mpLayout
->GetUpdatesManager().OnStartChanges();
3341 wxRect
& bounds
= pBar
->mBounds
;
3343 if ( forLeftHandle
)
3345 // do not allow bar width become less then minimal
3346 if ( bounds
.x
+ ofs
> bounds
.x
+ bounds
.width
- mProps
.mMinCBarDim
.x
)
3348 bounds
.width
= mProps
.mMinCBarDim
.x
;
3354 bounds
.width
-= ofs
;
3359 // move bar left if necessary
3360 if ( bounds
.width
+ ofs
< mProps
.mMinCBarDim
.x
)
3362 bounds
.x
= bounds
.x
+ bounds
.width
+ ofs
- mProps
.mMinCBarDim
.x
;
3363 bounds
.width
= mProps
.mMinCBarDim
.x
;
3366 // resize right border only
3367 bounds
.width
+= ofs
;
3371 cbRowInfo
* pToRow
= pBar
->mpRow
;
3373 this->RemoveBar( pBar
);
3375 InsertBar( pBar
, pToRow
);
3377 mpLayout
->RecalcLayout(false);
3379 mpLayout
->GetUpdatesManager().OnFinishChanges();
3380 mpLayout
->GetUpdatesManager().UpdateNow();
3384 /*** row/bar resizing related methods ***/
3386 void cbDockPane::DrawVertHandle( wxDC
& dc
, int x
, int y
, int height
)
3388 int lower
= y
+ height
;
3390 dc
.SetPen( mpLayout
->mLightPen
);
3391 dc
.DrawLine( x
,y
, x
, lower
);
3393 dc
.SetPen( mpLayout
->mGrayPen
);
3395 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3398 dc
.DrawLine( x
,y
, x
, lower
);
3401 dc
.SetPen( mpLayout
->mDarkPen
);
3403 dc
.DrawLine( x
,y
, x
, lower
);
3405 dc
.SetPen( mpLayout
->mBlackPen
);
3407 dc
.DrawLine( x
,y
, x
, lower
);
3410 void cbDockPane::DrawHorizHandle( wxDC
& dc
, int x
, int y
, int width
)
3412 int right
= x
+ width
;
3414 dc
.SetPen( mpLayout
->mLightPen
);
3415 dc
.DrawLine( x
,y
, right
, y
);
3417 dc
.SetPen( mpLayout
->mGrayPen
);
3420 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3423 dc
.DrawLine( x
,y
, right
, y
);
3426 dc
.SetPen( mpLayout
->mDarkPen
);
3427 dc
.DrawLine( x
,y
, right
, ++y
);
3429 dc
.SetPen( mpLayout
->mBlackPen
);
3430 dc
.DrawLine( x
,y
, right
, ++y
);
3433 cbBarInfo
* cbDockPane::GetBarInfoByWindow( wxWindow
* pBarWnd
)
3435 wxBarIterator
i( mRows
);
3439 if ( i
.BarInfo().mpBarWnd
== pBarWnd
)
3441 return &i
.BarInfo();
3446 void cbDockPane::GetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3450 WX_CLEAR_LIST(wxList
,*pLst
);
3456 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3458 cbBarInfo
& bar
= *pRow
->mBars
[i
];
3460 cbBarShapeData
* pData
= new cbBarShapeData();
3462 pLst
->Append( (wxObject
*)pData
);
3464 pData
->mBounds
= bar
.mBounds
;
3465 pData
->mLenRatio
= bar
.mLenRatio
;
3469 void cbDockPane::SetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3471 if ( pLst
->GetFirst() == NULL
)
3474 wxObjectList::compatibility_iterator pData
= pLst
->GetFirst();
3477 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3479 wxASSERT( pData
); // DBG::
3481 cbBarInfo
& bar
= *pRow
->mBars
[i
];;
3483 cbBarShapeData
& data
= *((cbBarShapeData
*)pData
->GetData());
3485 bar
.mBounds
= data
.mBounds
;
3486 bar
.mLenRatio
= data
.mLenRatio
;
3488 pData
= pData
->GetNext();
3492 /***** Implementation for class cbUpdatesManagerBase *****/
3494 IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase
, wxObject
)
3496 /***** Implementation for class cbPluginBase *****/
3498 IMPLEMENT_ABSTRACT_CLASS( cbPluginBase
, wxEvtHandler
)
3500 cbPluginBase::~cbPluginBase()
3505 bool cbPluginBase::ProcessEvent(wxEvent
& event
)
3507 if ( mPaneMask
== wxALL_PANES
)
3509 return wxEvtHandler::ProcessEvent( event
);
3511 // extract mask info. from received event
3513 cbPluginEvent
& evt
= *( (cbPluginEvent
*)&event
);
3515 if ( evt
.mpPane
== 0 &&
3516 mPaneMask
== wxALL_PANES
)
3518 return wxEvtHandler::ProcessEvent( event
);
3522 switch ( evt
.mpPane
->mAlignment
)
3524 case FL_ALIGN_TOP
: mask
= FL_ALIGN_TOP_PANE
; break;
3525 case FL_ALIGN_BOTTOM
: mask
= FL_ALIGN_BOTTOM_PANE
;break;
3526 case FL_ALIGN_LEFT
: mask
= FL_ALIGN_LEFT_PANE
; break;
3527 case FL_ALIGN_RIGHT
: mask
= FL_ALIGN_RIGHT_PANE
; break;
3530 // if event's pane maks matches the plugin's mask
3532 if ( mPaneMask
& mask
)
3534 return wxEvtHandler::ProcessEvent( event
);
3536 // otherwise pass to the next handler if present
3538 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event
) )