1 /////////////////////////////////////////////////////////////////////////////
2 // Name: controlbar.cpp
3 // Purpose: Implementation for main controlbar classes.
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "controlbar.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
30 #include "wx/string.h"
31 #include "wx/utils.h" // import wxMin,wxMax macros
32 #include "wx/minifram.h"
34 #include "wx/fl/controlbar.h"
36 // import classes of default plugins
38 #include "wx/fl/panedrawpl.h"
39 #include "wx/fl/rowlayoutpl.h"
40 #include "wx/fl/antiflickpl.h"
41 #include "wx/fl/bardragpl.h"
42 #include "wx/fl/cbcustom.h"
44 #include "wx/fl/gcupdatesmgr.h" // import default updates manager class ("garbage-collecting" one)
45 #include "wx/fl/updatesmgr.h"
47 #include "wx/fl/toolwnd.h"
49 // These are the event IDs being initialized to a value to
50 // meet the new event paradigm as of wx2.3.0. Probably we
51 // should find a way to make these be non-global, but this
52 // works for right now.
53 wxEventType cbEVT_PL_LEFT_DOWN
= wxNewEventType();
54 wxEventType cbEVT_PL_LEFT_UP
= wxNewEventType();
55 wxEventType cbEVT_PL_RIGHT_DOWN
= wxNewEventType();
56 wxEventType cbEVT_PL_RIGHT_UP
= wxNewEventType();
57 wxEventType cbEVT_PL_MOTION
= wxNewEventType();
59 wxEventType cbEVT_PL_LEFT_DCLICK
= wxNewEventType();
61 wxEventType cbEVT_PL_LAYOUT_ROW
= wxNewEventType();
62 wxEventType cbEVT_PL_RESIZE_ROW
= wxNewEventType();
63 wxEventType cbEVT_PL_LAYOUT_ROWS
= wxNewEventType();
64 wxEventType cbEVT_PL_INSERT_BAR
= wxNewEventType();
65 wxEventType cbEVT_PL_RESIZE_BAR
= wxNewEventType();
66 wxEventType cbEVT_PL_REMOVE_BAR
= wxNewEventType();
67 wxEventType cbEVT_PL_SIZE_BAR_WND
= wxNewEventType();
69 wxEventType cbEVT_PL_DRAW_BAR_DECOR
= wxNewEventType();
70 wxEventType cbEVT_PL_DRAW_ROW_DECOR
= wxNewEventType();
71 wxEventType cbEVT_PL_DRAW_PANE_DECOR
= wxNewEventType();
72 wxEventType cbEVT_PL_DRAW_BAR_HANDLES
= wxNewEventType();
73 wxEventType cbEVT_PL_DRAW_ROW_HANDLES
= wxNewEventType();
74 wxEventType cbEVT_PL_DRAW_ROW_BKGROUND
= wxNewEventType();
75 wxEventType cbEVT_PL_DRAW_PANE_BKGROUND
= wxNewEventType();
77 wxEventType cbEVT_PL_START_BAR_DRAGGING
= wxNewEventType();
78 wxEventType cbEVT_PL_DRAW_HINT_RECT
= wxNewEventType();
80 wxEventType cbEVT_PL_START_DRAW_IN_AREA
= wxNewEventType();
81 wxEventType cbEVT_PL_FINISH_DRAW_IN_AREA
= wxNewEventType();
83 wxEventType cbEVT_PL_CUSTOMIZE_BAR
= wxNewEventType();
84 wxEventType cbEVT_PL_CUSTOMIZE_LAYOUT
= wxNewEventType();
86 wxEventType wxCUSTOM_CB_PLUGIN_EVENTS_START_AT
= wxNewEventType();
88 // some ascii-art, still can't get these *nice* cursors working on wx... :-(
90 static const char* _gHorizCursorImg
[] =
92 "............XX....XX............",
93 "............XX....XX............",
94 "............XX....XX............",
95 "............XX....XX............",
96 "............XX....XX............",
97 "...X........XX....XX........X...",
98 "..XX........XX....XX........XX..",
99 ".XXX........XX....XX........XXX.",
100 "XXXXXXXXXXXXXX....XXXXXXXXXXXXXX",
101 ".XXX........XX....XX........XXX.",
102 "..XX........XX....XX........XX..",
103 "...X........XX....XX........X...",
104 "............XX....XX............",
105 "............XX....XX............",
106 "............XX....XX............",
107 "............XX....XX............"
110 static const char* _gVertCursorImg
[] =
112 "................X...............",
113 "...............XXX..............",
114 "..............XXXXX.............",
115 ".............XXXXXXX............",
116 "................X...............",
117 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
118 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
119 "................................",
120 "................................",
121 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
122 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
123 "................X...............",
124 ".............XXXXXXX............",
125 "..............XXXXX.............",
126 "...............XXX..............",
127 "................X..............."
130 // helper inline functions
132 static inline bool rect_contains_point( const wxRect
& rect
, int x
, int y
)
134 return ( x
>= rect
.x
&&
136 x
< rect
.x
+ rect
.width
&&
137 y
< rect
.y
+ rect
.height
);
140 static inline bool rect_hits_rect( const wxRect
& r1
, const wxRect
& r2
)
142 if ( ( r2
.x
>= r1
.x
&& r2
.x
<= r1
.x
+ r1
.width
) ||
143 ( r1
.x
>= r2
.x
&& r1
.x
<= r2
.x
+ r2
.width
) )
145 if ( ( r2
.y
>= r1
.y
&& r2
.y
<= r1
.y
+ r1
.height
) ||
146 ( r1
.y
>= r2
.y
&& r1
.y
<= r2
.y
+ r2
.height
) )
153 static inline void hide_rect( wxRect
& r
)
161 static inline void clip_rect_against_rect( wxRect
& r1
, const wxRect
& r2
)
165 r1
.x
>= r2
.x
+ r2
.width
||
166 r1
.y
>= r2
.y
+ r2
.height
174 if ( r1
.x
+ r1
.width
> r2
.x
+ r2
.width
)
176 r1
.width
= r2
.x
+ r2
.width
- r1
.x
;
178 if ( r1
.y
+ r1
.height
> r2
.y
+ r2
.height
)
180 r1
.height
= r2
.y
+ r2
.height
- r1
.y
;
184 /***** Implementation for class cbBarSpy *****/
186 IMPLEMENT_DYNAMIC_CLASS( cbBarSpy
, wxEvtHandler
)
188 cbBarSpy::cbBarSpy(void)
193 cbBarSpy::cbBarSpy( wxFrameLayout
* pPanel
)
199 void cbBarSpy::SetBarWindow( wxWindow
* pWnd
)
204 bool cbBarSpy::ProcessEvent(wxEvent
& event
)
206 bool handled
= wxEvtHandler::ProcessEvent( event
);
208 int type
= event
.GetEventType();
210 if ( !handled
&& ( type
== wxEVT_LEFT_DOWN
||
211 type
== wxEVT_LEFT_DCLICK
) )
213 wxMouseEvent
& mevent
= *((wxMouseEvent
*)&event
);
218 mpBarWnd
->ClientToScreen( &x
, &y
);
219 mpLayout
->GetParentFrame().ScreenToClient( &x
, &y
);
224 // forwared not-handled event to frame-layout
226 if ( type
== wxEVT_LEFT_DOWN
)
228 //mpLayout->OnLButtonDown( mevent );
232 mpLayout
->OnLDblClick( mevent
);
240 /***** Implementation for class wxFrameLayout *****/
242 IMPLEMENT_DYNAMIC_CLASS( wxFrameLayout
, wxEvtHandler
)
244 BEGIN_EVENT_TABLE( wxFrameLayout
, wxEvtHandler
)
246 EVT_PAINT ( wxFrameLayout::OnPaint
)
247 EVT_SIZE ( wxFrameLayout::OnSize
)
248 EVT_LEFT_DOWN ( wxFrameLayout::OnLButtonDown
)
249 EVT_LEFT_UP ( wxFrameLayout::OnLButtonUp
)
250 EVT_RIGHT_DOWN ( wxFrameLayout::OnRButtonDown
)
251 EVT_RIGHT_UP ( wxFrameLayout::OnRButtonUp
)
252 EVT_MOTION ( wxFrameLayout::OnMouseMove
)
254 EVT_LEFT_DCLICK( wxFrameLayout::OnLDblClick
)
256 EVT_IDLE ( wxFrameLayout::OnIdle
)
257 EVT_SET_FOCUS ( wxFrameLayout::OnSetFocus
)
258 EVT_KILL_FOCUS ( wxFrameLayout::OnKillFocus
)
260 EVT_ACTIVATE ( wxFrameLayout::OnActivate
)
262 EVT_ERASE_BACKGROUND( wxFrameLayout::OnEraseBackground
)
266 // FIXME:: how to eliminate these cut&pasted constructors?
268 wxFrameLayout::wxFrameLayout(void)
271 mpFrameClient( NULL
),
273 mDarkPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
274 mLightPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT
), 1, wxSOLID
),
275 mGrayPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
276 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID
),
277 mBorderPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
279 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT
),
281 mpPaneInFocus( NULL
),
285 mpTopPlugin ( NULL
),
286 mpCaputesInput( NULL
),
288 mClientWndRefreshPending( FALSE
),
289 mRecalcPending( TRUE
),
290 mCheckFocusWhenIdle( FALSE
)
295 for ( i
= 0; i
!= MAX_PANES
; ++i
)
298 mFloatingOn
= CanReparent();
301 wxFrameLayout::wxFrameLayout( wxWindow
* pParentFrame
, wxWindow
* pFrameClient
, bool activateNow
)
303 : mpFrame( pParentFrame
),
304 mpFrameClient(pFrameClient
),
306 mDarkPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
307 mLightPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT
), 1, wxSOLID
),
308 mGrayPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
309 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID
),
310 mBorderPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
312 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT
),
314 mpPaneInFocus( NULL
),
317 mFloatingOn ( TRUE
),
319 mpTopPlugin ( NULL
),
320 mpCaputesInput( NULL
),
322 mClientWndRefreshPending( FALSE
),
323 mRecalcPending( TRUE
),
324 mCheckFocusWhenIdle( FALSE
),
331 for ( i
= 0; i
!= MAX_PANES
; ++i
)
332 mPanes
[i
] = new cbDockPane( i
, this );
339 // DBG:: set RED color of frame's background for the
340 // prurpose of tracking engine bugs "visually"
342 GetParentFrame().SetBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
) );
345 mFloatingOn
= CanReparent();
348 // NOTE:: below are the only platform-check "ifdef"s in the docking system!
350 bool wxFrameLayout::CanReparent()
354 #elif defined (__WXGTK__)
359 return FALSE
; // reparenting is not yet supported by Motif and others
369 void wxFrameLayout::ReparentWindow( wxWindow
* pChild
, wxWindow
* pNewParent
)
374 if ( pChild
->GetParent() )
376 bool success
= pChild
->GetParent()->GetChildren().DeleteObject( pChild
);
378 wxASSERT( success
); // DBG::
381 ::SetParent( (HWND
)pChild
->m_hWnd
, (HWND
)pNewParent
->m_hWnd
);
383 pNewParent
->GetChildren().Append( pChild
);
385 pChild
->SetParent( pNewParent
);
387 pChild
->Reparent(pNewParent
);
390 #elif defined(__WXGTK__)
391 // FOR NOW:: floating with wxGtk still very buggy
395 //pChild->ReParent( pNewParent );
399 wxMessageBox( "Sorry, docking is not supported for ports other than MSW and wxGTK" );
403 void wxFrameLayout::DestroyBarWindows()
405 wxNode
* pSpy
= mBarSpyList
.First();
409 cbBarSpy
& spy
= *((cbBarSpy
*)pSpy
->Data());
411 if ( spy
.mpBarWnd
->GetEventHandler() == &spy
)
413 spy
.mpBarWnd
->PopEventHandler();
423 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
425 if ( mAllBars
[i
]->mpBarWnd
)
427 mAllBars
[i
]->mpBarWnd
->Destroy();
428 mAllBars
[i
]->mpBarWnd
= NULL
;
433 void wxFrameLayout::ShowFloatedWindows( bool show
)
435 wxNode
* pNode
= mFloatedFrames
.First();
439 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
443 pNode
= pNode
->Next();
447 wxFrameLayout::~wxFrameLayout()
456 // destoy the chain of plugins from left to right
458 wxEvtHandler
* pCur
= mpTopPlugin
;
462 while ( pCur
->GetPreviousHandler() )
464 pCur
= pCur
->GetPreviousHandler();
468 wxEvtHandler
* pNext
= pCur
->GetNextHandler();
475 // destroy contents of arrays and lists
478 for ( i
= 0; i
!= MAX_PANES
; ++i
)
484 delete mpHorizCursor
;
487 if ( mpNormalCursor
)
488 delete mpNormalCursor
;
494 wxNode
* pSpy
= mBarSpyList
.First();
498 cbBarSpy
& spy
= *((cbBarSpy
*)pSpy
->Data());
500 if ( spy
.mpBarWnd
->GetEventHandler() == &spy
)
502 spy
.mpBarWnd
->PopEventHandler();
509 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
513 void wxFrameLayout::EnableFloating( bool enable
)
515 mFloatingOn
= enable
&& CanReparent();
518 void wxFrameLayout::Activate()
524 ShowFloatedWindows( TRUE
);
527 void wxFrameLayout::Deactivate()
529 ShowFloatedWindows( FALSE
);
536 void wxFrameLayout::SetFrameClient( wxWindow
* pFrameClient
)
538 mpFrameClient
= pFrameClient
;
541 wxWindow
* wxFrameLayout::GetFrameClient()
543 return mpFrameClient
;
546 cbUpdatesManagerBase
& wxFrameLayout::GetUpdatesManager()
549 mpUpdatesMgr
= CreateUpdatesManager();
551 return *mpUpdatesMgr
;
554 void wxFrameLayout::SetUpdatesManager( cbUpdatesManagerBase
* pUMgr
)
559 mpUpdatesMgr
= pUMgr
;
561 mpUpdatesMgr
->SetLayout( this );
564 cbUpdatesManagerBase
* wxFrameLayout::CreateUpdatesManager()
566 return new cbGCUpdatesMgr( this );
567 //return new cbSimpleUpdatesMgr( this );
570 void wxFrameLayout::AddBar( wxWindow
* pBarWnd
,
571 const cbDimInfo
& dimInfo
,
575 const wxString
& name
,
580 if ( pBarWnd
&& spyEvents
)
582 // hook up spy to bar window
583 cbBarSpy
* pSpy
= new cbBarSpy( this );
585 pSpy
->SetBarWindow( pBarWnd
);
586 pBarWnd
->PushEventHandler( pSpy
);
588 mBarSpyList
.Append( pSpy
);
591 cbBarInfo
* pInfo
= new cbBarInfo();
594 pInfo
->mpBarWnd
= pBarWnd
;
595 pInfo
->mDimInfo
= dimInfo
;
596 pInfo
->mState
= state
;
597 pInfo
->mAlignment
= alignment
;
598 pInfo
->mRowNo
= rowNo
;
599 pInfo
->mBounds
.x
= columnPos
;
601 mAllBars
.Add( pInfo
);
603 DoSetBarState( pInfo
);
606 bool wxFrameLayout::RedockBar( cbBarInfo
* pBar
,
607 const wxRect
& shapeInParent
,
613 pToPane
= HitTestPanes( shapeInParent
, NULL
);
617 return FALSE
; // bar's shape does not hit any pane
618 // - redocking is NOT possible
620 cbDockPane
* pBarPane
= GetBarPane( pBar
);
624 GetUpdatesManager().OnStartChanges();
626 pBarPane
->RemoveBar( pBar
);
628 // FIXME FIXME:: the recalculation below may be a *huge* performance
629 // hit, it could be eliminated though...
630 // but first the "pane-postion-changed" problem
633 RecalcLayout( FALSE
);
635 pToPane
->InsertBar( pBar
, shapeInParent
);
637 RecalcLayout( FALSE
);
639 // finish update "transaction"
643 GetUpdatesManager().OnFinishChanges();
644 GetUpdatesManager().UpdateNow();
650 cbBarInfo
* wxFrameLayout::FindBarByName( const wxString
& name
)
653 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
654 if ( mAllBars
[i
]->mName
== name
)
660 cbBarInfo
* wxFrameLayout::FindBarByWindow( const wxWindow
* pWnd
)
663 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
664 if ( mAllBars
[i
]->mpBarWnd
== pWnd
)
670 BarArrayT
& wxFrameLayout::GetBars()
675 void wxFrameLayout::SetBarState( cbBarInfo
* pBar
, int newState
, bool updateNow
)
677 if ( newState
== wxCBAR_FLOATING
&& !mFloatingOn
)
683 GetUpdatesManager().OnStartChanges();
685 pBar
->mUMgrData
.SetDirty(TRUE
);
687 // check bar's previous state
689 if ( pBar
->mState
!= wxCBAR_HIDDEN
&& pBar
->mState
!= wxCBAR_FLOATING
)
694 bool success
= LocateBar( pBar
, &pRow
, &pPane
);
696 wxASSERT( success
); // DBG::
698 // save LRU-dim info before removing bar
700 pBar
->mDimInfo
.mLRUPane
= pPane
->GetAlignment();
701 pBar
->mDimInfo
.mBounds
[ pPane
->GetAlignment() ] = pBar
->mBounds
;
703 // remove it from the pane it was docked on
705 pPane
->RemoveBar( pBar
);
709 if ( pBar
->mState
== wxCBAR_FLOATING
&& newState
!= wxCBAR_FLOATING
)
711 // remove bar's window from the containing mini-frame
712 // and set its parent to be layout's parent frame
714 if ( pBar
->mpBarWnd
)
716 pBar
->mpBarWnd
->Show(FALSE
); // to avoid flicker upon reparenting
718 wxNode
* pNode
= mFloatedFrames
.First();
722 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
724 if ( pFFrm
->GetBar() == pBar
)
726 pFFrm
->Show( FALSE
); // reduces flicker sligthly
728 ReparentWindow( pBar
->mpBarWnd
, &GetParentFrame() );
730 pBar
->mBounds
= pBar
->mDimInfo
.mBounds
[ pBar
->mDimInfo
.mLRUPane
];
732 if ( newState
!= wxCBAR_HIDDEN
)
734 pBar
->mAlignment
= pBar
->mDimInfo
.mLRUPane
;
736 mFloatedFrames
.DeleteNode( pNode
);
738 pFFrm
->Show( FALSE
);
739 pFFrm
->Destroy(); break;
742 pNode
= pNode
->Next();
745 // FOR NOW:: excessive!
746 //if ( mpFrameClient ) mpFrameClient->Refresh();
748 mClientWndRefreshPending
= TRUE
;
752 pBar
->mState
= newState
;
754 DoSetBarState( pBar
);
760 GetUpdatesManager().OnFinishChanges();
761 GetUpdatesManager().UpdateNow();
765 void wxFrameLayout::InverseVisibility( cbBarInfo
* pBar
)
767 wxASSERT( pBar
); // DBG::
769 // "inverse" bar-visibility of the selected bar
773 if ( pBar
->mState
== wxCBAR_HIDDEN
)
775 if ( pBar
->mAlignment
== -1 )
777 pBar
->mAlignment
= 0; // just remove "-1" marking
778 newState
= wxCBAR_FLOATING
;
781 if ( pBar
->mAlignment
== FL_ALIGN_TOP
||
782 pBar
->mAlignment
== FL_ALIGN_BOTTOM
)
784 newState
= wxCBAR_DOCKED_HORIZONTALLY
;
786 newState
= wxCBAR_DOCKED_VERTICALLY
;
790 newState
= wxCBAR_HIDDEN
;
792 if ( pBar
->mState
== wxCBAR_FLOATING
)
794 pBar
->mAlignment
= -1;
797 this->SetBarState( pBar
, newState
, TRUE
);
799 if ( newState
== wxCBAR_FLOATING
)
801 this->RepositionFloatedBar( pBar
);
804 void wxFrameLayout::ApplyBarProperties( cbBarInfo
* pBar
)
806 if ( pBar
->mState
== wxCBAR_FLOATING
)
808 RepositionFloatedBar( pBar
);
811 if ( pBar
->mState
== wxCBAR_DOCKED_HORIZONTALLY
||
812 pBar
->mState
== wxCBAR_DOCKED_VERTICALLY
820 void wxFrameLayout::RepositionFloatedBar( cbBarInfo
* pBar
)
822 if ( !mFloatingOn
) return;
824 wxNode
* pNode
= mFloatedFrames
.First();
828 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->Data());
830 if ( pFFrm
->GetBar() == pBar
)
832 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
837 GetParentFrame().ClientToScreen( &x
, &y
);
839 pFFrm
->PositionFloatedWnd( x
,y
,
846 pNode
= pNode
->Next();
850 void wxFrameLayout::DoSetBarState( cbBarInfo
* pBar
)
852 if ( pBar
->mState
!= wxCBAR_FLOATING
&&
853 pBar
->mState
!= wxCBAR_HIDDEN
)
857 mPanes
[pBar
->mAlignment
]->InsertBar( pBar
);
859 if ( pBar
->mState
== wxCBAR_HIDDEN
)
863 if ( pBar
->mpBarWnd
)
865 pBar
->mpBarWnd
->Show( FALSE
);
869 if ( !mFloatingOn
) return;
873 if ( pBar
->mpBarWnd
== NULL
|| !CanReparent() )
875 // FOR NOW:: just hide it
877 if ( pBar
->mpBarWnd
)
879 pBar
->mpBarWnd
->Show( FALSE
);
881 pBar
->mState
= wxCBAR_HIDDEN
;
886 cbFloatedBarWindow
* pMiniFrm
= new cbFloatedBarWindow();
888 pMiniFrm
->SetBar( pBar
);
889 pMiniFrm
->SetLayout( this );
891 pMiniFrm
->Create( &GetParentFrame(), -1, pBar
->mName
,
894 wxFRAME_FLOAT_ON_PARENT
| wxFRAME_TOOL_WINDOW
897 pMiniFrm
->SetClient( pBar
->mpBarWnd
);
899 ReparentWindow( pBar
->mpBarWnd
, pMiniFrm
);
901 mFloatedFrames
.Append( pMiniFrm
);
903 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
905 // check if it wasn't floated anytime before
907 if ( bounds
.width
== -1 )
909 wxRect
& clntRect
= GetClientRect();
911 // adjust position into which the next floated bar will be placed
913 if ( mNextFloatedWndPos
.x
+ bounds
.width
> clntRect
.width
)
915 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
917 if ( mNextFloatedWndPos
.y
+ bounds
.height
> clntRect
.height
)
919 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
921 bounds
.x
= mNextFloatedWndPos
.x
+ clntRect
.x
;
922 bounds
.y
= mNextFloatedWndPos
.y
+ clntRect
.y
;
924 bounds
.width
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].x
;
925 bounds
.height
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].y
;
927 mNextFloatedWndPos
.x
+= mFloatingPosStep
.x
;
928 mNextFloatedWndPos
.y
+= mFloatingPosStep
.y
;
931 pMiniFrm
->Show( TRUE
);
933 // FIXME:: this is excessive
934 pBar
->mpBarWnd
->Show(TRUE
);
938 void wxFrameLayout::RemoveBar( cbBarInfo
* pBarInfo
)
940 // first, try to "guess" what was the perviouse state of the bar
945 if ( LocateBar( pBarInfo
, &pRow
, &pPane
) )
947 // ...aha, bar was docked into one of the panes,
948 // remove it from there
950 pPane
->RemoveBar( pBarInfo
);
954 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
956 if ( mAllBars
[i
] == pBarInfo
)
958 #if wxCHECK_VERSION(2,3,2)
959 mAllBars
.RemoveAt(i
);
963 if ( pBarInfo
->mpBarWnd
) // hides it's window
965 pBarInfo
->mpBarWnd
->Show( FALSE
);
972 wxFAIL_MSG("bar info should be present in the list of all bars of all panes");
975 bool wxFrameLayout::LocateBar( cbBarInfo
* pBarInfo
,
977 cbDockPane
** ppPane
)
983 for ( n
= 0; n
!= MAX_PANES
; ++n
)
985 wxBarIterator
i( mPanes
[n
]->GetRowList() );
989 if ( &i
.BarInfo() == pBarInfo
)
991 (*ppPane
) = mPanes
[n
];
992 (*ppRow
) = &i
.RowInfo();
1001 void wxFrameLayout::RecalcLayout( bool repositionBarsNow
)
1003 mRecalcPending
= FALSE
;
1005 int frmWidth
, frmHeight
;
1006 mpFrame
->GetClientSize( &frmWidth
, &frmHeight
);
1013 // pane positioning priorities in decreasing order:
1014 // top, bottom, left, right
1018 cbDockPane
* pPane
= mPanes
[ FL_ALIGN_TOP
];
1020 pPane
->SetPaneWidth( frmWidth
);
1021 pPane
->RecalcLayout();
1023 paneHeight
= pPane
->GetPaneHeight();
1027 rect
.width
= frmWidth
;
1028 rect
.height
= wxMin( paneHeight
, frmHeight
- curY
);
1030 pPane
->SetBoundsInParent( rect
);
1034 // setup BOTTOM pane
1036 pPane
= mPanes
[ FL_ALIGN_BOTTOM
];
1038 pPane
->SetPaneWidth( frmWidth
);
1039 pPane
->RecalcLayout();
1041 paneHeight
= pPane
->GetPaneHeight();
1044 rect
.y
= wxMax( frmHeight
- paneHeight
, curY
);
1045 rect
.width
= frmWidth
;
1046 rect
.height
= frmHeight
- rect
.y
;
1048 pPane
->SetBoundsInParent( rect
);
1052 pPane
= mPanes
[ FL_ALIGN_LEFT
];
1055 pPane
->SetPaneWidth( rect
.y
- curY
);
1057 pPane
->RecalcLayout();
1058 paneHeight
= pPane
->GetPaneHeight();
1061 rect
.height
= rect
.y
- curY
;
1064 rect
.width
= wxMin( paneHeight
, frmWidth
);
1066 pPane
->SetBoundsInParent( rect
);
1072 pPane
= mPanes
[ FL_ALIGN_RIGHT
];
1074 // left pane's height
1075 pPane
->SetPaneWidth( rect
.height
);
1077 pPane
->RecalcLayout();
1078 paneHeight
= pPane
->GetPaneHeight();
1080 // left pane's height
1081 rect
.height
= rect
.height
;
1082 rect
.x
= wxMax( frmWidth
- paneHeight
, curX
);
1084 rect
.width
= frmWidth
- rect
.x
;
1086 pPane
->SetBoundsInParent( rect
);
1088 // recalc bounds of the client-window
1090 mClntWndBounds
.x
= mPanes
[FL_ALIGN_LEFT
]->mBoundsInParent
.x
+
1091 mPanes
[FL_ALIGN_LEFT
]->mBoundsInParent
.width
;
1092 mClntWndBounds
.y
= mPanes
[FL_ALIGN_TOP
]->mBoundsInParent
.y
+
1093 mPanes
[FL_ALIGN_TOP
]->mBoundsInParent
.height
;
1095 mClntWndBounds
.width
= mPanes
[FL_ALIGN_RIGHT
]->mBoundsInParent
.x
-
1097 mClntWndBounds
.height
= mPanes
[FL_ALIGN_BOTTOM
]->mBoundsInParent
.y
-
1100 if ( repositionBarsNow
)
1105 int wxFrameLayout::GetClientHeight()
1107 // for better portablility wxWindow::GetSzie() is not used here
1109 return mClntWndBounds
.height
;
1112 int wxFrameLayout::GetClientWidth()
1114 // for better portablility wxWindow::GetSzie() is not used here
1116 return mClntWndBounds
.width
;
1119 void wxFrameLayout::PositionClientWindow()
1121 if ( mpFrameClient
)
1123 if ( mClntWndBounds
.width
>= 1 && mClntWndBounds
.height
>= 1 )
1125 mpFrameClient
->SetSize( mClntWndBounds
.x
, mClntWndBounds
.y
,
1126 mClntWndBounds
.width
, mClntWndBounds
.height
, 0 );
1128 if ( !mpFrameClient
->IsShown() )
1130 mpFrameClient
->Show( TRUE
);
1133 mpFrameClient
->Show( FALSE
);
1137 void wxFrameLayout::PositionPanes()
1139 PositionClientWindow();
1141 // FOR NOW:: excessive updates!
1142 // reposition bars within all panes
1145 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1146 mPanes
[i
]->SizePaneObjects();
1149 void wxFrameLayout::OnSize( wxSizeEvent
& event
)
1151 if ( event
.GetEventObject() == (wxObject
*) mpFrame
)
1153 GetUpdatesManager().OnStartChanges();
1155 GetUpdatesManager().OnFinishChanges();
1156 GetUpdatesManager().UpdateNow();
1161 /*** protected members ***/
1163 void wxFrameLayout::HideBarWindows()
1166 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
1167 if ( mAllBars
[i
]->mpBarWnd
&& mAllBars
[i
]->mState
!= wxCBAR_FLOATING
)
1168 mAllBars
[i
]->mpBarWnd
->Show( FALSE
);
1170 // then floated frames
1172 ShowFloatedWindows( FALSE
);
1174 if ( mpFrameClient
)
1176 mpFrameClient
->Show( FALSE
);
1179 void wxFrameLayout::UnhookFromFrame()
1181 // NOTE:: the SetEvtHandlerEnabled() method is not used
1182 // here, since it is assumed that unhooking layout
1183 // from window may result destroying of the layout itself
1185 // BUG BUG BUG (wx):: this would not be a problem if
1186 // wxEvtHandler's destructor checked if
1187 // this handler is currently the top-most
1188 // handler of some window, and additionally
1189 // to the reconnecting itself from the chain.
1190 // It would also re-setup current event handler
1191 // of the window using wxWindow::SetEventHandler()
1195 if ( mpFrame
->GetEventHandler() == this )
1197 mpFrame
->PopEventHandler();
1203 if ( this == mpFrame
->GetEventHandler() )
1205 mpFrame
->SetEventHandler( this->GetNextHandler() );
1209 wxEvtHandler
* pCur
= mpFrame
->GetEventHandler();
1216 pCur
= pCur
->GetNextHandler();
1219 // do not try to unhook ourselves if we're not hooked yet
1224 if ( GetPreviousHandler() )
1225 GetPreviousHandler()->SetNextHandler( GetNextHandler() );
1228 mpFrame
->PopEventHandler();
1232 if ( GetNextHandler() )
1233 GetNextHandler()->SetPreviousHandler( GetPreviousHandler() );
1235 SetNextHandler( NULL
);
1236 SetPreviousHandler( NULL
);
1240 void wxFrameLayout::HookUpToFrame()
1242 // unhook us first, we're already hooked up
1246 // put ourselves on top
1248 mpFrame
->PushEventHandler( this );
1251 cbDockPane
* wxFrameLayout::GetBarPane( cbBarInfo
* pBar
)
1254 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1255 if ( mPanes
[i
]->BarPresent( pBar
) )
1261 void wxFrameLayout::CreateCursors()
1264 // FIXME:: The below code somehow doesn't work - cursors remain unchanged
1267 set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
1269 mpHorizCursor = new wxCursor( bits, 32, 16 );
1271 set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
1273 mpVertCursor = new wxCursor( bits, 32, 16 );
1276 // FOR NOW:: use standard ones
1278 mpHorizCursor
= new wxCursor(wxCURSOR_SIZEWE
);
1279 mpVertCursor
= new wxCursor(wxCURSOR_SIZENS
);
1280 mpNormalCursor
= new wxCursor(wxCURSOR_ARROW
);
1281 mpDragCursor
= new wxCursor(wxCURSOR_CROSS
);
1282 mpNECursor
= new wxCursor(wxCURSOR_NO_ENTRY
);
1284 mFloatingPosStep
.x
= 25;
1285 mFloatingPosStep
.y
= 25;
1287 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
1288 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
1291 bool wxFrameLayout::HitTestPane( cbDockPane
* pPane
, int x
, int y
)
1293 return rect_contains_point( pPane
->GetRealRect(), x
, y
);
1296 cbDockPane
* wxFrameLayout::HitTestPanes( const wxRect
& rect
,
1297 cbDockPane
* pCurPane
)
1299 // first, give the privilege to the current pane
1301 if ( pCurPane
&& rect_hits_rect( pCurPane
->GetRealRect(), rect
) )
1306 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1308 if ( pCurPane
!= mPanes
[i
] &&
1309 rect_hits_rect( mPanes
[i
]->GetRealRect(), rect
) )
1317 void wxFrameLayout::ForwardMouseEvent( wxMouseEvent
& event
,
1318 cbDockPane
* pToPane
,
1321 wxPoint
pos( event
.m_x
, event
.m_y
);
1322 pToPane
->FrameToPane( &pos
.x
, &pos
.y
);
1324 if ( eventType
== cbEVT_PL_LEFT_DOWN
)
1326 cbLeftDownEvent
evt( pos
, pToPane
);
1327 FirePluginEvent( evt
);
1329 else if ( eventType
== cbEVT_PL_LEFT_DCLICK
)
1331 cbLeftDClickEvent
evt( pos
, pToPane
);
1332 FirePluginEvent( evt
);
1334 else if ( eventType
== cbEVT_PL_LEFT_UP
)
1336 cbLeftUpEvent
evt( pos
, pToPane
);
1337 FirePluginEvent( evt
);
1339 else if ( eventType
== cbEVT_PL_RIGHT_DOWN
)
1341 cbRightDownEvent
evt( pos
, pToPane
);
1342 FirePluginEvent( evt
);
1344 else if ( eventType
== cbEVT_PL_RIGHT_UP
)
1346 cbRightUpEvent
evt( pos
, pToPane
);
1347 FirePluginEvent( evt
);
1349 else if ( eventType
== cbEVT_PL_MOTION
)
1351 cbMotionEvent
evt( pos
, pToPane
);
1352 FirePluginEvent( evt
);
1356 int avoidCompilerWarning
= 0;
1357 wxASSERT(avoidCompilerWarning
); // DBG::
1359 } // wxFrameLayout::ForwardMouseEvent()
1362 void wxFrameLayout::RouteMouseEvent( wxMouseEvent
& event
, int pluginEvtType
)
1364 if ( mpPaneInFocus
)
1366 ForwardMouseEvent( event
, mpPaneInFocus
, pluginEvtType
);
1370 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1372 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1374 ForwardMouseEvent( event
, mPanes
[i
], pluginEvtType
);
1381 /*** event handlers ***/
1383 void wxFrameLayout::OnRButtonDown( wxMouseEvent
& event
)
1385 RouteMouseEvent( event
, cbEVT_PL_RIGHT_DOWN
);
1388 void wxFrameLayout::OnRButtonUp( wxMouseEvent
& event
)
1390 RouteMouseEvent( event
, cbEVT_PL_RIGHT_UP
);
1393 void wxFrameLayout::OnLButtonDown( wxMouseEvent
& event
)
1395 RouteMouseEvent( event
, cbEVT_PL_LEFT_DOWN
);
1398 void wxFrameLayout::OnLDblClick( wxMouseEvent
& event
)
1400 RouteMouseEvent( event
, cbEVT_PL_LEFT_DCLICK
);
1403 void wxFrameLayout::OnLButtonUp( wxMouseEvent
& event
)
1405 RouteMouseEvent( event
, cbEVT_PL_LEFT_UP
);
1408 void wxFrameLayout::OnMouseMove( wxMouseEvent
& event
)
1410 if ( mpPaneInFocus
)
1412 ForwardMouseEvent( event
, mpPaneInFocus
, cbEVT_PL_MOTION
);
1416 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1418 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1420 if ( mpLRUPane
&& mpLRUPane
!= mPanes
[i
] )
1422 // simulate "mouse-leave" event
1423 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1426 ForwardMouseEvent( event
, mPanes
[i
], cbEVT_PL_MOTION
);
1428 mpLRUPane
= mPanes
[i
];
1437 // simulate "mouse-leave" event
1438 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1443 void wxFrameLayout::OnPaint( wxPaintEvent
& event
)
1445 if ( mRecalcPending
)
1446 RecalcLayout( TRUE
);
1448 wxPaintDC
dc(mpFrame
);
1451 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1453 wxRect
& rect
= mPanes
[i
]->mBoundsInParent
;
1455 dc
.SetClippingRegion( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1457 mPanes
[i
]->PaintPane(dc
);
1459 dc
.DestroyClippingRegion();
1465 void wxFrameLayout::OnEraseBackground( wxEraseEvent
& event
)
1470 void wxFrameLayout::OnIdle( wxIdleEvent
& event
)
1472 wxWindow
* focus
= wxWindow::FindFocus();
1474 if ( !focus
&& mCheckFocusWhenIdle
)
1476 wxMessageBox( "Hi, no more focus in this app!" );
1478 mCheckFocusWhenIdle
= FALSE
;
1479 //ShowFloatedWindows( FALSE );
1482 mCheckFocusWhenIdle
= FALSE
;
1488 void wxFrameLayout::OnKillFocus( wxFocusEvent
& event
)
1490 //wxMessageBox( "wxFrameLayoutGot Kill Focus!" );
1491 //ShowFloatedWindows( FALSE );
1494 void wxFrameLayout::OnSetFocus( wxFocusEvent
& event
)
1496 //ShowFloatedWindows( TRUE );
1499 void wxFrameLayout::OnActivate( wxActivateEvent
& event
)
1502 if ( event
.GetActive() == FALSE
)
1504 wxWindow
* focus
= wxWindow::FindFocus();
1506 if ( !focus
|| focus
== &GetParentFrame() )
1508 mCheckFocusWhenIdle
= TRUE
;
1512 wxMessageBox("Deactivated!" );
1519 void wxFrameLayout::GetPaneProperties( cbCommonPaneProperties
& props
, int alignment
)
1521 props
= mPanes
[alignment
]->mProps
;
1524 void wxFrameLayout::SetPaneProperties( const cbCommonPaneProperties
& props
, int paneMask
)
1527 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1529 if ( mPanes
[i
]->MatchesMask( paneMask
) )
1530 mPanes
[i
]->mProps
= props
;
1534 void wxFrameLayout::SetMargins( int top
, int bottom
, int left
, int right
,
1538 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1540 cbDockPane
& pane
= *mPanes
[i
];
1542 if ( pane
.MatchesMask( paneMask
) )
1544 pane
.mTopMargin
= top
;
1545 pane
.mBottomMargin
= bottom
;
1546 pane
.mLeftMargin
= left
;
1547 pane
.mRightMargin
= right
;
1552 void wxFrameLayout::SetPaneBackground( const wxColour
& colour
)
1554 mBorderPen
.SetColour( colour
);
1557 void wxFrameLayout::RefreshNow( bool recalcLayout
)
1560 RecalcLayout( TRUE
);
1566 /*** plugin-related methods ***/
1568 void wxFrameLayout::FirePluginEvent( cbPluginEvent
& event
)
1570 // check state of input capture, before processing the event
1572 if ( mpCaputesInput
)
1574 bool isInputEvt
= TRUE
;
1575 #if wxCHECK_VERSION(2,3,0)
1576 if ( event
.m_eventType
!= cbEVT_PL_LEFT_DOWN
&&
1577 event
.m_eventType
!= cbEVT_PL_LEFT_UP
&&
1578 event
.m_eventType
!= cbEVT_PL_RIGHT_DOWN
&&
1579 event
.m_eventType
!= cbEVT_PL_RIGHT_UP
&&
1580 event
.m_eventType
!= cbEVT_PL_MOTION
)
1583 switch ( event
.m_eventType
)
1585 case cbEVT_PL_LEFT_DOWN
: break;
1586 case cbEVT_PL_LEFT_UP
: break;
1587 case cbEVT_PL_RIGHT_DOWN
: break;
1588 case cbEVT_PL_RIGHT_UP
: break;
1589 case cbEVT_PL_MOTION
: break;
1591 default : isInputEvt
= FALSE
; break;
1593 #endif // #if wxCHECK_VERSION(2,3,0)
1597 mpCaputesInput
->ProcessEvent( event
);
1602 GetTopPlugin().ProcessEvent( event
);
1605 void wxFrameLayout::CaptureEventsForPlugin ( cbPluginBase
* pPlugin
)
1607 // cannot capture events for more than one plugin at a time
1608 wxASSERT( mpCaputesInput
== NULL
);
1610 mpCaputesInput
= pPlugin
;
1614 void wxFrameLayout::ReleaseEventsFromPlugin( cbPluginBase
* pPlugin
)
1616 // events should be captured first
1617 wxASSERT( mpCaputesInput
!= NULL
);
1619 mpCaputesInput
= NULL
;
1622 void wxFrameLayout::CaptureEventsForPane( cbDockPane
* toPane
)
1624 // cannot capture events twice (without releasing)
1625 wxASSERT( mpPaneInFocus
== NULL
);
1627 mpFrame
->CaptureMouse();
1629 mpPaneInFocus
= toPane
;
1632 void wxFrameLayout::ReleaseEventsFromPane( cbDockPane
* fromPane
)
1634 // cannot release events without capturing them
1635 wxASSERT( mpPaneInFocus
!= NULL
);
1637 mpFrame
->ReleaseMouse();
1639 mpPaneInFocus
= NULL
;
1642 cbPluginBase
& wxFrameLayout::GetTopPlugin()
1646 PushDefaultPlugins(); // automatic configuration
1648 return *mpTopPlugin
;
1651 void wxFrameLayout::SetTopPlugin( cbPluginBase
* pPlugin
)
1653 mpTopPlugin
= pPlugin
;
1656 bool wxFrameLayout::HasTopPlugin()
1658 return ( mpTopPlugin
!= NULL
);
1661 void wxFrameLayout::PushPlugin( cbPluginBase
* pPlugin
)
1665 mpTopPlugin
= pPlugin
;
1668 pPlugin
->SetNextHandler( mpTopPlugin
);
1670 mpTopPlugin
->SetPreviousHandler( pPlugin
);
1672 mpTopPlugin
= pPlugin
;
1675 mpTopPlugin
->OnInitPlugin(); // notification
1678 void wxFrameLayout::PopPlugin()
1680 wxASSERT( mpTopPlugin
); // DBG:: at least one plugin should be present
1682 cbPluginBase
* pPopped
= mpTopPlugin
;
1684 mpTopPlugin
= (cbPluginBase
*)mpTopPlugin
->GetNextHandler();
1689 void wxFrameLayout::PopAllPlugins()
1691 while( mpTopPlugin
) PopPlugin();
1694 void wxFrameLayout::PushDefaultPlugins()
1696 // FIXME:: to much of the stuff for the default...
1698 AddPlugin( CLASSINFO( cbRowLayoutPlugin
) );
1699 AddPlugin( CLASSINFO( cbBarDragPlugin
) );
1700 AddPlugin( CLASSINFO( cbPaneDrawPlugin
) );
1703 void wxFrameLayout::AddPlugin( wxClassInfo
* pPlInfo
, int paneMask
)
1705 if ( FindPlugin ( pPlInfo
) ) return; // same type of plugin cannot be added twice
1707 cbPluginBase
* pObj
= (cbPluginBase
*)pPlInfo
->CreateObject();
1709 wxASSERT(pObj
); // DBG:: plugin's class should be dynamic
1711 pObj
->mPaneMask
= paneMask
;
1712 pObj
->mpLayout
= this;
1717 void wxFrameLayout::AddPluginBefore( wxClassInfo
* pNextPlInfo
, wxClassInfo
* pPlInfo
,
1720 wxASSERT( pNextPlInfo
!= pPlInfo
); // DBG:: no sense
1722 cbPluginBase
* pNextPl
= FindPlugin( pNextPlInfo
);
1726 AddPlugin( pPlInfo
, paneMask
);
1731 // remove existing one if present
1733 cbPluginBase
* pExistingPl
= FindPlugin( pPlInfo
);
1735 if ( pExistingPl
) RemovePlugin( pPlInfo
);
1737 // create an instance
1739 cbPluginBase
* pNewPl
= (cbPluginBase
*)pPlInfo
->CreateObject();
1741 wxASSERT(pNewPl
); // DBG:: plugin's class should be dynamic
1743 // insert it to the chain
1745 if ( pNextPl
->GetPreviousHandler() )
1747 pNextPl
->GetPreviousHandler()->SetNextHandler( pNewPl
);
1749 mpTopPlugin
= pNewPl
;
1751 pNewPl
->SetNextHandler( pNextPl
);
1753 pNewPl
->SetPreviousHandler( pNextPl
->GetPreviousHandler() );
1755 pNextPl
->SetPreviousHandler( pNewPl
);
1759 pNewPl
->mPaneMask
= paneMask
;
1760 pNewPl
->mpLayout
= this;
1762 pNewPl
->OnInitPlugin();
1765 void wxFrameLayout::RemovePlugin( wxClassInfo
* pPlInfo
)
1767 cbPluginBase
* pPlugin
= FindPlugin( pPlInfo
);
1769 if ( !pPlugin
) return; // it's OK to remove not-existing plugin ;-)
1771 if ( pPlugin
->GetPreviousHandler() == NULL
)
1773 mpTopPlugin
= (cbPluginBase
*)pPlugin
->GetNextHandler();
1778 cbPluginBase
* wxFrameLayout::FindPlugin( wxClassInfo
* pPlInfo
)
1780 cbPluginBase
*pCur
= mpTopPlugin
;
1784 // NOTE:: it might appear useful matching plugin
1785 // classes "polymorphically":
1787 if ( pCur
->GetClassInfo()->IsKindOf( pPlInfo
) )
1791 pCur
= (cbPluginBase
*)pCur
->GetNextHandler();
1797 /***** Implementation for class cbUpdateMgrData *****/
1799 IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData
, wxObject
)
1801 cbUpdateMgrData::cbUpdateMgrData()
1803 : mPrevBounds( -1,-1,0,0 ),
1804 mIsDirty( TRUE
) // inidicate initial change
1807 void cbUpdateMgrData::StoreItemState( const wxRect
& boundsInParent
)
1809 mPrevBounds
= boundsInParent
;
1812 void cbUpdateMgrData::SetDirty( bool isDirty
)
1817 void cbUpdateMgrData::SetCustomData( wxObject
* pCustomData
)
1819 mpCustomData
= pCustomData
;
1822 /***** Implementation for class cbDockPane *****/
1824 void wxBarIterator::Reset()
1826 mpRow
= ( mpRows
->Count() ) ? (*mpRows
)[0] : NULL
;
1830 wxBarIterator::wxBarIterator( RowArrayT
& rows
)
1839 bool wxBarIterator::Next()
1844 mpBar
= mpBar
->mpNext
;
1847 if ( mpRow
->mBars
.GetCount() == 0 )
1852 mpBar
= mpRow
->mBars
[0];
1857 // skip to the next row
1859 mpRow
= mpRow
->mpNext
;
1863 mpBar
= mpRow
->mBars
[0];
1874 cbBarInfo
& wxBarIterator::BarInfo()
1879 cbRowInfo
& wxBarIterator::RowInfo()
1884 /***** Implementation for class cbBarDimHandlerBase *****/
1886 IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase
, wxObject
)
1888 cbBarDimHandlerBase::cbBarDimHandlerBase()
1892 void cbBarDimHandlerBase::AddRef()
1897 void cbBarDimHandlerBase::RemoveRef()
1899 if ( --mRefCount
<= 0 ) delete this;
1902 /***** Implementation for class cbDimInfo *****/
1904 IMPLEMENT_DYNAMIC_CLASS( cbDimInfo
, wxObject
)
1906 cbDimInfo::cbDimInfo()
1915 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1920 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1924 cbDimInfo::cbDimInfo( cbBarDimHandlerBase
* pDimHandler
,
1929 mIsFixed ( isFixed
),
1931 mpHandler( pDimHandler
)
1935 // int vtad = *((int*)mpHandler);
1936 mpHandler
->AddRef();
1940 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1945 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1949 cbDimInfo::cbDimInfo( int dh_x
, int dh_y
,
1957 cbBarDimHandlerBase
* pDimHandler
1959 : mVertGap ( vertGap
),
1960 mHorizGap ( horizGap
),
1961 mIsFixed ( isFixed
),
1962 mpHandler( pDimHandler
)
1966 // int vtad = *((int*)mpHandler);
1967 mpHandler
->AddRef();
1970 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= dh_x
;
1971 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= dh_y
;
1972 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= dv_x
;
1973 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= dv_y
;
1974 mSizes
[wxCBAR_FLOATING
].x
= f_x
;
1975 mSizes
[wxCBAR_FLOATING
].y
= f_y
;
1978 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1979 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1982 cbDimInfo::cbDimInfo( int x
, int y
,
1983 bool isFixed
, int gap
,
1984 cbBarDimHandlerBase
* pDimHandler
)
1987 mIsFixed ( isFixed
),
1988 mpHandler( pDimHandler
)
1992 // int vtad = *((int*)mpHandler);
1993 mpHandler
->AddRef();
1996 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= x
;
1997 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= y
;
1998 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= x
;
1999 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= y
;
2000 mSizes
[wxCBAR_FLOATING
].x
= x
;
2001 mSizes
[wxCBAR_FLOATING
].y
= y
;
2004 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2005 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
2008 cbDimInfo::~cbDimInfo()
2012 mpHandler
->RemoveRef();
2015 const cbDimInfo
& cbDimInfo::operator=( const cbDimInfo
& other
)
2017 if ( this == &other
)
2021 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2022 mSizes
[i
] = other
.mSizes
[i
];
2024 mIsFixed
= other
.mIsFixed
;
2025 mpHandler
= other
.mpHandler
;
2027 mVertGap
= other
.mVertGap
;
2028 mHorizGap
= other
.mHorizGap
;
2032 mpHandler
->AddRef();
2037 /***** Implementation for structure cbCommonPaneProperties *****/
2039 IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties
, wxObject
)
2041 cbCommonPaneProperties::cbCommonPaneProperties(void)
2043 : mRealTimeUpdatesOn ( TRUE
),
2044 mOutOfPaneDragOn ( TRUE
),
2045 mExactDockPredictionOn( FALSE
),
2046 mNonDestructFirctionOn( FALSE
),
2047 mShow3DPaneBorderOn ( TRUE
),
2048 mBarFloatingOn ( FALSE
),
2049 mRowProportionsOn ( FALSE
),
2050 mColProportionsOn ( TRUE
),
2051 mBarCollapseIconsOn ( FALSE
),
2052 mBarDragHintsOn ( FALSE
),
2054 mMinCBarDim( 16, 16 ),
2055 mResizeHandleSize( 4 )
2058 /***** Implementation for class cbRowInfo *****/
2060 IMPLEMENT_DYNAMIC_CLASS( cbRowInfo
, wxObject
)
2062 cbRowInfo::cbRowInfo(void)
2064 : mNotFixedBarsCnt( FALSE
),
2067 mpExpandedBar ( NULL
)
2070 cbRowInfo::~cbRowInfo()
2072 // nothing! all bars are removed using global bar
2073 // list in wxFrameLayout class
2076 /***** Implementation for class cbBarInfo *****/
2078 IMPLEMENT_DYNAMIC_CLASS( cbBarInfo
, wxObject
)
2080 cbBarInfo::cbBarInfo(void)
2088 cbBarInfo::~cbBarInfo()
2093 /***** Implementation for class cbDockPane *****/
2095 IMPLEMENT_DYNAMIC_CLASS( cbDockPane
, wxObject
)
2097 // FIXME:: how to eliminate these cut&pasted constructors?
2099 cbDockPane::cbDockPane(void)
2100 : mLeftMargin ( 1 ),
2104 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2105 // since the real dimensions of the pane may not
2106 // be known, while inserting bars initially
2107 mPaneHeight( 32768 ),
2113 cbDockPane::cbDockPane( int alignment
, wxFrameLayout
* pPanel
)
2115 : mLeftMargin ( 1 ),
2119 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2120 // since the real dimensions of the pane may not
2121 // be known, while inserting bars initially
2122 mPaneHeight( 32768 ),
2123 mAlignment ( alignment
),
2124 mpLayout ( pPanel
),
2128 cbDockPane::~cbDockPane()
2131 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2134 mRowShapeData
.DeleteContents( TRUE
);
2136 // NOTE:: control bar infromation structures are cleaned-up
2137 // in wxFrameLayout's destructor, using global control-bar list
2140 void cbDockPane::SetMargins( int top
, int bottom
, int left
, int right
)
2143 mBottomMargin
= bottom
;
2145 mRightMargin
= right
;
2148 /*** helpers of cbDockPane ***/
2150 void cbDockPane::PaintBarDecorations( cbBarInfo
* pBar
, wxDC
& dc
)
2152 cbDrawBarDecorEvent
evt( pBar
, dc
, this );
2154 mpLayout
->FirePluginEvent( evt
);
2157 void cbDockPane::PaintBarHandles( cbBarInfo
* pBar
, wxDC
& dc
)
2159 cbDrawBarHandlesEvent
evt( pBar
, dc
, this );
2161 mpLayout
->FirePluginEvent( evt
);
2164 void cbDockPane::PaintBar( cbBarInfo
* pBar
, wxDC
& dc
)
2166 PaintBarDecorations( pBar
, dc
);
2167 PaintBarHandles( pBar
, dc
);
2170 void cbDockPane::PaintRowHandles( cbRowInfo
* pRow
, wxDC
& dc
)
2172 cbDrawRowHandlesEvent
evt( pRow
, dc
, this );
2174 mpLayout
->FirePluginEvent( evt
);
2176 cbDrawRowDecorEvent
evt1( pRow
, dc
, this );
2178 mpLayout
->FirePluginEvent( evt1
);
2181 void cbDockPane::PaintRowBackground ( cbRowInfo
* pRow
, wxDC
& dc
)
2183 cbDrawRowBkGroundEvent
evt( pRow
, dc
, this );
2185 mpLayout
->FirePluginEvent( evt
);
2188 void cbDockPane::PaintRowDecorations( cbRowInfo
* pRow
, wxDC
& dc
)
2192 // decorations first
2193 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2195 PaintBarDecorations( pRow
->mBars
[i
], dc
);
2197 // then handles if present
2198 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2200 PaintBarHandles( pRow
->mBars
[i
], dc
);
2203 void cbDockPane::PaintRow( cbRowInfo
* pRow
, wxDC
& dc
)
2205 PaintRowBackground ( pRow
, dc
);
2206 PaintRowDecorations( pRow
, dc
);
2207 PaintRowHandles ( pRow
, dc
);
2210 void cbDockPane::PaintPaneBackground( wxDC
& dc
)
2212 cbDrawPaneBkGroundEvent
evt( dc
, this );
2214 mpLayout
->FirePluginEvent( evt
);
2217 void cbDockPane::PaintPaneDecorations( wxDC
& dc
)
2219 cbDrawPaneDecorEvent
evt( dc
, this );
2221 mpLayout
->FirePluginEvent( evt
);
2224 void cbDockPane::PaintPane( wxDC
& dc
)
2226 PaintPaneBackground( dc
);
2230 // first decorations
2231 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2233 PaintRowBackground( mRows
[i
], dc
);
2234 PaintRowDecorations( mRows
[i
], dc
);
2238 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2239 PaintRowHandles( mRows
[i
], dc
);
2242 PaintPaneDecorations( dc
);
2245 void cbDockPane::SizeBar( cbBarInfo
* pBar
)
2247 cbSizeBarWndEvent
evt( pBar
, this );
2249 mpLayout
->FirePluginEvent( evt
);
2253 void cbDockPane::SizeRowObjects( cbRowInfo
* pRow
)
2256 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2257 SizeBar( pRow
->mBars
[i
] );
2260 void cbDockPane::SizePaneObjects()
2263 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2264 SizeRowObjects( mRows
[i
] );
2267 wxDC
* cbDockPane::StartDrawInArea( const wxRect
& area
)
2271 cbStartDrawInAreaEvent
evt( area
, &pDc
, this );
2273 mpLayout
->FirePluginEvent( evt
);
2278 void cbDockPane::FinishDrawInArea( const wxRect
& area
)
2280 cbFinishDrawInAreaEvent
evt( area
, this );
2282 mpLayout
->FirePluginEvent( evt
);
2285 bool cbDockPane::IsFixedSize( cbBarInfo
* pInfo
)
2287 return ( pInfo
->mDimInfo
.mIsFixed
);
2290 int cbDockPane::GetNotFixedBarsCount( cbRowInfo
* pRow
)
2295 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2297 if ( !pRow
->mBars
[i
]->IsFixed() )
2304 void cbDockPane::RemoveBar( cbBarInfo
* pBar
)
2306 bool needsRestoring
= mProps
.mNonDestructFirctionOn
&&
2307 mpStoredRow
== pBar
->mpRow
;
2309 cbRemoveBarEvent
evt( pBar
, this );
2311 mpLayout
->FirePluginEvent( evt
);
2313 if ( needsRestoring
)
2315 SetRowShapeData( mpStoredRow
, &mRowShapeData
);
2321 void cbDockPane::SyncRowFlags( cbRowInfo
* pRow
)
2323 // setup mHasOnlyFixedBars flag for the row information
2324 pRow
->mHasOnlyFixedBars
= TRUE
;
2326 pRow
->mNotFixedBarsCnt
= 0;
2329 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2331 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2335 if ( !bar
.IsFixed() )
2337 pRow
->mHasOnlyFixedBars
= FALSE
;
2338 ++pRow
->mNotFixedBarsCnt
;
2343 void cbDockPane::FrameToPane( int* x
, int* y
)
2348 if ( mAlignment
== FL_ALIGN_TOP
||
2349 mAlignment
== FL_ALIGN_BOTTOM
2352 *x
-= mBoundsInParent
.x
;
2353 *y
-= mBoundsInParent
.y
;
2357 int rx
= *x
, ry
= *y
;
2359 *x
= ry
- mBoundsInParent
.y
;
2361 *y
= rx
- mBoundsInParent
.x
;
2365 void cbDockPane::PaneToFrame( int* x
, int* y
)
2367 if ( mAlignment
== FL_ALIGN_TOP
||
2368 mAlignment
== FL_ALIGN_BOTTOM
2371 *x
+= mBoundsInParent
.x
;
2372 *y
+= mBoundsInParent
.y
;
2376 int rx
= *x
, ry
= *y
;
2378 *x
= ry
+ mBoundsInParent
.x
;
2380 *y
= mBoundsInParent
.y
+ rx
;
2387 void cbDockPane::FrameToPane( wxRect
* pRect
)
2389 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2390 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2391 pRect
->y
+ pRect
->height
);
2393 FrameToPane( &upperLeft
.x
, &upperLeft
.y
);
2394 FrameToPane( &lowerRight
.x
, &lowerRight
.y
);
2396 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2397 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2399 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2400 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2403 void cbDockPane::PaneToFrame( wxRect
* pRect
)
2405 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2406 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2407 pRect
->y
+ pRect
->height
);
2409 PaneToFrame( &upperLeft
.x
, &upperLeft
.y
);
2410 PaneToFrame( &lowerRight
.x
, &lowerRight
.y
);
2412 //wxRect newRect = wxRect( upperLeft, lowerRight );
2414 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2415 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2417 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2418 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2421 int cbDockPane::GetRowAt( int paneY
)
2430 for ( ; i
!= mRows
.Count(); ++i
)
2432 int rowHeight
= mRows
[i
]->mRowHeight
;
2434 int third
= rowHeight
/3;
2436 if ( paneY
>= curY
&& paneY
< curY
+ third
)
2439 if ( paneY
>= curY
+ third
&& paneY
< curY
+ rowHeight
- third
)
2448 int cbDockPane::GetRowAt( int upperY
, int lowerY
)
2452 int range = lowerY - upperY;
2453 int oneThird = range / 3;
2455 wxNode* pRow = mRows.First();
2459 if ( lowerY <= 0 ) return -1;
2463 int rowHeight = GetRowHeight( (wxList*)pRow->Data() );
2465 if ( upperY >= curY &&
2466 lowerY < curY ) return row;
2468 if ( upperY <= curY &&
2470 curY - upperY >= oneThird ) return row-1;
2472 if ( ( upperY < curY + rowHeight &&
2473 lowerY >= curY + rowHeight &&
2474 curY + rowHeight - lowerY >= oneThird )
2478 if ( lowerY <= curY + rowHeight ) return row;
2482 pRow = pRow->Next();
2486 int mid
= upperY
+ (lowerY
- upperY
)/2;
2494 for ( ; i
!= mRows
.Count(); ++i
)
2496 int rowHeight
= mRows
[i
]->mRowHeight
;
2498 if ( mid
>= curY
&& mid
< curY
+ rowHeight
) return i
;
2506 int cbDockPane::GetRowY( cbRowInfo
* pRow
)
2511 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2513 if ( mRows
[i
] == pRow
)
2516 curY
+= mRows
[i
]->mRowHeight
;
2522 bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo
* pRow
)
2524 while ( pRow
->mpPrev
)
2526 pRow
= pRow
->mpPrev
;
2528 if ( pRow
->mHasOnlyFixedBars
)
2536 bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo
* pRow
)
2538 while( pRow
->mpNext
)
2540 pRow
= pRow
->mpNext
;
2542 if ( pRow
->mHasOnlyFixedBars
)
2550 bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo
* pBar
)
2552 while( pBar
->mpPrev
)
2554 pBar
= pBar
->mpPrev
;
2556 if ( pBar
->IsFixed() )
2564 bool cbDockPane::HasNotFixedBarsRight( cbBarInfo
* pBar
)
2566 while( pBar
->mpNext
)
2568 pBar
= pBar
->mpNext
;
2570 if ( pBar
->IsFixed() )
2578 void cbDockPane::CalcLengthRatios( cbRowInfo
* pInRow
)
2584 // calc current-maximal-total-length of all maximized bars
2586 for ( i
= 0; i
!= pInRow
->mBars
.GetCount(); ++i
)
2588 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2590 if ( !bar
.IsFixed() )
2591 totalWidth
+= bar
.mBounds
.width
;
2594 // set up percentages of occupied space for each maximized bar
2596 for ( i
= 0; i
!= pInRow
->mBars
.Count(); ++i
)
2598 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2600 if ( !bar
.IsFixed() )
2601 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalWidth
);
2605 void cbDockPane::RecalcRowLayout( cbRowInfo
* pRow
)
2607 cbLayoutRowEvent
evt( pRow
, this );
2609 mpLayout
->FirePluginEvent( evt
);
2612 void cbDockPane::ExpandBar( cbBarInfo
* pBar
)
2614 mpLayout
->GetUpdatesManager().OnStartChanges();
2616 if ( !pBar
->mpRow
->mpExpandedBar
)
2618 // save ratios only when there arent any bars expanded yet
2620 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2623 ratios
.Alloc( pBar
->mpRow
->mNotFixedBarsCnt
);
2625 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2629 if ( !pCur
->IsFixed() )
2632 ratios
[ ratios
.GetCount() - 1 ] = pCur
->mLenRatio
;
2635 pCur
= pCur
->mpNext
;
2639 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2643 pCur
->mLenRatio
= 0.0; // minimize the rest
2645 pCur
= pCur
->mpNext
;
2648 pBar
->mLenRatio
= 1.0; // 100%
2649 pBar
->mBounds
.width
= 0;
2651 pBar
->mpRow
->mpExpandedBar
= pBar
;
2653 mpLayout
->RecalcLayout( FALSE
);
2655 mpLayout
->GetUpdatesManager().OnFinishChanges();
2656 mpLayout
->GetUpdatesManager().UpdateNow();
2659 void cbDockPane::ContractBar( cbBarInfo
* pBar
)
2661 mpLayout
->GetUpdatesManager().OnStartChanges();
2663 // FIXME: What's the purpose of this???
2664 // double ratio = 1.0/ double( pBar->mpRow->mNotFixedBarsCnt );
2666 // restore ratios which were present before expansion
2668 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2670 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2676 if ( !pCur
->IsFixed() )
2678 pCur
->mLenRatio
= ratios
[i
];
2682 pCur
= pCur
->mpNext
;
2688 pBar
->mpRow
->mpExpandedBar
= NULL
;
2690 mpLayout
->RecalcLayout( FALSE
);
2692 mpLayout
->GetUpdatesManager().OnFinishChanges();
2693 mpLayout
->GetUpdatesManager().UpdateNow();
2696 void cbDockPane::InitLinksForRow( cbRowInfo
* pRow
)
2699 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2701 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2706 bar
.mpPrev
= pRow
->mBars
[i
-1];
2708 if ( i
== pRow
->mBars
.Count() - 1 )
2711 bar
.mpNext
= pRow
->mBars
[i
+1];
2715 void cbDockPane::InitLinksForRows()
2718 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2720 cbRowInfo
& row
= *mRows
[i
];
2725 row
.mpPrev
= mRows
[i
-1];
2727 if ( i
== mRows
.Count() - 1 )
2730 row
.mpNext
= mRows
[i
+1];
2734 void cbDockPane::DoInsertBar( cbBarInfo
* pBar
, int rowNo
)
2736 cbRowInfo
* pRow
= NULL
;
2738 if ( rowNo
== -1 || rowNo
>= (int)mRows
.Count() )
2740 pRow
= new cbRowInfo();
2742 if ( rowNo
== -1 && mRows
.Count() )
2744 mRows
.Insert( pRow
, 0 );
2752 pRow
= mRows
[rowNo
];
2754 if ( mProps
.mNonDestructFirctionOn
== TRUE
)
2756 // store original shape of the row (before the bar is inserted)
2760 GetRowShapeData( mpStoredRow
, &mRowShapeData
);
2764 if ( pRow
->mBars
.Count() )
2766 pRow
->mpExpandedBar
= NULL
;
2768 cbInsertBarEvent
insEvt( pBar
, pRow
, this );
2770 mpLayout
->FirePluginEvent( insEvt
);
2772 mpLayout
->GetUpdatesManager().OnRowWillChange( pRow
, this );
2775 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
, const wxRect
& atRect
)
2777 wxRect rect
= atRect
;
2778 FrameToPane( &rect
);
2780 pBarInfo
->mBounds
.x
= rect
.x
;
2781 pBarInfo
->mBounds
.width
= rect
.width
;
2782 pBarInfo
->mBounds
.height
= rect
.height
;
2784 int row
= GetRowAt( rect
.y
, rect
.y
+ rect
.height
);
2786 DoInsertBar( pBarInfo
, row
);
2789 void cbDockPane::InsertBar( cbBarInfo
* pBar
, cbRowInfo
* pIntoRow
)
2791 cbInsertBarEvent
insEvt( pBar
, pIntoRow
, this );
2793 mpLayout
->FirePluginEvent( insEvt
);
2795 mpLayout
->GetUpdatesManager().OnRowWillChange( pIntoRow
, this );
2798 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
)
2800 // set transient properties
2802 pBarInfo
->mpRow
= NULL
;
2803 pBarInfo
->mHasLeftHandle
= FALSE
;
2804 pBarInfo
->mHasRightHandle
= FALSE
;
2805 pBarInfo
->mLenRatio
= 0.0;
2807 // set preferred bar dimensions, according to the state in which
2808 // the bar is being inserted
2810 pBarInfo
->mBounds
.width
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].x
;
2811 pBarInfo
->mBounds
.height
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].y
;
2813 DoInsertBar( pBarInfo
, pBarInfo
->mRowNo
);
2816 void cbDockPane::RemoveRow( cbRowInfo
* pRow
)
2819 // first, hide all bar-windows in the removed row
2820 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2822 if ( pRow
->mBars
[i
]->mpBarWnd
)
2823 pRow
->mBars
[i
]->mpBarWnd
->Show( FALSE
);
2826 mRows
.Remove( pRow
);
2828 pRow
->mUMgrData
.SetDirty(TRUE
);
2831 void cbDockPane::InsertRow( cbRowInfo
* pRow
, cbRowInfo
* pBeforeRow
)
2837 mRows
.Insert( pRow
, mRows
.Index( pBeforeRow
) );
2841 pRow
->mUMgrData
.SetDirty(TRUE
);
2844 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2845 pRow
->mBars
[i
]->mUMgrData
.SetDirty( TRUE
);
2847 SyncRowFlags( pRow
);
2850 void cbDockPane::SetPaneWidth(int width
)
2852 if ( IsHorizontal() )
2853 mPaneWidth
= width
- mLeftMargin
- mRightMargin
;
2855 mPaneWidth
= width
- mTopMargin
- mBottomMargin
;
2859 void cbDockPane::SetBoundsInParent( const wxRect
& rect
)
2861 mBoundsInParent
= rect
;
2863 // set pane dimensions in local coordinates
2865 if ( IsHorizontal() )
2867 mPaneWidth
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2868 mPaneHeight
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2872 mPaneWidth
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2873 mPaneHeight
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2876 // convert bounding rectangles of all pane items into parent frame's coordinates
2878 wxBarIterator
i( mRows
);
2880 wxRect noMarginsRect
= mBoundsInParent
;
2882 noMarginsRect
.x
+= mLeftMargin
;
2883 noMarginsRect
.y
+= mTopMargin
;
2884 noMarginsRect
.width
-= ( mLeftMargin
+ mRightMargin
);
2885 noMarginsRect
.height
-= ( mTopMargin
+ mBottomMargin
);
2887 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2889 if ( mBoundsInParent
.width
< 0 ||
2890 mBoundsInParent
.height
< 0 )
2892 hide_rect( mBoundsInParent
);
2894 if ( noMarginsRect
.width
< 0 ||
2895 noMarginsRect
.height
< 0 )
2897 hide_rect( noMarginsRect
);
2899 // calculate mBoundsInParent for each item in the pane
2903 cbBarInfo
& bar
= i
.BarInfo();
2905 cbRowInfo
* pRowInfo
= bar
.mpRow
;
2907 // set up row info, if this is first bar in the row
2909 if ( pRowInfo
&& bar
.mpPrev
== NULL
)
2911 pRowInfo
->mBoundsInParent
.y
= pRowInfo
->mRowY
;
2912 pRowInfo
->mBoundsInParent
.x
= 0;
2913 pRowInfo
->mBoundsInParent
.width
= mPaneWidth
;
2914 pRowInfo
->mBoundsInParent
.height
= pRowInfo
->mRowHeight
;
2916 PaneToFrame( &pRowInfo
->mBoundsInParent
);
2918 clip_rect_against_rect( pRowInfo
->mBoundsInParent
, noMarginsRect
);
2921 wxRect bounds
= bar
.mBounds
;
2923 // exclude dimensions of handles, when calculating
2924 // bar's bounds in parent (i.e. "visual bounds")
2926 if ( bar
.mHasLeftHandle
)
2928 bounds
.x
+= mProps
.mResizeHandleSize
;
2929 bounds
.width
-= mProps
.mResizeHandleSize
;
2932 if ( bar
.mHasRightHandle
)
2934 bounds
.width
-= mProps
.mResizeHandleSize
;
2936 PaneToFrame( &bounds
);
2938 clip_rect_against_rect( bounds
, noMarginsRect
);
2940 bar
.mBoundsInParent
= bounds
;
2944 bool cbDockPane::BarPresent( cbBarInfo
* pBar
)
2946 wxBarIterator
iter( mRows
);
2948 while( iter
.Next() )
2950 if ( &iter
.BarInfo() == pBar
) return TRUE
;
2955 cbRowInfo
* cbDockPane::GetRow( int row
)
2957 if ( row
>= (int)mRows
.Count() ) return NULL
;
2959 return mRows
[ row
];
2962 int cbDockPane::GetRowIndex( cbRowInfo
* pRow
)
2965 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2967 if ( mRows
[i
] == pRow
)
2971 wxFAIL_MSG("Row must be present to call cbDockPane::GetRowIndex()");
2976 int cbDockPane::GetPaneHeight()
2978 // first, recalculate row heights and the Y-positions
2980 cbLayoutRowsEvent
evt( this );
2981 mpLayout
->FirePluginEvent( evt
);
2985 if ( IsHorizontal() )
2987 height
+= mTopMargin
+ mBottomMargin
;
2989 height
+= mLeftMargin
+ mRightMargin
;
2991 int count
= mRows
.Count();
2995 height
+= mRows
[count
-1]->mRowY
+ mRows
[count
-1]->mRowHeight
;
3000 int cbDockPane::GetAlignment()
3005 bool cbDockPane::MatchesMask( int paneMask
)
3009 // FIXME:: use array instead of switch()
3013 case FL_ALIGN_TOP
: thisMask
= FL_ALIGN_TOP_PANE
; break;
3014 case FL_ALIGN_BOTTOM
: thisMask
= FL_ALIGN_BOTTOM_PANE
;break;
3015 case FL_ALIGN_LEFT
: thisMask
= FL_ALIGN_LEFT_PANE
; break;
3016 case FL_ALIGN_RIGHT
: thisMask
= FL_ALIGN_RIGHT_PANE
; break;
3019 wxFAIL_MSG("Bad FL alignment type detected in cbDockPane::MatchesMask()");
3022 return ( thisMask
& paneMask
) != 0;
3025 void cbDockPane::RecalcLayout()
3027 // first, reposition rows and items vertically
3029 cbLayoutRowsEvent
evt( this );
3030 mpLayout
->FirePluginEvent( evt
);
3032 // then horizontally in each row
3035 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3036 RecalcRowLayout( mRows
[i
] );
3039 int cbDockPane::GetDockingState()
3041 if ( mAlignment
== FL_ALIGN_TOP
||
3042 mAlignment
== FL_ALIGN_BOTTOM
)
3044 return wxCBAR_DOCKED_HORIZONTALLY
;
3047 return wxCBAR_DOCKED_VERTICALLY
;
3050 inline bool cbDockPane::HasPoint( const wxPoint
& pos
, int x
, int y
,
3051 int width
, int height
)
3053 return ( pos
.x
>= x
&&
3055 pos
.x
< x
+ width
&&
3056 pos
.y
< y
+ height
);
3059 int cbDockPane::HitTestPaneItems( const wxPoint
& pos
,
3068 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3070 cbRowInfo
& row
= *mRows
[i
];
3074 // hit-test handles of the row, if present
3076 if ( row
.mHasUpperHandle
)
3078 if ( HasPoint( pos
, 0, row
.mRowY
,
3079 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3081 return CB_UPPER_ROW_HANDLE_HITTED
;
3084 if ( row
.mHasLowerHandle
)
3086 if ( HasPoint( pos
, 0, row
.mRowY
+ row
.mRowHeight
- mProps
.mResizeHandleSize
,
3087 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3089 return CB_LOWER_ROW_HANDLE_HITTED
;
3092 // hit-test bar handles and bar content
3095 for ( k
= 0; k
!= row
.mBars
.Count(); ++k
)
3097 cbBarInfo
& bar
= *row
.mBars
[k
];
3098 wxRect
& bounds
= bar
.mBounds
;
3102 if ( bar
.mHasLeftHandle
)
3104 if ( HasPoint( pos
, bounds
.x
, bounds
.y
,
3105 mProps
.mResizeHandleSize
, bounds
.height
) )
3107 return CB_LEFT_BAR_HANDLE_HITTED
;
3110 if ( bar
.mHasRightHandle
)
3112 if ( HasPoint( pos
, bounds
.x
+ bounds
.width
- mProps
.mResizeHandleSize
, bounds
.y
,
3113 mProps
.mResizeHandleSize
, bounds
.height
) )
3115 return CB_RIGHT_BAR_HANDLE_HITTED
;
3118 if ( HasPoint( pos
, bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
) )
3119 return CB_BAR_CONTENT_HITTED
;
3121 } // hit-test next bar
3125 return CB_NO_ITEMS_HITTED
;
3128 void cbDockPane::GetBarResizeRange( cbBarInfo
* pBar
, int* from
, int *till
,
3129 bool forLeftHandle
)
3131 cbBarInfo
* pGivenBar
= pBar
;
3135 // calc unavailable space from the left
3137 while( pBar
->mpPrev
)
3139 pBar
= pBar
->mpPrev
;
3141 if ( !pBar
->IsFixed() ) notFree
+= mProps
.mMinCBarDim
.x
;
3142 else notFree
+= pBar
->mBounds
.width
;
3151 // calc unavailable space from the right
3153 while( pBar
->mpNext
)
3155 pBar
= pBar
->mpNext
;
3157 if ( pBar
->mBounds
.x
>= mPaneWidth
) break;
3159 // treat not-fixed bars as minimized
3161 if ( !pBar
->IsFixed() )
3163 notFree
+= mProps
.mMinCBarDim
.x
;
3166 if ( pBar
->mBounds
.x
+ pBar
->mBounds
.width
>= mPaneWidth
)
3168 notFree
+= mPaneWidth
- pBar
->mBounds
.x
;
3172 notFree
+= pBar
->mBounds
.width
;
3177 *till
= mPaneWidth
- notFree
;
3179 // do not let resizing totally deform the bar itself
3181 if ( forLeftHandle
)
3183 (*till
) -= mProps
.mMinCBarDim
.x
;
3186 (*from
) += mProps
.mMinCBarDim
.x
;
3189 int cbDockPane::GetMinimalRowHeight( cbRowInfo
* pRow
)
3191 int height
= mProps
.mMinCBarDim
.y
;
3194 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3196 if ( pRow
->mBars
[i
]->IsFixed() )
3197 height
= wxMax( height
, pRow
->mBars
[i
]->mBounds
.height
);
3200 if ( pRow
->mHasUpperHandle
)
3201 height
+= mProps
.mResizeHandleSize
;
3203 if ( pRow
->mHasLowerHandle
)
3204 height
+= mProps
.mResizeHandleSize
;
3209 void cbDockPane::SetRowHeight( cbRowInfo
* pRow
, int newHeight
)
3211 if ( pRow
->mHasUpperHandle
)
3213 newHeight
-= mProps
.mResizeHandleSize
;
3215 if ( pRow
->mHasLowerHandle
)
3217 newHeight
-= mProps
.mResizeHandleSize
;
3220 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3222 if ( !pRow
->mBars
[i
]->IsFixed() )
3223 pRow
->mBars
[i
]->mBounds
.height
= newHeight
;
3227 void cbDockPane::GetRowResizeRange( cbRowInfo
* pRow
, int* from
, int* till
,
3228 bool forUpperHandle
)
3230 cbRowInfo
* pGivenRow
= pRow
;
3232 // calc unavailable space from above
3236 while( pRow
->mpPrev
)
3238 pRow
= pRow
->mpPrev
;
3240 notFree
+= GetMinimalRowHeight( pRow
);
3246 // allow accupy the client window space by resizing pane rows
3247 if ( mAlignment
== FL_ALIGN_BOTTOM
)
3249 *from
-= mpLayout
->GetClientHeight();
3251 if ( mAlignment
== FL_ALIGN_RIGHT
)
3253 *from
-= mpLayout
->GetClientWidth();
3255 // calc unavailable space from below
3261 while( pRow
->mpNext
)
3263 pRow
= pRow
->mpNext
;
3265 notFree
+= GetMinimalRowHeight( pRow
);
3269 *till
= mPaneHeight
- notFree
;
3271 // allow adjustinig pane space vs. client window space by resizing pane row heights
3273 if ( mAlignment
== FL_ALIGN_TOP
)
3275 *till
+= mpLayout
->GetClientHeight();
3277 if ( mAlignment
== FL_ALIGN_LEFT
)
3279 *till
+= mpLayout
->GetClientWidth();
3281 // do not let the resizing of the row totally squeeze the row itself
3283 cbRowInfo
& row
= *pGivenRow
;
3285 if ( forUpperHandle
)
3287 *till
= row
.mRowY
+ row
.mRowHeight
- GetMinimalRowHeight( pGivenRow
);
3289 if ( row
.mHasUpperHandle
)
3291 *till
-= mProps
.mResizeHandleSize
;
3295 *from
+= GetMinimalRowHeight( pGivenRow
);
3297 if ( row
.mHasLowerHandle
)
3299 *from
-= mProps
.mResizeHandleSize
;
3303 void cbDockPane::ResizeRow( cbRowInfo
* pRow
, int ofs
,
3304 bool forUpperHandle
)
3306 cbResizeRowEvent
evt( pRow
, ofs
, forUpperHandle
, this );
3308 mpLayout
->FirePluginEvent( evt
);
3311 void cbDockPane::ResizeBar( cbBarInfo
* pBar
, int ofs
,
3312 bool forLeftHandle
)
3314 pBar
->mpRow
->mpExpandedBar
= NULL
;
3316 mpLayout
->GetUpdatesManager().OnStartChanges();
3318 wxRect
& bounds
= pBar
->mBounds
;
3320 if ( forLeftHandle
)
3322 // do not allow bar width become less then minimal
3323 if ( bounds
.x
+ ofs
> bounds
.x
+ bounds
.width
- mProps
.mMinCBarDim
.x
)
3325 bounds
.width
= mProps
.mMinCBarDim
.x
;
3331 bounds
.width
-= ofs
;
3336 // move bar left if necessary
3337 if ( bounds
.width
+ ofs
< mProps
.mMinCBarDim
.x
)
3339 bounds
.x
= bounds
.x
+ bounds
.width
+ ofs
- mProps
.mMinCBarDim
.x
;
3340 bounds
.width
= mProps
.mMinCBarDim
.x
;
3343 // resize right border only
3344 bounds
.width
+= ofs
;
3348 cbRowInfo
* pToRow
= pBar
->mpRow
;
3350 this->RemoveBar( pBar
);
3352 InsertBar( pBar
, pToRow
);
3354 mpLayout
->RecalcLayout(FALSE
);
3356 mpLayout
->GetUpdatesManager().OnFinishChanges();
3357 mpLayout
->GetUpdatesManager().UpdateNow();
3361 /*** row/bar resizing related methods ***/
3363 void cbDockPane::DrawVertHandle( wxDC
& dc
, int x
, int y
, int height
)
3365 int lower
= y
+ height
;
3367 dc
.SetPen( mpLayout
->mLightPen
);
3368 dc
.DrawLine( x
,y
, x
, lower
);
3370 dc
.SetPen( mpLayout
->mGrayPen
);
3372 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3375 dc
.DrawLine( x
,y
, x
, lower
);
3378 dc
.SetPen( mpLayout
->mDarkPen
);
3380 dc
.DrawLine( x
,y
, x
, lower
);
3382 dc
.SetPen( mpLayout
->mBlackPen
);
3384 dc
.DrawLine( x
,y
, x
, lower
);
3387 void cbDockPane::DrawHorizHandle( wxDC
& dc
, int x
, int y
, int width
)
3389 int right
= x
+ width
;
3391 dc
.SetPen( mpLayout
->mLightPen
);
3392 dc
.DrawLine( x
,y
, right
, y
);
3394 dc
.SetPen( mpLayout
->mGrayPen
);
3397 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3400 dc
.DrawLine( x
,y
, right
, y
);
3403 dc
.SetPen( mpLayout
->mDarkPen
);
3404 dc
.DrawLine( x
,y
, right
, ++y
);
3406 dc
.SetPen( mpLayout
->mBlackPen
);
3407 dc
.DrawLine( x
,y
, right
, ++y
);
3410 cbBarInfo
* cbDockPane::GetBarInfoByWindow( wxWindow
* pBarWnd
)
3412 wxBarIterator
i( mRows
);
3416 if ( i
.BarInfo().mpBarWnd
== pBarWnd
)
3418 return &i
.BarInfo();
3423 void cbDockPane::GetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3425 pLst
->DeleteContents( TRUE
);
3429 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3431 cbBarInfo
& bar
= *pRow
->mBars
[i
];
3433 cbBarShapeData
* pData
= new cbBarShapeData();
3435 pLst
->Append( (wxObject
*)pData
);
3437 pData
->mBounds
= bar
.mBounds
;
3438 pData
->mLenRatio
= bar
.mLenRatio
;
3442 void cbDockPane::SetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3444 if ( pLst
->First() == NULL
)
3447 wxNode
* pData
= pLst
->First();
3450 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3452 wxASSERT( pData
); // DBG::
3454 cbBarInfo
& bar
= *pRow
->mBars
[i
];;
3456 cbBarShapeData
& data
= *((cbBarShapeData
*)pData
->Data());
3458 bar
.mBounds
= data
.mBounds
;
3459 bar
.mLenRatio
= data
.mLenRatio
;
3461 pData
= pData
->Next();
3465 /***** Implementation for class cbUpdatesManagerBase *****/
3467 IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase
, wxObject
)
3469 /***** Implementation for class cbPluginBase *****/
3471 IMPLEMENT_ABSTRACT_CLASS( cbPluginBase
, wxEvtHandler
)
3473 cbPluginBase::~cbPluginBase()
3478 bool cbPluginBase::ProcessEvent(wxEvent
& event
)
3480 if ( mPaneMask
== wxALL_PANES
)
3482 return wxEvtHandler::ProcessEvent( event
);
3484 // extract mask info. from received event
3486 cbPluginEvent
& evt
= *( (cbPluginEvent
*)&event
);
3488 if ( evt
.mpPane
== 0 &&
3489 mPaneMask
== wxALL_PANES
)
3491 return wxEvtHandler::ProcessEvent( event
);
3495 switch ( evt
.mpPane
->mAlignment
)
3497 case FL_ALIGN_TOP
: mask
= FL_ALIGN_TOP_PANE
; break;
3498 case FL_ALIGN_BOTTOM
: mask
= FL_ALIGN_BOTTOM_PANE
;break;
3499 case FL_ALIGN_LEFT
: mask
= FL_ALIGN_LEFT_PANE
; break;
3500 case FL_ALIGN_RIGHT
: mask
= FL_ALIGN_RIGHT_PANE
; break;
3503 // if event's pane maks matches the plugin's mask
3505 if ( mPaneMask
& mask
)
3507 return wxEvtHandler::ProcessEvent( event
);
3509 // otherwise pass to the next handler if present
3511 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event
) )