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
)
297 for ( 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
),
333 for ( 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();
425 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
427 if ( mAllBars
[i
]->mpBarWnd
)
429 mAllBars
[i
]->mpBarWnd
->Destroy();
430 mAllBars
[i
]->mpBarWnd
= NULL
;
435 void wxFrameLayout::ShowFloatedWindows( bool show
)
437 wxNode
* pNode
= mFloatedFrames
.First();
441 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
445 pNode
= pNode
->Next();
449 wxFrameLayout::~wxFrameLayout()
458 // destoy the chain of plugins from left to right
460 wxEvtHandler
* pCur
= mpTopPlugin
;
464 while ( pCur
->GetPreviousHandler() )
466 pCur
= pCur
->GetPreviousHandler();
470 wxEvtHandler
* pNext
= pCur
->GetNextHandler();
477 // 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
)
515 void wxFrameLayout::EnableFloating( bool enable
)
517 mFloatingOn
= enable
&& CanReparent();
520 void wxFrameLayout::Activate()
526 ShowFloatedWindows( TRUE
);
529 void wxFrameLayout::Deactivate()
531 ShowFloatedWindows( FALSE
);
538 void wxFrameLayout::SetFrameClient( wxWindow
* pFrameClient
)
540 mpFrameClient
= pFrameClient
;
543 wxWindow
* wxFrameLayout::GetFrameClient()
545 return mpFrameClient
;
548 cbUpdatesManagerBase
& wxFrameLayout::GetUpdatesManager()
551 mpUpdatesMgr
= CreateUpdatesManager();
553 return *mpUpdatesMgr
;
556 void wxFrameLayout::SetUpdatesManager( cbUpdatesManagerBase
* pUMgr
)
561 mpUpdatesMgr
= pUMgr
;
563 mpUpdatesMgr
->SetLayout( this );
566 cbUpdatesManagerBase
* wxFrameLayout::CreateUpdatesManager()
568 return new cbGCUpdatesMgr( this );
569 //return new cbSimpleUpdatesMgr( this );
572 void wxFrameLayout::AddBar( wxWindow
* pBarWnd
,
573 const cbDimInfo
& dimInfo
,
577 const wxString
& name
,
582 if ( pBarWnd
&& spyEvents
)
584 // hook up spy to bar window
585 cbBarSpy
* pSpy
= new cbBarSpy( this );
587 pSpy
->SetBarWindow( pBarWnd
);
588 pBarWnd
->PushEventHandler( pSpy
);
590 mBarSpyList
.Append( pSpy
);
593 cbBarInfo
* pInfo
= new cbBarInfo();
596 pInfo
->mpBarWnd
= pBarWnd
;
597 pInfo
->mDimInfo
= dimInfo
;
598 pInfo
->mState
= state
;
599 pInfo
->mAlignment
= alignment
;
600 pInfo
->mRowNo
= rowNo
;
601 pInfo
->mBounds
.x
= columnPos
;
603 mAllBars
.Add( pInfo
);
605 DoSetBarState( pInfo
);
608 bool wxFrameLayout::RedockBar( cbBarInfo
* pBar
,
609 const wxRect
& shapeInParent
,
615 pToPane
= HitTestPanes( shapeInParent
, NULL
);
619 return FALSE
; // bar's shape does not hit any pane
620 // - redocking is NOT possible
622 cbDockPane
* pBarPane
= GetBarPane( pBar
);
626 GetUpdatesManager().OnStartChanges();
628 pBarPane
->RemoveBar( pBar
);
630 // FIXME FIXME:: the below recalc. may be a *huge* performance
631 // hit, it could be eliminated though...
632 // but first the "pane-postion-changed" problem
635 RecalcLayout( FALSE
);
637 pToPane
->InsertBar( pBar
, shapeInParent
);
639 RecalcLayout( FALSE
);
641 // finish update "transaction"
645 GetUpdatesManager().OnFinishChanges();
646 GetUpdatesManager().UpdateNow();
652 cbBarInfo
* wxFrameLayout::FindBarByName( const wxString
& name
)
655 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
656 if ( mAllBars
[i
]->mName
== name
)
662 cbBarInfo
* wxFrameLayout::FindBarByWindow( const wxWindow
* pWnd
)
665 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
666 if ( mAllBars
[i
]->mpBarWnd
== pWnd
)
672 BarArrayT
& wxFrameLayout::GetBars()
677 void wxFrameLayout::SetBarState( cbBarInfo
* pBar
, int newState
, bool updateNow
)
679 if ( newState
== wxCBAR_FLOATING
&& !mFloatingOn
)
685 GetUpdatesManager().OnStartChanges();
687 pBar
->mUMgrData
.SetDirty(TRUE
);
689 // check bar's previous state
691 if ( pBar
->mState
!= wxCBAR_HIDDEN
&& pBar
->mState
!= wxCBAR_FLOATING
)
696 bool success
= LocateBar( pBar
, &pRow
, &pPane
);
698 wxASSERT( success
); // DBG::
700 // save LRU-dim info before removing bar
702 pBar
->mDimInfo
.mLRUPane
= pPane
->GetAlignment();
703 pBar
->mDimInfo
.mBounds
[ pPane
->GetAlignment() ] = pBar
->mBounds
;
705 // remove it from the pane it was docked on
707 pPane
->RemoveBar( pBar
);
711 if ( pBar
->mState
== wxCBAR_FLOATING
&& newState
!= wxCBAR_FLOATING
)
713 // remove bar's window form the containing mini-frame
714 // and set it's parent to be layout's parent frame
716 if ( pBar
->mpBarWnd
)
718 pBar
->mpBarWnd
->Show(FALSE
); // to avoid flicker upon reparenting
720 wxNode
* pNode
= mFloatedFrames
.First();
724 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
726 if ( pFFrm
->GetBar() == pBar
)
728 pFFrm
->Show( FALSE
); // reduces flicker sligthly
730 ReparentWindow( pBar
->mpBarWnd
, &GetParentFrame() );
732 pBar
->mBounds
= pBar
->mDimInfo
.mBounds
[ pBar
->mDimInfo
.mLRUPane
];
734 if ( newState
!= wxCBAR_HIDDEN
)
736 pBar
->mAlignment
= pBar
->mDimInfo
.mLRUPane
;
738 mFloatedFrames
.DeleteNode( pNode
);
740 pFFrm
->Show( FALSE
);
741 pFFrm
->Destroy(); break;
744 pNode
= pNode
->Next();
747 // FOR NOW:: excessive!
748 //if ( mpFrameClient ) mpFrameClient->Refresh();
750 mClientWndRefreshPending
= TRUE
;
754 pBar
->mState
= newState
;
756 DoSetBarState( pBar
);
762 GetUpdatesManager().OnFinishChanges();
763 GetUpdatesManager().UpdateNow();
767 void wxFrameLayout::InverseVisibility( cbBarInfo
* pBar
)
769 wxASSERT( pBar
); // DBG::
771 // "inverse" bar-visibility of the selected bar
775 if ( pBar
->mState
== wxCBAR_HIDDEN
)
777 if ( pBar
->mAlignment
== -1 )
779 pBar
->mAlignment
= 0; // just remove "-1" marking
780 newState
= wxCBAR_FLOATING
;
783 if ( pBar
->mAlignment
== FL_ALIGN_TOP
||
784 pBar
->mAlignment
== FL_ALIGN_BOTTOM
)
786 newState
= wxCBAR_DOCKED_HORIZONTALLY
;
788 newState
= wxCBAR_DOCKED_VERTICALLY
;
792 newState
= wxCBAR_HIDDEN
;
794 if ( pBar
->mState
== wxCBAR_FLOATING
)
796 pBar
->mAlignment
= -1;
799 this->SetBarState( pBar
, newState
, TRUE
);
801 if ( newState
== wxCBAR_FLOATING
)
803 this->RepositionFloatedBar( pBar
);
806 void wxFrameLayout::ApplyBarProperties( cbBarInfo
* pBar
)
808 if ( pBar
->mState
== wxCBAR_FLOATING
)
810 RepositionFloatedBar( pBar
);
813 if ( pBar
->mState
== wxCBAR_DOCKED_HORIZONTALLY
||
814 pBar
->mState
== wxCBAR_DOCKED_VERTICALLY
822 void wxFrameLayout::RepositionFloatedBar( cbBarInfo
* pBar
)
824 if ( !mFloatingOn
) return;
826 wxNode
* pNode
= mFloatedFrames
.First();
830 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
832 if ( pFFrm
->GetBar() == pBar
)
834 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
839 GetParentFrame().ClientToScreen( &x
, &y
);
841 pFFrm
->PositionFloatedWnd( x
,y
,
848 pNode
= pNode
->Next();
852 void wxFrameLayout::DoSetBarState( cbBarInfo
* pBar
)
854 if ( pBar
->mState
!= wxCBAR_FLOATING
&&
855 pBar
->mState
!= wxCBAR_HIDDEN
)
859 mPanes
[pBar
->mAlignment
]->InsertBar( pBar
);
861 if ( pBar
->mState
== wxCBAR_HIDDEN
)
865 if ( pBar
->mpBarWnd
)
867 pBar
->mpBarWnd
->Show( FALSE
);
871 if ( !mFloatingOn
) return;
875 if ( pBar
->mpBarWnd
== NULL
|| !CanReparent() )
877 // FOR NOW:: just hide it
879 if ( pBar
->mpBarWnd
)
881 pBar
->mpBarWnd
->Show( FALSE
);
883 pBar
->mState
= wxCBAR_HIDDEN
;
888 cbFloatedBarWindow
* pMiniFrm
= new cbFloatedBarWindow();
890 pMiniFrm
->SetBar( pBar
);
891 pMiniFrm
->SetLayout( this );
893 pMiniFrm
->Create( &GetParentFrame(), -1, pBar
->mName
,
896 wxFRAME_FLOAT_ON_PARENT
| wxFRAME_TOOL_WINDOW
899 pMiniFrm
->SetClient( pBar
->mpBarWnd
);
901 ReparentWindow( pBar
->mpBarWnd
, pMiniFrm
);
903 mFloatedFrames
.Append( pMiniFrm
);
905 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
907 // check if it wasn't floated anytime before
909 if ( bounds
.width
== -1 )
911 wxRect
& clntRect
= GetClientRect();
913 // adjust position into which the next floated bar will be placed
915 if ( mNextFloatedWndPos
.x
+ bounds
.width
> clntRect
.width
)
917 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
919 if ( mNextFloatedWndPos
.y
+ bounds
.height
> clntRect
.height
)
921 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
923 bounds
.x
= mNextFloatedWndPos
.x
+ clntRect
.x
;
924 bounds
.y
= mNextFloatedWndPos
.y
+ clntRect
.y
;
926 bounds
.width
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].x
;
927 bounds
.height
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].y
;
929 mNextFloatedWndPos
.x
+= mFloatingPosStep
.x
;
930 mNextFloatedWndPos
.y
+= mFloatingPosStep
.y
;
933 pMiniFrm
->Show( TRUE
);
935 // FIXME:: this is excessive
936 pBar
->mpBarWnd
->Show(TRUE
);
940 void wxFrameLayout::RemoveBar( cbBarInfo
* pBarInfo
)
942 // first, try to "guess" what was the perviouse state of the bar
947 if ( LocateBar( pBarInfo
, &pRow
, &pPane
) )
949 // ...aha, bar was docked into one of the panes,
950 // remove it from there
952 pPane
->RemoveBar( pBarInfo
);
956 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
958 if ( mAllBars
[i
] == pBarInfo
)
960 #if wxCHECK_VERSION(2,3,2)
961 mAllBars
.RemoveAt(i
);
965 if ( pBarInfo
->mpBarWnd
) // hides it's window
967 pBarInfo
->mpBarWnd
->Show( FALSE
);
974 wxFAIL_MSG("bar info should be present in the list of all bars of all panes");
977 bool wxFrameLayout::LocateBar( cbBarInfo
* pBarInfo
,
979 cbDockPane
** ppPane
)
985 for ( n
= 0; n
!= MAX_PANES
; ++n
)
987 wxBarIterator
i( mPanes
[n
]->GetRowList() );
991 if ( &i
.BarInfo() == pBarInfo
)
993 (*ppPane
) = mPanes
[n
];
994 (*ppRow
) = &i
.RowInfo();
1003 void wxFrameLayout::RecalcLayout( bool repositionBarsNow
)
1005 mRecalcPending
= FALSE
;
1007 int frmWidth
, frmHeight
;
1008 mpFrame
->GetClientSize( &frmWidth
, &frmHeight
);
1015 // pane positioning priorities in decreasing order:
1016 // top, bottom, left, right
1020 cbDockPane
* pPane
= mPanes
[ FL_ALIGN_TOP
];
1022 pPane
->SetPaneWidth( frmWidth
);
1023 pPane
->RecalcLayout();
1025 paneHeight
= pPane
->GetPaneHeight();
1029 rect
.width
= frmWidth
;
1030 rect
.height
= wxMin( paneHeight
, frmHeight
- curY
);
1032 pPane
->SetBoundsInParent( rect
);
1036 // setup BOTTOM pane
1038 pPane
= mPanes
[ FL_ALIGN_BOTTOM
];
1040 pPane
->SetPaneWidth( frmWidth
);
1041 pPane
->RecalcLayout();
1043 paneHeight
= pPane
->GetPaneHeight();
1046 rect
.y
= wxMax( frmHeight
- paneHeight
, curY
);
1047 rect
.width
= frmWidth
;
1048 rect
.height
= frmHeight
- rect
.y
;
1050 pPane
->SetBoundsInParent( rect
);
1054 pPane
= mPanes
[ FL_ALIGN_LEFT
];
1057 pPane
->SetPaneWidth( rect
.y
- curY
);
1059 pPane
->RecalcLayout();
1060 paneHeight
= pPane
->GetPaneHeight();
1063 rect
.height
= rect
.y
- curY
;
1066 rect
.width
= wxMin( paneHeight
, frmWidth
);
1068 pPane
->SetBoundsInParent( rect
);
1074 pPane
= mPanes
[ FL_ALIGN_RIGHT
];
1076 // left pane's height
1077 pPane
->SetPaneWidth( rect
.height
);
1079 pPane
->RecalcLayout();
1080 paneHeight
= pPane
->GetPaneHeight();
1082 // left pane's height
1083 rect
.height
= rect
.height
;
1084 rect
.x
= wxMax( frmWidth
- paneHeight
, curX
);
1086 rect
.width
= frmWidth
- rect
.x
;
1088 pPane
->SetBoundsInParent( rect
);
1090 // recalc bounds of the client-window
1092 mClntWndBounds
.x
= mPanes
[FL_ALIGN_LEFT
]->mBoundsInParent
.x
+
1093 mPanes
[FL_ALIGN_LEFT
]->mBoundsInParent
.width
;
1094 mClntWndBounds
.y
= mPanes
[FL_ALIGN_TOP
]->mBoundsInParent
.y
+
1095 mPanes
[FL_ALIGN_TOP
]->mBoundsInParent
.height
;
1097 mClntWndBounds
.width
= mPanes
[FL_ALIGN_RIGHT
]->mBoundsInParent
.x
-
1099 mClntWndBounds
.height
= mPanes
[FL_ALIGN_BOTTOM
]->mBoundsInParent
.y
-
1102 if ( repositionBarsNow
)
1107 int wxFrameLayout::GetClientHeight()
1109 // for better portablility wxWindow::GetSzie() is not used here
1111 return mClntWndBounds
.height
;
1114 int wxFrameLayout::GetClientWidth()
1116 // for better portablility wxWindow::GetSzie() is not used here
1118 return mClntWndBounds
.width
;
1121 void wxFrameLayout::PositionClientWindow()
1123 if ( mpFrameClient
)
1125 if ( mClntWndBounds
.width
>= 1 && mClntWndBounds
.height
>= 1 )
1127 mpFrameClient
->SetSize( mClntWndBounds
.x
, mClntWndBounds
.y
,
1128 mClntWndBounds
.width
, mClntWndBounds
.height
, 0 );
1130 if ( !mpFrameClient
->IsShown() )
1132 mpFrameClient
->Show( TRUE
);
1135 mpFrameClient
->Show( FALSE
);
1139 void wxFrameLayout::PositionPanes()
1141 PositionClientWindow();
1143 // FOR NOW:: excessive updates!
1144 // reposition bars within all panes
1147 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1148 mPanes
[i
]->SizePaneObjects();
1151 void wxFrameLayout::OnSize( wxSizeEvent
& event
)
1153 if ( event
.GetEventObject() == (wxObject
*) mpFrame
)
1158 /*** protected members ***/
1160 void wxFrameLayout::HideBarWindows()
1163 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
1164 if ( mAllBars
[i
]->mpBarWnd
&& mAllBars
[i
]->mState
!= wxCBAR_FLOATING
)
1165 mAllBars
[i
]->mpBarWnd
->Show( FALSE
);
1167 // then floated frames
1169 ShowFloatedWindows( FALSE
);
1171 if ( mpFrameClient
)
1173 mpFrameClient
->Show( FALSE
);
1176 void wxFrameLayout::UnhookFromFrame()
1178 // NOTE:: the SetEvtHandlerEnabled() method is not used
1179 // here, since it is assumed, that unhooking layout
1180 // from window may result destroying of the layout itself
1182 // BUG BUG BUG (wx):: this would not be a problem if
1183 // wxEvtHandler's destructor would check if
1184 // this handler is currently the top-most
1185 // handler of some window, and additionally
1186 // to the reconnecting itself from the chain
1187 // it would also re-setup current event handler
1188 // of the window using wxWindow::SetEventHandler()
1192 if ( mpFrame
->GetEventHandler() == this )
1194 mpFrame
->PopEventHandler();
1200 if ( this == mpFrame
->GetEventHandler() )
1202 mpFrame
->SetEventHandler( this->GetNextHandler() );
1206 wxEvtHandler
* pCur
= mpFrame
->GetEventHandler();
1213 pCur
= pCur
->GetNextHandler();
1216 // do not try to unhook ourselves if we're not hooked yet
1221 if ( GetPreviousHandler() )
1222 GetPreviousHandler()->SetNextHandler( GetNextHandler() );
1225 mpFrame
->PopEventHandler();
1229 if ( GetNextHandler() )
1230 GetNextHandler()->SetPreviousHandler( GetPreviousHandler() );
1232 SetNextHandler( NULL
);
1233 SetPreviousHandler( NULL
);
1237 void wxFrameLayout::HookUpToFrame()
1239 // unhook us first, we're already hooked up
1243 // put ourselves on top
1245 mpFrame
->PushEventHandler( this );
1248 cbDockPane
* wxFrameLayout::GetBarPane( cbBarInfo
* pBar
)
1251 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1252 if ( mPanes
[i
]->BarPresent( pBar
) )
1258 void wxFrameLayout::CreateCursors()
1261 // FIXME:: The below code somehow doesn't work - cursors remain unchanged
1264 set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
1266 mpHorizCursor = new wxCursor( bits, 32, 16 );
1268 set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
1270 mpVertCursor = new wxCursor( bits, 32, 16 );
1273 // FOR NOW:: use standard ones
1275 mpHorizCursor
= new wxCursor(wxCURSOR_SIZEWE
);
1276 mpVertCursor
= new wxCursor(wxCURSOR_SIZENS
);
1277 mpNormalCursor
= new wxCursor(wxCURSOR_ARROW
);
1278 mpDragCursor
= new wxCursor(wxCURSOR_CROSS
);
1279 mpNECursor
= new wxCursor(wxCURSOR_NO_ENTRY
);
1281 mFloatingPosStep
.x
= 25;
1282 mFloatingPosStep
.y
= 25;
1284 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
1285 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
1288 bool wxFrameLayout::HitTestPane( cbDockPane
* pPane
, int x
, int y
)
1290 return rect_contains_point( pPane
->GetRealRect(), x
, y
);
1293 cbDockPane
* wxFrameLayout::HitTestPanes( const wxRect
& rect
,
1294 cbDockPane
* pCurPane
)
1296 // first, give the privilege to the current pane
1298 if ( pCurPane
&& rect_hits_rect( pCurPane
->GetRealRect(), rect
) )
1303 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1305 if ( pCurPane
!= mPanes
[i
] &&
1306 rect_hits_rect( mPanes
[i
]->GetRealRect(), rect
) )
1314 void wxFrameLayout::ForwardMouseEvent( wxMouseEvent
& event
,
1315 cbDockPane
* pToPane
,
1318 wxPoint
pos( event
.m_x
, event
.m_y
);
1319 pToPane
->FrameToPane( &pos
.x
, &pos
.y
);
1321 if ( eventType
== cbEVT_PL_LEFT_DOWN
)
1323 cbLeftDownEvent
evt( pos
, pToPane
);
1324 FirePluginEvent( evt
);
1326 else if ( eventType
== cbEVT_PL_LEFT_DCLICK
)
1328 cbLeftDClickEvent
evt( pos
, pToPane
);
1329 FirePluginEvent( evt
);
1331 else if ( eventType
== cbEVT_PL_LEFT_UP
)
1333 cbLeftUpEvent
evt( pos
, pToPane
);
1334 FirePluginEvent( evt
);
1336 else if ( eventType
== cbEVT_PL_RIGHT_DOWN
)
1338 cbRightDownEvent
evt( pos
, pToPane
);
1339 FirePluginEvent( evt
);
1341 else if ( eventType
== cbEVT_PL_RIGHT_UP
)
1343 cbRightUpEvent
evt( pos
, pToPane
);
1344 FirePluginEvent( evt
);
1346 else if ( eventType
== cbEVT_PL_MOTION
)
1348 cbMotionEvent
evt( pos
, pToPane
);
1349 FirePluginEvent( evt
);
1353 int avoidCompilerWarning
= 0;
1354 wxASSERT(avoidCompilerWarning
); // DBG::
1356 } // wxFrameLayout::ForwardMouseEvent()
1359 void wxFrameLayout::RouteMouseEvent( wxMouseEvent
& event
, int pluginEvtType
)
1361 if ( mpPaneInFocus
)
1363 ForwardMouseEvent( event
, mpPaneInFocus
, pluginEvtType
);
1367 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1369 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1371 ForwardMouseEvent( event
, mPanes
[i
], pluginEvtType
);
1378 /*** event handlers ***/
1380 void wxFrameLayout::OnRButtonDown( wxMouseEvent
& event
)
1382 RouteMouseEvent( event
, cbEVT_PL_RIGHT_DOWN
);
1385 void wxFrameLayout::OnRButtonUp( wxMouseEvent
& event
)
1387 RouteMouseEvent( event
, cbEVT_PL_RIGHT_UP
);
1390 void wxFrameLayout::OnLButtonDown( wxMouseEvent
& event
)
1392 RouteMouseEvent( event
, cbEVT_PL_LEFT_DOWN
);
1395 void wxFrameLayout::OnLDblClick( wxMouseEvent
& event
)
1397 RouteMouseEvent( event
, cbEVT_PL_LEFT_DCLICK
);
1400 void wxFrameLayout::OnLButtonUp( wxMouseEvent
& event
)
1402 RouteMouseEvent( event
, cbEVT_PL_LEFT_UP
);
1405 void wxFrameLayout::OnMouseMove( wxMouseEvent
& event
)
1407 if ( mpPaneInFocus
)
1409 ForwardMouseEvent( event
, mpPaneInFocus
, cbEVT_PL_MOTION
);
1413 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1415 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1417 if ( mpLRUPane
&& mpLRUPane
!= mPanes
[i
] )
1419 // simulate "mouse-leave" event
1420 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1423 ForwardMouseEvent( event
, mPanes
[i
], cbEVT_PL_MOTION
);
1425 mpLRUPane
= mPanes
[i
];
1434 // simulate "mouse-leave" event
1435 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1440 void wxFrameLayout::OnPaint( wxPaintEvent
& event
)
1442 if ( mRecalcPending
)
1443 RecalcLayout( TRUE
);
1445 wxPaintDC
dc(mpFrame
);
1448 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1450 wxRect
& rect
= mPanes
[i
]->mBoundsInParent
;
1452 dc
.SetClippingRegion( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1454 mPanes
[i
]->PaintPane(dc
);
1456 dc
.DestroyClippingRegion();
1462 void wxFrameLayout::OnEraseBackground( wxEraseEvent
& event
)
1467 void wxFrameLayout::OnIdle( wxIdleEvent
& event
)
1469 wxWindow
* focus
= wxWindow::FindFocus();
1471 if ( !focus
&& mCheckFocusWhenIdle
)
1473 wxMessageBox( "Hi, no more focus in this app!" );
1475 mCheckFocusWhenIdle
= FALSE
;
1476 //ShowFloatedWindows( FALSE );
1479 mCheckFocusWhenIdle
= FALSE
;
1485 void wxFrameLayout::OnKillFocus( wxFocusEvent
& event
)
1487 //wxMessageBox( "wxFrameLayoutGot Kill Focus!" );
1488 //ShowFloatedWindows( FALSE );
1491 void wxFrameLayout::OnSetFocus( wxFocusEvent
& event
)
1493 //ShowFloatedWindows( TRUE );
1496 void wxFrameLayout::OnActivate( wxActivateEvent
& event
)
1499 if ( event
.GetActive() == FALSE
)
1501 wxWindow
* focus
= wxWindow::FindFocus();
1503 if ( !focus
|| focus
== &GetParentFrame() )
1505 mCheckFocusWhenIdle
= TRUE
;
1509 wxMessageBox("Deactivated!" );
1516 void wxFrameLayout::GetPaneProperties( cbCommonPaneProperties
& props
, int alignment
)
1518 props
= mPanes
[alignment
]->mProps
;
1521 void wxFrameLayout::SetPaneProperties( const cbCommonPaneProperties
& props
, int paneMask
)
1524 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1526 if ( mPanes
[i
]->MatchesMask( paneMask
) )
1527 mPanes
[i
]->mProps
= props
;
1531 void wxFrameLayout::SetMargins( int top
, int bottom
, int left
, int right
,
1535 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1537 cbDockPane
& pane
= *mPanes
[i
];
1539 if ( pane
.MatchesMask( paneMask
) )
1541 pane
.mTopMargin
= top
;
1542 pane
.mBottomMargin
= bottom
;
1543 pane
.mLeftMargin
= left
;
1544 pane
.mRightMargin
= right
;
1549 void wxFrameLayout::SetPaneBackground( const wxColour
& colour
)
1551 mBorderPen
.SetColour( colour
);
1554 void wxFrameLayout::RefreshNow( bool recalcLayout
)
1556 if ( recalcLayout
) RecalcLayout( TRUE
);
1558 if ( mpFrame
) mpFrame
->Refresh();
1561 /*** plugin-related methods ***/
1563 void wxFrameLayout::FirePluginEvent( cbPluginEvent
& event
)
1565 // check state of input capture, before processing the event
1567 if ( mpCaputesInput
)
1569 bool isInputEvt
= TRUE
;
1570 #if wxCHECK_VERSION(2,3,0)
1571 if ( event
.m_eventType
!= cbEVT_PL_LEFT_DOWN
&&
1572 event
.m_eventType
!= cbEVT_PL_LEFT_UP
&&
1573 event
.m_eventType
!= cbEVT_PL_RIGHT_DOWN
&&
1574 event
.m_eventType
!= cbEVT_PL_RIGHT_UP
&&
1575 event
.m_eventType
!= cbEVT_PL_MOTION
)
1578 switch ( event
.m_eventType
)
1580 case cbEVT_PL_LEFT_DOWN
: break;
1581 case cbEVT_PL_LEFT_UP
: break;
1582 case cbEVT_PL_RIGHT_DOWN
: break;
1583 case cbEVT_PL_RIGHT_UP
: break;
1584 case cbEVT_PL_MOTION
: break;
1586 default : isInputEvt
= FALSE
; break;
1588 #endif // #if wxCHECK_VERSION(2,3,0)
1592 mpCaputesInput
->ProcessEvent( event
);
1597 GetTopPlugin().ProcessEvent( event
);
1600 void wxFrameLayout::CaptureEventsForPlugin ( cbPluginBase
* pPlugin
)
1602 // cannot capture events for more than one plugin at a time
1603 wxASSERT( mpCaputesInput
== NULL
);
1605 mpCaputesInput
= pPlugin
;
1609 void wxFrameLayout::ReleaseEventsFromPlugin( cbPluginBase
* pPlugin
)
1611 // events should be captured first
1612 wxASSERT( mpCaputesInput
!= NULL
);
1614 mpCaputesInput
= NULL
;
1617 void wxFrameLayout::CaptureEventsForPane( cbDockPane
* toPane
)
1619 // cannot capture events twice (without releasing)
1620 wxASSERT( mpPaneInFocus
== NULL
);
1622 mpFrame
->CaptureMouse();
1624 mpPaneInFocus
= toPane
;
1627 void wxFrameLayout::ReleaseEventsFromPane( cbDockPane
* fromPane
)
1629 // cannot release events without capturing them
1630 wxASSERT( mpPaneInFocus
!= NULL
);
1632 mpFrame
->ReleaseMouse();
1634 mpPaneInFocus
= NULL
;
1637 cbPluginBase
& wxFrameLayout::GetTopPlugin()
1641 PushDefaultPlugins(); // automatic configuration
1643 return *mpTopPlugin
;
1646 void wxFrameLayout::SetTopPlugin( cbPluginBase
* pPlugin
)
1648 mpTopPlugin
= pPlugin
;
1651 bool wxFrameLayout::HasTopPlugin()
1653 return ( mpTopPlugin
!= NULL
);
1656 void wxFrameLayout::PushPlugin( cbPluginBase
* pPlugin
)
1660 mpTopPlugin
= pPlugin
;
1663 pPlugin
->SetNextHandler( mpTopPlugin
);
1665 mpTopPlugin
->SetPreviousHandler( pPlugin
);
1667 mpTopPlugin
= pPlugin
;
1670 mpTopPlugin
->OnInitPlugin(); // notification
1673 void wxFrameLayout::PopPlugin()
1675 wxASSERT( mpTopPlugin
); // DBG:: at least one plugin should be present
1677 cbPluginBase
* pPopped
= mpTopPlugin
;
1679 mpTopPlugin
= (cbPluginBase
*)mpTopPlugin
->GetNextHandler();
1684 void wxFrameLayout::PopAllPlugins()
1686 while( mpTopPlugin
) PopPlugin();
1689 void wxFrameLayout::PushDefaultPlugins()
1691 // FIXME:: to much of the stuff for the default...
1693 AddPlugin( CLASSINFO( cbRowLayoutPlugin
) );
1694 AddPlugin( CLASSINFO( cbBarDragPlugin
) );
1695 AddPlugin( CLASSINFO( cbPaneDrawPlugin
) );
1698 void wxFrameLayout::AddPlugin( wxClassInfo
* pPlInfo
, int paneMask
)
1700 if ( FindPlugin ( pPlInfo
) ) return; // same type of plugin cannot be added twice
1702 cbPluginBase
* pObj
= (cbPluginBase
*)pPlInfo
->CreateObject();
1704 wxASSERT(pObj
); // DBG:: plugin's class should be dynamic
1706 pObj
->mPaneMask
= paneMask
;
1707 pObj
->mpLayout
= this;
1712 void wxFrameLayout::AddPluginBefore( wxClassInfo
* pNextPlInfo
, wxClassInfo
* pPlInfo
,
1715 wxASSERT( pNextPlInfo
!= pPlInfo
); // DBG:: no sense
1717 cbPluginBase
* pNextPl
= FindPlugin( pNextPlInfo
);
1721 AddPlugin( pPlInfo
, paneMask
);
1726 // remove existing one if present
1728 cbPluginBase
* pExistingPl
= FindPlugin( pPlInfo
);
1730 if ( pExistingPl
) RemovePlugin( pPlInfo
);
1732 // create an instance
1734 cbPluginBase
* pNewPl
= (cbPluginBase
*)pPlInfo
->CreateObject();
1736 wxASSERT(pNewPl
); // DBG:: plugin's class should be dynamic
1738 // insert it to the chain
1740 if ( pNextPl
->GetPreviousHandler() )
1742 pNextPl
->GetPreviousHandler()->SetNextHandler( pNewPl
);
1744 mpTopPlugin
= pNewPl
;
1746 pNewPl
->SetNextHandler( pNextPl
);
1748 pNewPl
->SetPreviousHandler( pNextPl
->GetPreviousHandler() );
1750 pNextPl
->SetPreviousHandler( pNewPl
);
1754 pNewPl
->mPaneMask
= paneMask
;
1755 pNewPl
->mpLayout
= this;
1757 pNewPl
->OnInitPlugin();
1760 void wxFrameLayout::RemovePlugin( wxClassInfo
* pPlInfo
)
1762 cbPluginBase
* pPlugin
= FindPlugin( pPlInfo
);
1764 if ( !pPlugin
) return; // it's OK to remove not-existing plugin ;-)
1766 if ( pPlugin
->GetPreviousHandler() == NULL
)
1768 mpTopPlugin
= (cbPluginBase
*)pPlugin
->GetNextHandler();
1773 cbPluginBase
* wxFrameLayout::FindPlugin( wxClassInfo
* pPlInfo
)
1775 cbPluginBase
*pCur
= mpTopPlugin
;
1779 // NOTE:: it might appear useful matching plugin
1780 // classes "polymorphically":
1782 if ( pCur
->GetClassInfo()->IsKindOf( pPlInfo
) )
1786 pCur
= (cbPluginBase
*)pCur
->GetNextHandler();
1792 /***** Implementation for class cbUpdateMgrData *****/
1794 IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData
, wxObject
)
1796 cbUpdateMgrData::cbUpdateMgrData()
1798 : mPrevBounds( -1,-1,0,0 ),
1799 mIsDirty( TRUE
) // inidicate initial change
1802 void cbUpdateMgrData::StoreItemState( const wxRect
& boundsInParent
)
1804 mPrevBounds
= boundsInParent
;
1807 void cbUpdateMgrData::SetDirty( bool isDirty
)
1812 void cbUpdateMgrData::SetCustomData( wxObject
* pCustomData
)
1814 mpCustomData
= pCustomData
;
1817 /***** Implementation for class cbDockPane *****/
1819 void wxBarIterator::Reset()
1821 mpRow
= ( mpRows
->Count() ) ? (*mpRows
)[0] : NULL
;
1825 wxBarIterator::wxBarIterator( RowArrayT
& rows
)
1834 bool wxBarIterator::Next()
1839 mpBar
= mpBar
->mpNext
;
1842 if ( mpRow
->mBars
.GetCount() == 0 )
1847 mpBar
= mpRow
->mBars
[0];
1852 // skip to the next row
1854 mpRow
= mpRow
->mpNext
;
1858 mpBar
= mpRow
->mBars
[0];
1869 cbBarInfo
& wxBarIterator::BarInfo()
1874 cbRowInfo
& wxBarIterator::RowInfo()
1879 /***** Implementation for class cbBarDimHandlerBase *****/
1881 IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase
, wxObject
)
1883 cbBarDimHandlerBase::cbBarDimHandlerBase()
1887 void cbBarDimHandlerBase::AddRef()
1892 void cbBarDimHandlerBase::RemoveRef()
1894 if ( --mRefCount
<= 0 ) delete this;
1897 /***** Implementation for class cbDimInfo *****/
1899 IMPLEMENT_DYNAMIC_CLASS( cbDimInfo
, wxObject
)
1901 cbDimInfo::cbDimInfo()
1910 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1915 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1919 cbDimInfo::cbDimInfo( cbBarDimHandlerBase
* pDimHandler
,
1924 mIsFixed ( isFixed
),
1926 mpHandler( pDimHandler
)
1930 // int vtad = *((int*)mpHandler);
1931 mpHandler
->AddRef();
1935 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1940 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1944 cbDimInfo::cbDimInfo( int dh_x
, int dh_y
,
1952 cbBarDimHandlerBase
* pDimHandler
1954 : mVertGap ( vertGap
),
1955 mHorizGap ( horizGap
),
1956 mIsFixed ( isFixed
),
1957 mpHandler( pDimHandler
)
1961 // int vtad = *((int*)mpHandler);
1962 mpHandler
->AddRef();
1965 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= dh_x
;
1966 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= dh_y
;
1967 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= dv_x
;
1968 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= dv_y
;
1969 mSizes
[wxCBAR_FLOATING
].x
= f_x
;
1970 mSizes
[wxCBAR_FLOATING
].y
= f_y
;
1973 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1974 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1977 cbDimInfo::cbDimInfo( int x
, int y
,
1978 bool isFixed
, int gap
,
1979 cbBarDimHandlerBase
* pDimHandler
)
1982 mIsFixed ( isFixed
),
1983 mpHandler( pDimHandler
)
1987 // int vtad = *((int*)mpHandler);
1988 mpHandler
->AddRef();
1991 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= x
;
1992 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= y
;
1993 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= x
;
1994 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= y
;
1995 mSizes
[wxCBAR_FLOATING
].x
= x
;
1996 mSizes
[wxCBAR_FLOATING
].y
= y
;
1999 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2000 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
2003 cbDimInfo::~cbDimInfo()
2007 mpHandler
->RemoveRef();
2010 const cbDimInfo
& cbDimInfo::operator=( const cbDimInfo
& other
)
2012 if ( this == &other
)
2016 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2017 mSizes
[i
] = other
.mSizes
[i
];
2019 mIsFixed
= other
.mIsFixed
;
2020 mpHandler
= other
.mpHandler
;
2022 mVertGap
= other
.mVertGap
;
2023 mHorizGap
= other
.mHorizGap
;
2027 mpHandler
->AddRef();
2032 /***** Implementation for structure cbCommonPaneProperties *****/
2034 IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties
, wxObject
)
2036 cbCommonPaneProperties::cbCommonPaneProperties(void)
2038 : mRealTimeUpdatesOn ( TRUE
),
2039 mOutOfPaneDragOn ( TRUE
),
2040 mExactDockPredictionOn( FALSE
),
2041 mNonDestructFirctionOn( FALSE
),
2042 mShow3DPaneBorderOn ( TRUE
),
2043 mBarFloatingOn ( FALSE
),
2044 mRowProportionsOn ( FALSE
),
2045 mColProportionsOn ( TRUE
),
2046 mBarCollapseIconsOn ( FALSE
),
2047 mBarDragHintsOn ( FALSE
),
2049 mMinCBarDim( 16, 16 ),
2050 mResizeHandleSize( 4 )
2053 /***** Implementation for class cbRowInfo *****/
2055 IMPLEMENT_DYNAMIC_CLASS( cbRowInfo
, wxObject
)
2057 cbRowInfo::cbRowInfo(void)
2059 : mNotFixedBarsCnt( FALSE
),
2062 mpExpandedBar ( NULL
)
2065 cbRowInfo::~cbRowInfo()
2067 // nothing! all bars are removed using global bar
2068 // list in wxFrameLayout class
2071 /***** Implementation for class cbBarInfo *****/
2073 IMPLEMENT_DYNAMIC_CLASS( cbBarInfo
, wxObject
)
2075 cbBarInfo::cbBarInfo(void)
2083 cbBarInfo::~cbBarInfo()
2088 /***** Implementation for class cbDockPane *****/
2090 IMPLEMENT_DYNAMIC_CLASS( cbDockPane
, wxObject
)
2092 // FIXME:: how to eliminate these cut&pasted constructors?
2094 cbDockPane::cbDockPane(void)
2095 : mLeftMargin ( 1 ),
2099 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2100 // since the real dimensions of the pane may not
2101 // be known, while inserting bars initially
2102 mPaneHeight( 32768 ),
2108 cbDockPane::cbDockPane( int alignment
, wxFrameLayout
* pPanel
)
2110 : mLeftMargin ( 1 ),
2114 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2115 // since the real dimensions of the pane may not
2116 // be known, while inserting bars initially
2117 mPaneHeight( 32768 ),
2118 mAlignment ( alignment
),
2119 mpLayout ( pPanel
),
2123 cbDockPane::~cbDockPane()
2126 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2129 mRowShapeData
.DeleteContents( TRUE
);
2131 // NOTE:: control bar infromation structures are cleaned-up
2132 // in wxFrameLayout's destructor, using global control-bar list
2135 void cbDockPane::SetMargins( int top
, int bottom
, int left
, int right
)
2138 mBottomMargin
= bottom
;
2140 mRightMargin
= right
;
2143 /*** helpers of cbDockPane ***/
2145 void cbDockPane::PaintBarDecorations( cbBarInfo
* pBar
, wxDC
& dc
)
2147 cbDrawBarDecorEvent
evt( pBar
, dc
, this );
2149 mpLayout
->FirePluginEvent( evt
);
2152 void cbDockPane::PaintBarHandles( cbBarInfo
* pBar
, wxDC
& dc
)
2154 cbDrawBarHandlesEvent
evt( pBar
, dc
, this );
2156 mpLayout
->FirePluginEvent( evt
);
2159 void cbDockPane::PaintBar( cbBarInfo
* pBar
, wxDC
& dc
)
2161 PaintBarDecorations( pBar
, dc
);
2162 PaintBarHandles( pBar
, dc
);
2165 void cbDockPane::PaintRowHandles( cbRowInfo
* pRow
, wxDC
& dc
)
2167 cbDrawRowHandlesEvent
evt( pRow
, dc
, this );
2169 mpLayout
->FirePluginEvent( evt
);
2171 cbDrawRowDecorEvent
evt1( pRow
, dc
, this );
2173 mpLayout
->FirePluginEvent( evt1
);
2176 void cbDockPane::PaintRowBackground ( cbRowInfo
* pRow
, wxDC
& dc
)
2178 cbDrawRowBkGroundEvent
evt( pRow
, dc
, this );
2180 mpLayout
->FirePluginEvent( evt
);
2183 void cbDockPane::PaintRowDecorations( cbRowInfo
* pRow
, wxDC
& dc
)
2187 // decorations first
2188 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2190 PaintBarDecorations( pRow
->mBars
[i
], dc
);
2192 // then handles if present
2193 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2195 PaintBarHandles( pRow
->mBars
[i
], dc
);
2198 void cbDockPane::PaintRow( cbRowInfo
* pRow
, wxDC
& dc
)
2200 PaintRowBackground ( pRow
, dc
);
2201 PaintRowDecorations( pRow
, dc
);
2202 PaintRowHandles ( pRow
, dc
);
2205 void cbDockPane::PaintPaneBackground( wxDC
& dc
)
2207 cbDrawPaneBkGroundEvent
evt( dc
, this );
2209 mpLayout
->FirePluginEvent( evt
);
2212 void cbDockPane::PaintPaneDecorations( wxDC
& dc
)
2214 cbDrawPaneDecorEvent
evt( dc
, this );
2216 mpLayout
->FirePluginEvent( evt
);
2219 void cbDockPane::PaintPane( wxDC
& dc
)
2221 PaintPaneBackground( dc
);
2225 // first decorations
2226 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2228 PaintRowBackground( mRows
[i
], dc
);
2229 PaintRowDecorations( mRows
[i
], dc
);
2233 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2234 PaintRowHandles( mRows
[i
], dc
);
2237 PaintPaneDecorations( dc
);
2240 void cbDockPane::SizeBar( cbBarInfo
* pBar
)
2242 cbSizeBarWndEvent
evt( pBar
, this );
2244 mpLayout
->FirePluginEvent( evt
);
2248 void cbDockPane::SizeRowObjects( cbRowInfo
* pRow
)
2251 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2252 SizeBar( pRow
->mBars
[i
] );
2255 void cbDockPane::SizePaneObjects()
2258 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2259 SizeRowObjects( mRows
[i
] );
2262 wxDC
* cbDockPane::StartDrawInArea( const wxRect
& area
)
2266 cbStartDrawInAreaEvent
evt( area
, &pDc
, this );
2268 mpLayout
->FirePluginEvent( evt
);
2273 void cbDockPane::FinishDrawInArea( const wxRect
& area
)
2275 cbFinishDrawInAreaEvent
evt( area
, this );
2277 mpLayout
->FirePluginEvent( evt
);
2280 bool cbDockPane::IsFixedSize( cbBarInfo
* pInfo
)
2282 return ( pInfo
->mDimInfo
.mIsFixed
);
2285 int cbDockPane::GetNotFixedBarsCount( cbRowInfo
* pRow
)
2290 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2292 if ( !pRow
->mBars
[i
]->IsFixed() )
2299 void cbDockPane::RemoveBar( cbBarInfo
* pBar
)
2301 bool needsRestoring
= mProps
.mNonDestructFirctionOn
&&
2302 mpStoredRow
== pBar
->mpRow
;
2304 cbRemoveBarEvent
evt( pBar
, this );
2306 mpLayout
->FirePluginEvent( evt
);
2308 if ( needsRestoring
)
2310 SetRowShapeData( mpStoredRow
, &mRowShapeData
);
2316 void cbDockPane::SyncRowFlags( cbRowInfo
* pRow
)
2318 // setup mHasOnlyFixedBars flag for the row information
2319 pRow
->mHasOnlyFixedBars
= TRUE
;
2321 pRow
->mNotFixedBarsCnt
= 0;
2324 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2326 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2330 if ( !bar
.IsFixed() )
2332 pRow
->mHasOnlyFixedBars
= FALSE
;
2333 ++pRow
->mNotFixedBarsCnt
;
2338 void cbDockPane::FrameToPane( int* x
, int* y
)
2343 if ( mAlignment
== FL_ALIGN_TOP
||
2344 mAlignment
== FL_ALIGN_BOTTOM
2347 *x
-= mBoundsInParent
.x
;
2348 *y
-= mBoundsInParent
.y
;
2352 int rx
= *x
, ry
= *y
;
2354 *x
= ry
- mBoundsInParent
.y
;
2356 *y
= rx
- mBoundsInParent
.x
;
2360 void cbDockPane::PaneToFrame( int* x
, int* y
)
2362 if ( mAlignment
== FL_ALIGN_TOP
||
2363 mAlignment
== FL_ALIGN_BOTTOM
2366 *x
+= mBoundsInParent
.x
;
2367 *y
+= mBoundsInParent
.y
;
2371 int rx
= *x
, ry
= *y
;
2373 *x
= ry
+ mBoundsInParent
.x
;
2375 *y
= mBoundsInParent
.y
+ rx
;
2382 void cbDockPane::FrameToPane( wxRect
* pRect
)
2384 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2385 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2386 pRect
->y
+ pRect
->height
);
2388 FrameToPane( &upperLeft
.x
, &upperLeft
.y
);
2389 FrameToPane( &lowerRight
.x
, &lowerRight
.y
);
2391 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2392 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2394 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2395 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2398 void cbDockPane::PaneToFrame( wxRect
* pRect
)
2400 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2401 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2402 pRect
->y
+ pRect
->height
);
2404 PaneToFrame( &upperLeft
.x
, &upperLeft
.y
);
2405 PaneToFrame( &lowerRight
.x
, &lowerRight
.y
);
2407 //wxRect newRect = wxRect( upperLeft, lowerRight );
2409 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2410 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2412 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2413 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2416 int cbDockPane::GetRowAt( int paneY
)
2425 for ( ; i
!= mRows
.Count(); ++i
)
2427 int rowHeight
= mRows
[i
]->mRowHeight
;
2429 int third
= rowHeight
/3;
2431 if ( paneY
>= curY
&& paneY
< curY
+ third
)
2434 if ( paneY
>= curY
+ third
&& paneY
< curY
+ rowHeight
- third
)
2443 int cbDockPane::GetRowAt( int upperY
, int lowerY
)
2447 int range = lowerY - upperY;
2448 int oneThird = range / 3;
2450 wxNode* pRow = mRows.First();
2454 if ( lowerY <= 0 ) return -1;
2458 int rowHeight = GetRowHeight( (wxList*)pRow->Data() );
2460 if ( upperY >= curY &&
2461 lowerY < curY ) return row;
2463 if ( upperY <= curY &&
2465 curY - upperY >= oneThird ) return row-1;
2467 if ( ( upperY < curY + rowHeight &&
2468 lowerY >= curY + rowHeight &&
2469 curY + rowHeight - lowerY >= oneThird )
2473 if ( lowerY <= curY + rowHeight ) return row;
2477 pRow = pRow->Next();
2481 int mid
= upperY
+ (lowerY
- upperY
)/2;
2489 for ( ; i
!= mRows
.Count(); ++i
)
2491 int rowHeight
= mRows
[i
]->mRowHeight
;
2493 if ( mid
>= curY
&& mid
< curY
+ rowHeight
) return i
;
2501 int cbDockPane::GetRowY( cbRowInfo
* pRow
)
2506 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2508 if ( mRows
[i
] == pRow
)
2511 curY
+= mRows
[i
]->mRowHeight
;
2517 bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo
* pRow
)
2519 while ( pRow
->mpPrev
)
2521 pRow
= pRow
->mpPrev
;
2523 if ( pRow
->mHasOnlyFixedBars
)
2531 bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo
* pRow
)
2533 while( pRow
->mpNext
)
2535 pRow
= pRow
->mpNext
;
2537 if ( pRow
->mHasOnlyFixedBars
)
2545 bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo
* pBar
)
2547 while( pBar
->mpPrev
)
2549 pBar
= pBar
->mpPrev
;
2551 if ( pBar
->IsFixed() )
2559 bool cbDockPane::HasNotFixedBarsRight( cbBarInfo
* pBar
)
2561 while( pBar
->mpNext
)
2563 pBar
= pBar
->mpNext
;
2565 if ( pBar
->IsFixed() )
2573 void cbDockPane::CalcLengthRatios( cbRowInfo
* pInRow
)
2579 // clac current-maximal-total-length of all maximized bars
2581 for ( i
= 0; i
!= pInRow
->mBars
.GetCount(); ++i
)
2583 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2585 if ( !bar
.IsFixed() )
2586 totalWidth
+= bar
.mBounds
.width
;
2589 // set up persentages of occupied space for each maximized bar
2591 for ( i
= 0; i
!= pInRow
->mBars
.Count(); ++i
)
2593 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2595 if ( !bar
.IsFixed() )
2596 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalWidth
);
2600 void cbDockPane::RecalcRowLayout( cbRowInfo
* pRow
)
2602 cbLayoutRowEvent
evt( pRow
, this );
2604 mpLayout
->FirePluginEvent( evt
);
2607 void cbDockPane::ExpandBar( cbBarInfo
* pBar
)
2609 mpLayout
->GetUpdatesManager().OnStartChanges();
2611 if ( !pBar
->mpRow
->mpExpandedBar
)
2613 // save ratios only when there arent any bars expanded yet
2615 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2618 ratios
.Alloc( pBar
->mpRow
->mNotFixedBarsCnt
);
2620 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2624 if ( !pCur
->IsFixed() )
2627 ratios
[ ratios
.GetCount() - 1 ] = pCur
->mLenRatio
;
2630 pCur
= pCur
->mpNext
;
2634 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2638 pCur
->mLenRatio
= 0.0; // minimize the rest
2640 pCur
= pCur
->mpNext
;
2643 pBar
->mLenRatio
= 1.0; // 100%
2644 pBar
->mBounds
.width
= 0;
2646 pBar
->mpRow
->mpExpandedBar
= pBar
;
2648 mpLayout
->RecalcLayout( FALSE
);
2650 mpLayout
->GetUpdatesManager().OnFinishChanges();
2651 mpLayout
->GetUpdatesManager().UpdateNow();
2654 void cbDockPane::ContractBar( cbBarInfo
* pBar
)
2656 mpLayout
->GetUpdatesManager().OnStartChanges();
2658 // FIXME: What's the purpose of this???
2659 // double ratio = 1.0/ double( pBar->mpRow->mNotFixedBarsCnt );
2661 // restore ratios which were present before expansion
2663 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2665 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2671 if ( !pCur
->IsFixed() )
2673 pCur
->mLenRatio
= ratios
[i
];
2677 pCur
= pCur
->mpNext
;
2683 pBar
->mpRow
->mpExpandedBar
= NULL
;
2685 mpLayout
->RecalcLayout( FALSE
);
2687 mpLayout
->GetUpdatesManager().OnFinishChanges();
2688 mpLayout
->GetUpdatesManager().UpdateNow();
2691 void cbDockPane::InitLinksForRow( cbRowInfo
* pRow
)
2694 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2696 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2701 bar
.mpPrev
= pRow
->mBars
[i
-1];
2703 if ( i
== pRow
->mBars
.Count() - 1 )
2706 bar
.mpNext
= pRow
->mBars
[i
+1];
2710 void cbDockPane::InitLinksForRows()
2713 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2715 cbRowInfo
& row
= *mRows
[i
];
2720 row
.mpPrev
= mRows
[i
-1];
2722 if ( i
== mRows
.Count() - 1 )
2725 row
.mpNext
= mRows
[i
+1];
2729 void cbDockPane::DoInsertBar( cbBarInfo
* pBar
, int rowNo
)
2731 cbRowInfo
* pRow
= NULL
;
2733 if ( rowNo
== -1 || rowNo
>= (int)mRows
.Count() )
2735 pRow
= new cbRowInfo();
2737 if ( rowNo
== -1 && mRows
.Count() )
2739 mRows
.Insert( pRow
, 0 );
2747 pRow
= mRows
[rowNo
];
2749 if ( mProps
.mNonDestructFirctionOn
== TRUE
)
2751 // store original shape of the row (before the bar is inserted)
2755 GetRowShapeData( mpStoredRow
, &mRowShapeData
);
2759 if ( pRow
->mBars
.Count() )
2761 pRow
->mpExpandedBar
= NULL
;
2763 cbInsertBarEvent
insEvt( pBar
, pRow
, this );
2765 mpLayout
->FirePluginEvent( insEvt
);
2767 mpLayout
->GetUpdatesManager().OnRowWillChange( pRow
, this );
2770 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
, const wxRect
& atRect
)
2772 wxRect rect
= atRect
;
2773 FrameToPane( &rect
);
2775 pBarInfo
->mBounds
.x
= rect
.x
;
2776 pBarInfo
->mBounds
.width
= rect
.width
;
2777 pBarInfo
->mBounds
.height
= rect
.height
;
2779 int row
= GetRowAt( rect
.y
, rect
.y
+ rect
.height
);
2781 DoInsertBar( pBarInfo
, row
);
2784 void cbDockPane::InsertBar( cbBarInfo
* pBar
, cbRowInfo
* pIntoRow
)
2786 cbInsertBarEvent
insEvt( pBar
, pIntoRow
, this );
2788 mpLayout
->FirePluginEvent( insEvt
);
2790 mpLayout
->GetUpdatesManager().OnRowWillChange( pIntoRow
, this );
2793 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
)
2795 // set transient properties
2797 pBarInfo
->mpRow
= NULL
;
2798 pBarInfo
->mHasLeftHandle
= FALSE
;
2799 pBarInfo
->mHasRightHandle
= FALSE
;
2800 pBarInfo
->mLenRatio
= 0.0;
2802 // set preferred bar dimensions, according to the state in which
2803 // the bar is being inserted
2805 pBarInfo
->mBounds
.width
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].x
;
2806 pBarInfo
->mBounds
.height
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].y
;
2808 DoInsertBar( pBarInfo
, pBarInfo
->mRowNo
);
2811 void cbDockPane::RemoveRow( cbRowInfo
* pRow
)
2814 // first, hide all bar-windows in the removed row
2815 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2817 if ( pRow
->mBars
[i
]->mpBarWnd
)
2818 pRow
->mBars
[i
]->mpBarWnd
->Show( FALSE
);
2821 mRows
.Remove( pRow
);
2823 pRow
->mUMgrData
.SetDirty(TRUE
);
2826 void cbDockPane::InsertRow( cbRowInfo
* pRow
, cbRowInfo
* pBeforeRow
)
2832 mRows
.Insert( pRow
, mRows
.Index( pBeforeRow
) );
2836 pRow
->mUMgrData
.SetDirty(TRUE
);
2839 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2840 pRow
->mBars
[i
]->mUMgrData
.SetDirty( TRUE
);
2842 SyncRowFlags( pRow
);
2845 void cbDockPane::SetPaneWidth(int width
)
2847 if ( IsHorizontal() )
2848 mPaneWidth
= width
- mLeftMargin
- mRightMargin
;
2850 mPaneWidth
= width
- mTopMargin
- mBottomMargin
;
2854 void cbDockPane::SetBoundsInParent( const wxRect
& rect
)
2856 mBoundsInParent
= rect
;
2858 // set pane dimensions in local coordinates
2860 if ( IsHorizontal() )
2862 mPaneWidth
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2863 mPaneHeight
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2867 mPaneWidth
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2868 mPaneHeight
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2871 // convert bounding rectangles of all pane items into parent frame's coordinates
2873 wxBarIterator
i( mRows
);
2875 wxRect noMarginsRect
= mBoundsInParent
;
2877 noMarginsRect
.x
+= mLeftMargin
;
2878 noMarginsRect
.y
+= mTopMargin
;
2879 noMarginsRect
.width
-= ( mLeftMargin
+ mRightMargin
);
2880 noMarginsRect
.height
-= ( mTopMargin
+ mBottomMargin
);
2882 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2884 if ( mBoundsInParent
.width
< 0 ||
2885 mBoundsInParent
.height
< 0 )
2887 hide_rect( mBoundsInParent
);
2889 if ( noMarginsRect
.width
< 0 ||
2890 noMarginsRect
.height
< 0 )
2892 hide_rect( noMarginsRect
);
2894 // calculate mBoundsInParent for each item in the pane
2898 cbBarInfo
& bar
= i
.BarInfo();
2900 cbRowInfo
* pRowInfo
= bar
.mpRow
;
2902 // set up row info, if this is first bar in the row
2904 if ( pRowInfo
&& bar
.mpPrev
== NULL
)
2906 pRowInfo
->mBoundsInParent
.y
= pRowInfo
->mRowY
;
2907 pRowInfo
->mBoundsInParent
.x
= 0;
2908 pRowInfo
->mBoundsInParent
.width
= mPaneWidth
;
2909 pRowInfo
->mBoundsInParent
.height
= pRowInfo
->mRowHeight
;
2911 PaneToFrame( &pRowInfo
->mBoundsInParent
);
2913 clip_rect_against_rect( pRowInfo
->mBoundsInParent
, noMarginsRect
);
2916 wxRect bounds
= bar
.mBounds
;
2918 // exclude dimensions of handles, when calculating
2919 // bar's bounds in parent (i.e. "visual bounds")
2921 if ( bar
.mHasLeftHandle
)
2923 bounds
.x
+= mProps
.mResizeHandleSize
;
2924 bounds
.width
-= mProps
.mResizeHandleSize
;
2927 if ( bar
.mHasRightHandle
)
2929 bounds
.width
-= mProps
.mResizeHandleSize
;
2931 PaneToFrame( &bounds
);
2933 clip_rect_against_rect( bounds
, noMarginsRect
);
2935 bar
.mBoundsInParent
= bounds
;
2939 bool cbDockPane::BarPresent( cbBarInfo
* pBar
)
2941 wxBarIterator
iter( mRows
);
2943 while( iter
.Next() )
2945 if ( &iter
.BarInfo() == pBar
) return TRUE
;
2950 cbRowInfo
* cbDockPane::GetRow( int row
)
2952 if ( row
>= (int)mRows
.Count() ) return NULL
;
2954 return mRows
[ row
];
2957 int cbDockPane::GetRowIndex( cbRowInfo
* pRow
)
2960 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2962 if ( mRows
[i
] == pRow
)
2966 wxFAIL_MSG("Row must be present to call cbDockPane::GetRowIndex()");
2971 int cbDockPane::GetPaneHeight()
2973 // first, recalculate row heights and the Y-positions
2975 cbLayoutRowsEvent
evt( this );
2976 mpLayout
->FirePluginEvent( evt
);
2980 if ( IsHorizontal() )
2982 height
+= mTopMargin
+ mBottomMargin
;
2984 height
+= mLeftMargin
+ mRightMargin
;
2986 int count
= mRows
.Count();
2990 height
+= mRows
[count
-1]->mRowY
+ mRows
[count
-1]->mRowHeight
;
2995 int cbDockPane::GetAlignment()
3000 bool cbDockPane::MatchesMask( int paneMask
)
3004 // FIXME:: use array instead of switch()
3008 case FL_ALIGN_TOP
: thisMask
= FL_ALIGN_TOP_PANE
; break;
3009 case FL_ALIGN_BOTTOM
: thisMask
= FL_ALIGN_BOTTOM_PANE
;break;
3010 case FL_ALIGN_LEFT
: thisMask
= FL_ALIGN_LEFT_PANE
; break;
3011 case FL_ALIGN_RIGHT
: thisMask
= FL_ALIGN_RIGHT_PANE
; break;
3014 wxFAIL_MSG("Bad FL alignment type detected in cbDockPane::MatchesMask()");
3017 return ( thisMask
& paneMask
) != 0;
3020 void cbDockPane::RecalcLayout()
3022 // first, reposition rows and items vertically
3024 cbLayoutRowsEvent
evt( this );
3025 mpLayout
->FirePluginEvent( evt
);
3027 // then horizontally in each row
3030 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3031 RecalcRowLayout( mRows
[i
] );
3034 int cbDockPane::GetDockingState()
3036 if ( mAlignment
== FL_ALIGN_TOP
||
3037 mAlignment
== FL_ALIGN_BOTTOM
)
3039 return wxCBAR_DOCKED_HORIZONTALLY
;
3042 return wxCBAR_DOCKED_VERTICALLY
;
3045 inline bool cbDockPane::HasPoint( const wxPoint
& pos
, int x
, int y
,
3046 int width
, int height
)
3048 return ( pos
.x
>= x
&&
3050 pos
.x
< x
+ width
&&
3051 pos
.y
< y
+ height
);
3054 int cbDockPane::HitTestPaneItems( const wxPoint
& pos
,
3063 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3065 cbRowInfo
& row
= *mRows
[i
];
3069 // hit-test handles of the row, if present
3071 if ( row
.mHasUpperHandle
)
3073 if ( HasPoint( pos
, 0, row
.mRowY
,
3074 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3076 return CB_UPPER_ROW_HANDLE_HITTED
;
3079 if ( row
.mHasLowerHandle
)
3081 if ( HasPoint( pos
, 0, row
.mRowY
+ row
.mRowHeight
- mProps
.mResizeHandleSize
,
3082 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3084 return CB_LOWER_ROW_HANDLE_HITTED
;
3087 // hit-test bar handles and bar content
3090 for ( k
= 0; k
!= row
.mBars
.Count(); ++k
)
3092 cbBarInfo
& bar
= *row
.mBars
[k
];
3093 wxRect
& bounds
= bar
.mBounds
;
3097 if ( bar
.mHasLeftHandle
)
3099 if ( HasPoint( pos
, bounds
.x
, bounds
.y
,
3100 mProps
.mResizeHandleSize
, bounds
.height
) )
3102 return CB_LEFT_BAR_HANDLE_HITTED
;
3105 if ( bar
.mHasRightHandle
)
3107 if ( HasPoint( pos
, bounds
.x
+ bounds
.width
- mProps
.mResizeHandleSize
, bounds
.y
,
3108 mProps
.mResizeHandleSize
, bounds
.height
) )
3110 return CB_RIGHT_BAR_HANDLE_HITTED
;
3113 if ( HasPoint( pos
, bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
) )
3114 return CB_BAR_CONTENT_HITTED
;
3116 } // hit-test next bar
3120 return CB_NO_ITEMS_HITTED
;
3123 void cbDockPane::GetBarResizeRange( cbBarInfo
* pBar
, int* from
, int *till
,
3124 bool forLeftHandle
)
3126 cbBarInfo
* pGivenBar
= pBar
;
3130 // calc unavailable space from the left
3132 while( pBar
->mpPrev
)
3134 pBar
= pBar
->mpPrev
;
3136 if ( !pBar
->IsFixed() ) notFree
+= mProps
.mMinCBarDim
.x
;
3137 else notFree
+= pBar
->mBounds
.width
;
3146 // calc unavailable space from the right
3148 while( pBar
->mpNext
)
3150 pBar
= pBar
->mpNext
;
3152 if ( pBar
->mBounds
.x
>= mPaneWidth
) break;
3154 // treat not-fixed bars as minimized
3156 if ( !pBar
->IsFixed() )
3158 notFree
+= mProps
.mMinCBarDim
.x
;
3161 if ( pBar
->mBounds
.x
+ pBar
->mBounds
.width
>= mPaneWidth
)
3163 notFree
+= mPaneWidth
- pBar
->mBounds
.x
;
3167 notFree
+= pBar
->mBounds
.width
;
3172 *till
= mPaneWidth
- notFree
;
3174 // do not let resizing totally deform the bar itself
3176 if ( forLeftHandle
)
3178 (*till
) -= mProps
.mMinCBarDim
.x
;
3181 (*from
) += mProps
.mMinCBarDim
.x
;
3184 int cbDockPane::GetMinimalRowHeight( cbRowInfo
* pRow
)
3186 int height
= mProps
.mMinCBarDim
.y
;
3189 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3191 if ( pRow
->mBars
[i
]->IsFixed() )
3192 height
= wxMax( height
, pRow
->mBars
[i
]->mBounds
.height
);
3195 if ( pRow
->mHasUpperHandle
)
3196 height
+= mProps
.mResizeHandleSize
;
3198 if ( pRow
->mHasLowerHandle
)
3199 height
+= mProps
.mResizeHandleSize
;
3204 void cbDockPane::SetRowHeight( cbRowInfo
* pRow
, int newHeight
)
3206 if ( pRow
->mHasUpperHandle
)
3208 newHeight
-= mProps
.mResizeHandleSize
;
3210 if ( pRow
->mHasLowerHandle
)
3212 newHeight
-= mProps
.mResizeHandleSize
;
3215 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3217 if ( !pRow
->mBars
[i
]->IsFixed() )
3218 pRow
->mBars
[i
]->mBounds
.height
= newHeight
;
3222 void cbDockPane::GetRowResizeRange( cbRowInfo
* pRow
, int* from
, int* till
,
3223 bool forUpperHandle
)
3225 cbRowInfo
* pGivenRow
= pRow
;
3227 // calc unavailable space from above
3231 while( pRow
->mpPrev
)
3233 pRow
= pRow
->mpPrev
;
3235 notFree
+= GetMinimalRowHeight( pRow
);
3241 // allow accupy the client window space by resizing pane rows
3242 if ( mAlignment
== FL_ALIGN_BOTTOM
)
3244 *from
-= mpLayout
->GetClientHeight();
3246 if ( mAlignment
== FL_ALIGN_RIGHT
)
3248 *from
-= mpLayout
->GetClientWidth();
3250 // calc unavailable space from below
3256 while( pRow
->mpNext
)
3258 pRow
= pRow
->mpNext
;
3260 notFree
+= GetMinimalRowHeight( pRow
);
3264 *till
= mPaneHeight
- notFree
;
3266 // allow adjustinig pane space vs. client window space by resizing pane row heights
3268 if ( mAlignment
== FL_ALIGN_TOP
)
3270 *till
+= mpLayout
->GetClientHeight();
3272 if ( mAlignment
== FL_ALIGN_LEFT
)
3274 *till
+= mpLayout
->GetClientWidth();
3276 // do not let the resizing of the row totally squeeze the row itself
3278 cbRowInfo
& row
= *pGivenRow
;
3280 if ( forUpperHandle
)
3282 *till
= row
.mRowY
+ row
.mRowHeight
- GetMinimalRowHeight( pGivenRow
);
3284 if ( row
.mHasUpperHandle
)
3286 *till
-= mProps
.mResizeHandleSize
;
3290 *from
+= GetMinimalRowHeight( pGivenRow
);
3292 if ( row
.mHasLowerHandle
)
3294 *from
-= mProps
.mResizeHandleSize
;
3298 void cbDockPane::ResizeRow( cbRowInfo
* pRow
, int ofs
,
3299 bool forUpperHandle
)
3301 cbResizeRowEvent
evt( pRow
, ofs
, forUpperHandle
, this );
3303 mpLayout
->FirePluginEvent( evt
);
3306 void cbDockPane::ResizeBar( cbBarInfo
* pBar
, int ofs
,
3307 bool forLeftHandle
)
3309 pBar
->mpRow
->mpExpandedBar
= NULL
;
3311 mpLayout
->GetUpdatesManager().OnStartChanges();
3313 wxRect
& bounds
= pBar
->mBounds
;
3315 if ( forLeftHandle
)
3317 // do not allow bar width become less then minimal
3318 if ( bounds
.x
+ ofs
> bounds
.x
+ bounds
.width
- mProps
.mMinCBarDim
.x
)
3320 bounds
.width
= mProps
.mMinCBarDim
.x
;
3326 bounds
.width
-= ofs
;
3331 // move bar left if necessary
3332 if ( bounds
.width
+ ofs
< mProps
.mMinCBarDim
.x
)
3334 bounds
.x
= bounds
.x
+ bounds
.width
+ ofs
- mProps
.mMinCBarDim
.x
;
3335 bounds
.width
= mProps
.mMinCBarDim
.x
;
3338 // resize right border only
3339 bounds
.width
+= ofs
;
3343 cbRowInfo
* pToRow
= pBar
->mpRow
;
3345 this->RemoveBar( pBar
);
3347 InsertBar( pBar
, pToRow
);
3349 mpLayout
->RecalcLayout(FALSE
);
3351 mpLayout
->GetUpdatesManager().OnFinishChanges();
3352 mpLayout
->GetUpdatesManager().UpdateNow();
3356 /*** row/bar resizing related methods ***/
3358 void cbDockPane::DrawVertHandle( wxDC
& dc
, int x
, int y
, int height
)
3360 int lower
= y
+ height
;
3362 dc
.SetPen( mpLayout
->mLightPen
);
3363 dc
.DrawLine( x
,y
, x
, lower
);
3365 dc
.SetPen( mpLayout
->mGrayPen
);
3367 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3370 dc
.DrawLine( x
,y
, x
, lower
);
3373 dc
.SetPen( mpLayout
->mDarkPen
);
3375 dc
.DrawLine( x
,y
, x
, lower
);
3377 dc
.SetPen( mpLayout
->mBlackPen
);
3379 dc
.DrawLine( x
,y
, x
, lower
);
3382 void cbDockPane::DrawHorizHandle( wxDC
& dc
, int x
, int y
, int width
)
3384 int right
= x
+ width
;
3386 dc
.SetPen( mpLayout
->mLightPen
);
3387 dc
.DrawLine( x
,y
, right
, y
);
3389 dc
.SetPen( mpLayout
->mGrayPen
);
3392 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3395 dc
.DrawLine( x
,y
, right
, y
);
3398 dc
.SetPen( mpLayout
->mDarkPen
);
3399 dc
.DrawLine( x
,y
, right
, ++y
);
3401 dc
.SetPen( mpLayout
->mBlackPen
);
3402 dc
.DrawLine( x
,y
, right
, ++y
);
3405 cbBarInfo
* cbDockPane::GetBarInfoByWindow( wxWindow
* pBarWnd
)
3407 wxBarIterator
i( mRows
);
3411 if ( i
.BarInfo().mpBarWnd
== pBarWnd
)
3413 return &i
.BarInfo();
3418 void cbDockPane::GetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3420 pLst
->DeleteContents( TRUE
);
3424 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3426 cbBarInfo
& bar
= *pRow
->mBars
[i
];
3428 cbBarShapeData
* pData
= new cbBarShapeData();
3430 pLst
->Append( (wxObject
*)pData
);
3432 pData
->mBounds
= bar
.mBounds
;
3433 pData
->mLenRatio
= bar
.mLenRatio
;
3437 void cbDockPane::SetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3439 if ( pLst
->First() == NULL
)
3442 wxNode
* pData
= pLst
->First();
3445 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3447 wxASSERT( pData
); // DBG::
3449 cbBarInfo
& bar
= *pRow
->mBars
[i
];;
3451 cbBarShapeData
& data
= *((cbBarShapeData
*)pData
->Data());
3453 bar
.mBounds
= data
.mBounds
;
3454 bar
.mLenRatio
= data
.mLenRatio
;
3456 pData
= pData
->Next();
3460 /***** Implementation for class cbUpdatesManagerBase *****/
3462 IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase
, wxObject
)
3464 /***** Implementation for class cbPluginBase *****/
3466 IMPLEMENT_ABSTRACT_CLASS( cbPluginBase
, wxEvtHandler
)
3468 cbPluginBase::~cbPluginBase()
3473 bool cbPluginBase::ProcessEvent(wxEvent
& event
)
3475 if ( mPaneMask
== wxALL_PANES
)
3477 return wxEvtHandler::ProcessEvent( event
);
3479 // extract mask info. from received event
3481 cbPluginEvent
& evt
= *( (cbPluginEvent
*)&event
);
3483 if ( evt
.mpPane
== 0 &&
3484 mPaneMask
== wxALL_PANES
)
3486 return wxEvtHandler::ProcessEvent( event
);
3490 switch ( evt
.mpPane
->mAlignment
)
3492 case FL_ALIGN_TOP
: mask
= FL_ALIGN_TOP_PANE
; break;
3493 case FL_ALIGN_BOTTOM
: mask
= FL_ALIGN_BOTTOM_PANE
;break;
3494 case FL_ALIGN_LEFT
: mask
= FL_ALIGN_LEFT_PANE
; break;
3495 case FL_ALIGN_RIGHT
: mask
= FL_ALIGN_RIGHT_PANE
; break;
3498 // if event's pane maks matches the plugin's mask
3500 if ( mPaneMask
& mask
)
3502 return wxEvtHandler::ProcessEvent( event
);
3504 // otherwise pass to the next handler if present
3506 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event
) )