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
)
1156 /*** protected members ***/
1158 void wxFrameLayout::HideBarWindows()
1161 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
1162 if ( mAllBars
[i
]->mpBarWnd
&& mAllBars
[i
]->mState
!= wxCBAR_FLOATING
)
1163 mAllBars
[i
]->mpBarWnd
->Show( FALSE
);
1165 // then floated frames
1167 ShowFloatedWindows( FALSE
);
1169 if ( mpFrameClient
)
1171 mpFrameClient
->Show( FALSE
);
1174 void wxFrameLayout::UnhookFromFrame()
1176 // NOTE:: the SetEvtHandlerEnabled() method is not used
1177 // here, since it is assumed that unhooking layout
1178 // from window may result destroying of the layout itself
1180 // BUG BUG BUG (wx):: this would not be a problem if
1181 // wxEvtHandler's destructor checked if
1182 // this handler is currently the top-most
1183 // handler of some window, and additionally
1184 // to the reconnecting itself from the chain.
1185 // It would also re-setup current event handler
1186 // of the window using wxWindow::SetEventHandler()
1190 if ( mpFrame
->GetEventHandler() == this )
1192 mpFrame
->PopEventHandler();
1198 if ( this == mpFrame
->GetEventHandler() )
1200 mpFrame
->SetEventHandler( this->GetNextHandler() );
1204 wxEvtHandler
* pCur
= mpFrame
->GetEventHandler();
1211 pCur
= pCur
->GetNextHandler();
1214 // do not try to unhook ourselves if we're not hooked yet
1219 if ( GetPreviousHandler() )
1220 GetPreviousHandler()->SetNextHandler( GetNextHandler() );
1223 mpFrame
->PopEventHandler();
1227 if ( GetNextHandler() )
1228 GetNextHandler()->SetPreviousHandler( GetPreviousHandler() );
1230 SetNextHandler( NULL
);
1231 SetPreviousHandler( NULL
);
1235 void wxFrameLayout::HookUpToFrame()
1237 // unhook us first, we're already hooked up
1241 // put ourselves on top
1243 mpFrame
->PushEventHandler( this );
1246 cbDockPane
* wxFrameLayout::GetBarPane( cbBarInfo
* pBar
)
1249 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1250 if ( mPanes
[i
]->BarPresent( pBar
) )
1256 void wxFrameLayout::CreateCursors()
1259 // FIXME:: The below code somehow doesn't work - cursors remain unchanged
1262 set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
1264 mpHorizCursor = new wxCursor( bits, 32, 16 );
1266 set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
1268 mpVertCursor = new wxCursor( bits, 32, 16 );
1271 // FOR NOW:: use standard ones
1273 mpHorizCursor
= new wxCursor(wxCURSOR_SIZEWE
);
1274 mpVertCursor
= new wxCursor(wxCURSOR_SIZENS
);
1275 mpNormalCursor
= new wxCursor(wxCURSOR_ARROW
);
1276 mpDragCursor
= new wxCursor(wxCURSOR_CROSS
);
1277 mpNECursor
= new wxCursor(wxCURSOR_NO_ENTRY
);
1279 mFloatingPosStep
.x
= 25;
1280 mFloatingPosStep
.y
= 25;
1282 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
1283 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
1286 bool wxFrameLayout::HitTestPane( cbDockPane
* pPane
, int x
, int y
)
1288 return rect_contains_point( pPane
->GetRealRect(), x
, y
);
1291 cbDockPane
* wxFrameLayout::HitTestPanes( const wxRect
& rect
,
1292 cbDockPane
* pCurPane
)
1294 // first, give the privilege to the current pane
1296 if ( pCurPane
&& rect_hits_rect( pCurPane
->GetRealRect(), rect
) )
1301 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1303 if ( pCurPane
!= mPanes
[i
] &&
1304 rect_hits_rect( mPanes
[i
]->GetRealRect(), rect
) )
1312 void wxFrameLayout::ForwardMouseEvent( wxMouseEvent
& event
,
1313 cbDockPane
* pToPane
,
1316 wxPoint
pos( event
.m_x
, event
.m_y
);
1317 pToPane
->FrameToPane( &pos
.x
, &pos
.y
);
1319 if ( eventType
== cbEVT_PL_LEFT_DOWN
)
1321 cbLeftDownEvent
evt( pos
, pToPane
);
1322 FirePluginEvent( evt
);
1324 else if ( eventType
== cbEVT_PL_LEFT_DCLICK
)
1326 cbLeftDClickEvent
evt( pos
, pToPane
);
1327 FirePluginEvent( evt
);
1329 else if ( eventType
== cbEVT_PL_LEFT_UP
)
1331 cbLeftUpEvent
evt( pos
, pToPane
);
1332 FirePluginEvent( evt
);
1334 else if ( eventType
== cbEVT_PL_RIGHT_DOWN
)
1336 cbRightDownEvent
evt( pos
, pToPane
);
1337 FirePluginEvent( evt
);
1339 else if ( eventType
== cbEVT_PL_RIGHT_UP
)
1341 cbRightUpEvent
evt( pos
, pToPane
);
1342 FirePluginEvent( evt
);
1344 else if ( eventType
== cbEVT_PL_MOTION
)
1346 cbMotionEvent
evt( pos
, pToPane
);
1347 FirePluginEvent( evt
);
1351 int avoidCompilerWarning
= 0;
1352 wxASSERT(avoidCompilerWarning
); // DBG::
1354 } // wxFrameLayout::ForwardMouseEvent()
1357 void wxFrameLayout::RouteMouseEvent( wxMouseEvent
& event
, int pluginEvtType
)
1359 if ( mpPaneInFocus
)
1361 ForwardMouseEvent( event
, mpPaneInFocus
, pluginEvtType
);
1365 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1367 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1369 ForwardMouseEvent( event
, mPanes
[i
], pluginEvtType
);
1376 /*** event handlers ***/
1378 void wxFrameLayout::OnRButtonDown( wxMouseEvent
& event
)
1380 RouteMouseEvent( event
, cbEVT_PL_RIGHT_DOWN
);
1383 void wxFrameLayout::OnRButtonUp( wxMouseEvent
& event
)
1385 RouteMouseEvent( event
, cbEVT_PL_RIGHT_UP
);
1388 void wxFrameLayout::OnLButtonDown( wxMouseEvent
& event
)
1390 RouteMouseEvent( event
, cbEVT_PL_LEFT_DOWN
);
1393 void wxFrameLayout::OnLDblClick( wxMouseEvent
& event
)
1395 RouteMouseEvent( event
, cbEVT_PL_LEFT_DCLICK
);
1398 void wxFrameLayout::OnLButtonUp( wxMouseEvent
& event
)
1400 RouteMouseEvent( event
, cbEVT_PL_LEFT_UP
);
1403 void wxFrameLayout::OnMouseMove( wxMouseEvent
& event
)
1405 if ( mpPaneInFocus
)
1407 ForwardMouseEvent( event
, mpPaneInFocus
, cbEVT_PL_MOTION
);
1411 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1413 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1415 if ( mpLRUPane
&& mpLRUPane
!= mPanes
[i
] )
1417 // simulate "mouse-leave" event
1418 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1421 ForwardMouseEvent( event
, mPanes
[i
], cbEVT_PL_MOTION
);
1423 mpLRUPane
= mPanes
[i
];
1432 // simulate "mouse-leave" event
1433 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1438 void wxFrameLayout::OnPaint( wxPaintEvent
& event
)
1440 if ( mRecalcPending
)
1441 RecalcLayout( TRUE
);
1443 wxPaintDC
dc(mpFrame
);
1446 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1448 wxRect
& rect
= mPanes
[i
]->mBoundsInParent
;
1450 dc
.SetClippingRegion( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1452 mPanes
[i
]->PaintPane(dc
);
1454 dc
.DestroyClippingRegion();
1460 void wxFrameLayout::OnEraseBackground( wxEraseEvent
& event
)
1465 void wxFrameLayout::OnIdle( wxIdleEvent
& event
)
1467 wxWindow
* focus
= wxWindow::FindFocus();
1469 if ( !focus
&& mCheckFocusWhenIdle
)
1471 wxMessageBox( "Hi, no more focus in this app!" );
1473 mCheckFocusWhenIdle
= FALSE
;
1474 //ShowFloatedWindows( FALSE );
1477 mCheckFocusWhenIdle
= FALSE
;
1483 void wxFrameLayout::OnKillFocus( wxFocusEvent
& event
)
1485 //wxMessageBox( "wxFrameLayoutGot Kill Focus!" );
1486 //ShowFloatedWindows( FALSE );
1489 void wxFrameLayout::OnSetFocus( wxFocusEvent
& event
)
1491 //ShowFloatedWindows( TRUE );
1494 void wxFrameLayout::OnActivate( wxActivateEvent
& event
)
1497 if ( event
.GetActive() == FALSE
)
1499 wxWindow
* focus
= wxWindow::FindFocus();
1501 if ( !focus
|| focus
== &GetParentFrame() )
1503 mCheckFocusWhenIdle
= TRUE
;
1507 wxMessageBox("Deactivated!" );
1514 void wxFrameLayout::GetPaneProperties( cbCommonPaneProperties
& props
, int alignment
)
1516 props
= mPanes
[alignment
]->mProps
;
1519 void wxFrameLayout::SetPaneProperties( const cbCommonPaneProperties
& props
, int paneMask
)
1522 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1524 if ( mPanes
[i
]->MatchesMask( paneMask
) )
1525 mPanes
[i
]->mProps
= props
;
1529 void wxFrameLayout::SetMargins( int top
, int bottom
, int left
, int right
,
1533 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1535 cbDockPane
& pane
= *mPanes
[i
];
1537 if ( pane
.MatchesMask( paneMask
) )
1539 pane
.mTopMargin
= top
;
1540 pane
.mBottomMargin
= bottom
;
1541 pane
.mLeftMargin
= left
;
1542 pane
.mRightMargin
= right
;
1547 void wxFrameLayout::SetPaneBackground( const wxColour
& colour
)
1549 mBorderPen
.SetColour( colour
);
1552 void wxFrameLayout::RefreshNow( bool recalcLayout
)
1554 if ( recalcLayout
) RecalcLayout( TRUE
);
1556 if ( mpFrame
) mpFrame
->Refresh();
1559 /*** plugin-related methods ***/
1561 void wxFrameLayout::FirePluginEvent( cbPluginEvent
& event
)
1563 // check state of input capture, before processing the event
1565 if ( mpCaputesInput
)
1567 bool isInputEvt
= TRUE
;
1568 #if wxCHECK_VERSION(2,3,0)
1569 if ( event
.m_eventType
!= cbEVT_PL_LEFT_DOWN
&&
1570 event
.m_eventType
!= cbEVT_PL_LEFT_UP
&&
1571 event
.m_eventType
!= cbEVT_PL_RIGHT_DOWN
&&
1572 event
.m_eventType
!= cbEVT_PL_RIGHT_UP
&&
1573 event
.m_eventType
!= cbEVT_PL_MOTION
)
1576 switch ( event
.m_eventType
)
1578 case cbEVT_PL_LEFT_DOWN
: break;
1579 case cbEVT_PL_LEFT_UP
: break;
1580 case cbEVT_PL_RIGHT_DOWN
: break;
1581 case cbEVT_PL_RIGHT_UP
: break;
1582 case cbEVT_PL_MOTION
: break;
1584 default : isInputEvt
= FALSE
; break;
1586 #endif // #if wxCHECK_VERSION(2,3,0)
1590 mpCaputesInput
->ProcessEvent( event
);
1595 GetTopPlugin().ProcessEvent( event
);
1598 void wxFrameLayout::CaptureEventsForPlugin ( cbPluginBase
* pPlugin
)
1600 // cannot capture events for more than one plugin at a time
1601 wxASSERT( mpCaputesInput
== NULL
);
1603 mpCaputesInput
= pPlugin
;
1607 void wxFrameLayout::ReleaseEventsFromPlugin( cbPluginBase
* pPlugin
)
1609 // events should be captured first
1610 wxASSERT( mpCaputesInput
!= NULL
);
1612 mpCaputesInput
= NULL
;
1615 void wxFrameLayout::CaptureEventsForPane( cbDockPane
* toPane
)
1617 // cannot capture events twice (without releasing)
1618 wxASSERT( mpPaneInFocus
== NULL
);
1620 mpFrame
->CaptureMouse();
1622 mpPaneInFocus
= toPane
;
1625 void wxFrameLayout::ReleaseEventsFromPane( cbDockPane
* fromPane
)
1627 // cannot release events without capturing them
1628 wxASSERT( mpPaneInFocus
!= NULL
);
1630 mpFrame
->ReleaseMouse();
1632 mpPaneInFocus
= NULL
;
1635 cbPluginBase
& wxFrameLayout::GetTopPlugin()
1639 PushDefaultPlugins(); // automatic configuration
1641 return *mpTopPlugin
;
1644 void wxFrameLayout::SetTopPlugin( cbPluginBase
* pPlugin
)
1646 mpTopPlugin
= pPlugin
;
1649 bool wxFrameLayout::HasTopPlugin()
1651 return ( mpTopPlugin
!= NULL
);
1654 void wxFrameLayout::PushPlugin( cbPluginBase
* pPlugin
)
1658 mpTopPlugin
= pPlugin
;
1661 pPlugin
->SetNextHandler( mpTopPlugin
);
1663 mpTopPlugin
->SetPreviousHandler( pPlugin
);
1665 mpTopPlugin
= pPlugin
;
1668 mpTopPlugin
->OnInitPlugin(); // notification
1671 void wxFrameLayout::PopPlugin()
1673 wxASSERT( mpTopPlugin
); // DBG:: at least one plugin should be present
1675 cbPluginBase
* pPopped
= mpTopPlugin
;
1677 mpTopPlugin
= (cbPluginBase
*)mpTopPlugin
->GetNextHandler();
1682 void wxFrameLayout::PopAllPlugins()
1684 while( mpTopPlugin
) PopPlugin();
1687 void wxFrameLayout::PushDefaultPlugins()
1689 // FIXME:: to much of the stuff for the default...
1691 AddPlugin( CLASSINFO( cbRowLayoutPlugin
) );
1692 AddPlugin( CLASSINFO( cbBarDragPlugin
) );
1693 AddPlugin( CLASSINFO( cbPaneDrawPlugin
) );
1696 void wxFrameLayout::AddPlugin( wxClassInfo
* pPlInfo
, int paneMask
)
1698 if ( FindPlugin ( pPlInfo
) ) return; // same type of plugin cannot be added twice
1700 cbPluginBase
* pObj
= (cbPluginBase
*)pPlInfo
->CreateObject();
1702 wxASSERT(pObj
); // DBG:: plugin's class should be dynamic
1704 pObj
->mPaneMask
= paneMask
;
1705 pObj
->mpLayout
= this;
1710 void wxFrameLayout::AddPluginBefore( wxClassInfo
* pNextPlInfo
, wxClassInfo
* pPlInfo
,
1713 wxASSERT( pNextPlInfo
!= pPlInfo
); // DBG:: no sense
1715 cbPluginBase
* pNextPl
= FindPlugin( pNextPlInfo
);
1719 AddPlugin( pPlInfo
, paneMask
);
1724 // remove existing one if present
1726 cbPluginBase
* pExistingPl
= FindPlugin( pPlInfo
);
1728 if ( pExistingPl
) RemovePlugin( pPlInfo
);
1730 // create an instance
1732 cbPluginBase
* pNewPl
= (cbPluginBase
*)pPlInfo
->CreateObject();
1734 wxASSERT(pNewPl
); // DBG:: plugin's class should be dynamic
1736 // insert it to the chain
1738 if ( pNextPl
->GetPreviousHandler() )
1740 pNextPl
->GetPreviousHandler()->SetNextHandler( pNewPl
);
1742 mpTopPlugin
= pNewPl
;
1744 pNewPl
->SetNextHandler( pNextPl
);
1746 pNewPl
->SetPreviousHandler( pNextPl
->GetPreviousHandler() );
1748 pNextPl
->SetPreviousHandler( pNewPl
);
1752 pNewPl
->mPaneMask
= paneMask
;
1753 pNewPl
->mpLayout
= this;
1755 pNewPl
->OnInitPlugin();
1758 void wxFrameLayout::RemovePlugin( wxClassInfo
* pPlInfo
)
1760 cbPluginBase
* pPlugin
= FindPlugin( pPlInfo
);
1762 if ( !pPlugin
) return; // it's OK to remove not-existing plugin ;-)
1764 if ( pPlugin
->GetPreviousHandler() == NULL
)
1766 mpTopPlugin
= (cbPluginBase
*)pPlugin
->GetNextHandler();
1771 cbPluginBase
* wxFrameLayout::FindPlugin( wxClassInfo
* pPlInfo
)
1773 cbPluginBase
*pCur
= mpTopPlugin
;
1777 // NOTE:: it might appear useful matching plugin
1778 // classes "polymorphically":
1780 if ( pCur
->GetClassInfo()->IsKindOf( pPlInfo
) )
1784 pCur
= (cbPluginBase
*)pCur
->GetNextHandler();
1790 /***** Implementation for class cbUpdateMgrData *****/
1792 IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData
, wxObject
)
1794 cbUpdateMgrData::cbUpdateMgrData()
1796 : mPrevBounds( -1,-1,0,0 ),
1797 mIsDirty( TRUE
) // inidicate initial change
1800 void cbUpdateMgrData::StoreItemState( const wxRect
& boundsInParent
)
1802 mPrevBounds
= boundsInParent
;
1805 void cbUpdateMgrData::SetDirty( bool isDirty
)
1810 void cbUpdateMgrData::SetCustomData( wxObject
* pCustomData
)
1812 mpCustomData
= pCustomData
;
1815 /***** Implementation for class cbDockPane *****/
1817 void wxBarIterator::Reset()
1819 mpRow
= ( mpRows
->Count() ) ? (*mpRows
)[0] : NULL
;
1823 wxBarIterator::wxBarIterator( RowArrayT
& rows
)
1832 bool wxBarIterator::Next()
1837 mpBar
= mpBar
->mpNext
;
1840 if ( mpRow
->mBars
.GetCount() == 0 )
1845 mpBar
= mpRow
->mBars
[0];
1850 // skip to the next row
1852 mpRow
= mpRow
->mpNext
;
1856 mpBar
= mpRow
->mBars
[0];
1867 cbBarInfo
& wxBarIterator::BarInfo()
1872 cbRowInfo
& wxBarIterator::RowInfo()
1877 /***** Implementation for class cbBarDimHandlerBase *****/
1879 IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase
, wxObject
)
1881 cbBarDimHandlerBase::cbBarDimHandlerBase()
1885 void cbBarDimHandlerBase::AddRef()
1890 void cbBarDimHandlerBase::RemoveRef()
1892 if ( --mRefCount
<= 0 ) delete this;
1895 /***** Implementation for class cbDimInfo *****/
1897 IMPLEMENT_DYNAMIC_CLASS( cbDimInfo
, wxObject
)
1899 cbDimInfo::cbDimInfo()
1908 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1913 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1917 cbDimInfo::cbDimInfo( cbBarDimHandlerBase
* pDimHandler
,
1922 mIsFixed ( isFixed
),
1924 mpHandler( pDimHandler
)
1928 // int vtad = *((int*)mpHandler);
1929 mpHandler
->AddRef();
1933 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1938 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1942 cbDimInfo::cbDimInfo( int dh_x
, int dh_y
,
1950 cbBarDimHandlerBase
* pDimHandler
1952 : mVertGap ( vertGap
),
1953 mHorizGap ( horizGap
),
1954 mIsFixed ( isFixed
),
1955 mpHandler( pDimHandler
)
1959 // int vtad = *((int*)mpHandler);
1960 mpHandler
->AddRef();
1963 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= dh_x
;
1964 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= dh_y
;
1965 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= dv_x
;
1966 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= dv_y
;
1967 mSizes
[wxCBAR_FLOATING
].x
= f_x
;
1968 mSizes
[wxCBAR_FLOATING
].y
= f_y
;
1971 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1972 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1975 cbDimInfo::cbDimInfo( int x
, int y
,
1976 bool isFixed
, int gap
,
1977 cbBarDimHandlerBase
* pDimHandler
)
1980 mIsFixed ( isFixed
),
1981 mpHandler( pDimHandler
)
1985 // int vtad = *((int*)mpHandler);
1986 mpHandler
->AddRef();
1989 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= x
;
1990 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= y
;
1991 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= x
;
1992 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= y
;
1993 mSizes
[wxCBAR_FLOATING
].x
= x
;
1994 mSizes
[wxCBAR_FLOATING
].y
= y
;
1997 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1998 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
2001 cbDimInfo::~cbDimInfo()
2005 mpHandler
->RemoveRef();
2008 const cbDimInfo
& cbDimInfo::operator=( const cbDimInfo
& other
)
2010 if ( this == &other
)
2014 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2015 mSizes
[i
] = other
.mSizes
[i
];
2017 mIsFixed
= other
.mIsFixed
;
2018 mpHandler
= other
.mpHandler
;
2020 mVertGap
= other
.mVertGap
;
2021 mHorizGap
= other
.mHorizGap
;
2025 mpHandler
->AddRef();
2030 /***** Implementation for structure cbCommonPaneProperties *****/
2032 IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties
, wxObject
)
2034 cbCommonPaneProperties::cbCommonPaneProperties(void)
2036 : mRealTimeUpdatesOn ( TRUE
),
2037 mOutOfPaneDragOn ( TRUE
),
2038 mExactDockPredictionOn( FALSE
),
2039 mNonDestructFirctionOn( FALSE
),
2040 mShow3DPaneBorderOn ( TRUE
),
2041 mBarFloatingOn ( FALSE
),
2042 mRowProportionsOn ( FALSE
),
2043 mColProportionsOn ( TRUE
),
2044 mBarCollapseIconsOn ( FALSE
),
2045 mBarDragHintsOn ( FALSE
),
2047 mMinCBarDim( 16, 16 ),
2048 mResizeHandleSize( 4 )
2051 /***** Implementation for class cbRowInfo *****/
2053 IMPLEMENT_DYNAMIC_CLASS( cbRowInfo
, wxObject
)
2055 cbRowInfo::cbRowInfo(void)
2057 : mNotFixedBarsCnt( FALSE
),
2060 mpExpandedBar ( NULL
)
2063 cbRowInfo::~cbRowInfo()
2065 // nothing! all bars are removed using global bar
2066 // list in wxFrameLayout class
2069 /***** Implementation for class cbBarInfo *****/
2071 IMPLEMENT_DYNAMIC_CLASS( cbBarInfo
, wxObject
)
2073 cbBarInfo::cbBarInfo(void)
2081 cbBarInfo::~cbBarInfo()
2086 /***** Implementation for class cbDockPane *****/
2088 IMPLEMENT_DYNAMIC_CLASS( cbDockPane
, wxObject
)
2090 // FIXME:: how to eliminate these cut&pasted constructors?
2092 cbDockPane::cbDockPane(void)
2093 : mLeftMargin ( 1 ),
2097 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2098 // since the real dimensions of the pane may not
2099 // be known, while inserting bars initially
2100 mPaneHeight( 32768 ),
2106 cbDockPane::cbDockPane( int alignment
, wxFrameLayout
* pPanel
)
2108 : mLeftMargin ( 1 ),
2112 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2113 // since the real dimensions of the pane may not
2114 // be known, while inserting bars initially
2115 mPaneHeight( 32768 ),
2116 mAlignment ( alignment
),
2117 mpLayout ( pPanel
),
2121 cbDockPane::~cbDockPane()
2124 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2127 mRowShapeData
.DeleteContents( TRUE
);
2129 // NOTE:: control bar infromation structures are cleaned-up
2130 // in wxFrameLayout's destructor, using global control-bar list
2133 void cbDockPane::SetMargins( int top
, int bottom
, int left
, int right
)
2136 mBottomMargin
= bottom
;
2138 mRightMargin
= right
;
2141 /*** helpers of cbDockPane ***/
2143 void cbDockPane::PaintBarDecorations( cbBarInfo
* pBar
, wxDC
& dc
)
2145 cbDrawBarDecorEvent
evt( pBar
, dc
, this );
2147 mpLayout
->FirePluginEvent( evt
);
2150 void cbDockPane::PaintBarHandles( cbBarInfo
* pBar
, wxDC
& dc
)
2152 cbDrawBarHandlesEvent
evt( pBar
, dc
, this );
2154 mpLayout
->FirePluginEvent( evt
);
2157 void cbDockPane::PaintBar( cbBarInfo
* pBar
, wxDC
& dc
)
2159 PaintBarDecorations( pBar
, dc
);
2160 PaintBarHandles( pBar
, dc
);
2163 void cbDockPane::PaintRowHandles( cbRowInfo
* pRow
, wxDC
& dc
)
2165 cbDrawRowHandlesEvent
evt( pRow
, dc
, this );
2167 mpLayout
->FirePluginEvent( evt
);
2169 cbDrawRowDecorEvent
evt1( pRow
, dc
, this );
2171 mpLayout
->FirePluginEvent( evt1
);
2174 void cbDockPane::PaintRowBackground ( cbRowInfo
* pRow
, wxDC
& dc
)
2176 cbDrawRowBkGroundEvent
evt( pRow
, dc
, this );
2178 mpLayout
->FirePluginEvent( evt
);
2181 void cbDockPane::PaintRowDecorations( cbRowInfo
* pRow
, wxDC
& dc
)
2185 // decorations first
2186 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2188 PaintBarDecorations( pRow
->mBars
[i
], dc
);
2190 // then handles if present
2191 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2193 PaintBarHandles( pRow
->mBars
[i
], dc
);
2196 void cbDockPane::PaintRow( cbRowInfo
* pRow
, wxDC
& dc
)
2198 PaintRowBackground ( pRow
, dc
);
2199 PaintRowDecorations( pRow
, dc
);
2200 PaintRowHandles ( pRow
, dc
);
2203 void cbDockPane::PaintPaneBackground( wxDC
& dc
)
2205 cbDrawPaneBkGroundEvent
evt( dc
, this );
2207 mpLayout
->FirePluginEvent( evt
);
2210 void cbDockPane::PaintPaneDecorations( wxDC
& dc
)
2212 cbDrawPaneDecorEvent
evt( dc
, this );
2214 mpLayout
->FirePluginEvent( evt
);
2217 void cbDockPane::PaintPane( wxDC
& dc
)
2219 PaintPaneBackground( dc
);
2223 // first decorations
2224 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2226 PaintRowBackground( mRows
[i
], dc
);
2227 PaintRowDecorations( mRows
[i
], dc
);
2231 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2232 PaintRowHandles( mRows
[i
], dc
);
2235 PaintPaneDecorations( dc
);
2238 void cbDockPane::SizeBar( cbBarInfo
* pBar
)
2240 cbSizeBarWndEvent
evt( pBar
, this );
2242 mpLayout
->FirePluginEvent( evt
);
2246 void cbDockPane::SizeRowObjects( cbRowInfo
* pRow
)
2249 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2250 SizeBar( pRow
->mBars
[i
] );
2253 void cbDockPane::SizePaneObjects()
2256 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2257 SizeRowObjects( mRows
[i
] );
2260 wxDC
* cbDockPane::StartDrawInArea( const wxRect
& area
)
2264 cbStartDrawInAreaEvent
evt( area
, &pDc
, this );
2266 mpLayout
->FirePluginEvent( evt
);
2271 void cbDockPane::FinishDrawInArea( const wxRect
& area
)
2273 cbFinishDrawInAreaEvent
evt( area
, this );
2275 mpLayout
->FirePluginEvent( evt
);
2278 bool cbDockPane::IsFixedSize( cbBarInfo
* pInfo
)
2280 return ( pInfo
->mDimInfo
.mIsFixed
);
2283 int cbDockPane::GetNotFixedBarsCount( cbRowInfo
* pRow
)
2288 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2290 if ( !pRow
->mBars
[i
]->IsFixed() )
2297 void cbDockPane::RemoveBar( cbBarInfo
* pBar
)
2299 bool needsRestoring
= mProps
.mNonDestructFirctionOn
&&
2300 mpStoredRow
== pBar
->mpRow
;
2302 cbRemoveBarEvent
evt( pBar
, this );
2304 mpLayout
->FirePluginEvent( evt
);
2306 if ( needsRestoring
)
2308 SetRowShapeData( mpStoredRow
, &mRowShapeData
);
2314 void cbDockPane::SyncRowFlags( cbRowInfo
* pRow
)
2316 // setup mHasOnlyFixedBars flag for the row information
2317 pRow
->mHasOnlyFixedBars
= TRUE
;
2319 pRow
->mNotFixedBarsCnt
= 0;
2322 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2324 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2328 if ( !bar
.IsFixed() )
2330 pRow
->mHasOnlyFixedBars
= FALSE
;
2331 ++pRow
->mNotFixedBarsCnt
;
2336 void cbDockPane::FrameToPane( int* x
, int* y
)
2341 if ( mAlignment
== FL_ALIGN_TOP
||
2342 mAlignment
== FL_ALIGN_BOTTOM
2345 *x
-= mBoundsInParent
.x
;
2346 *y
-= mBoundsInParent
.y
;
2350 int rx
= *x
, ry
= *y
;
2352 *x
= ry
- mBoundsInParent
.y
;
2354 *y
= rx
- mBoundsInParent
.x
;
2358 void cbDockPane::PaneToFrame( int* x
, int* y
)
2360 if ( mAlignment
== FL_ALIGN_TOP
||
2361 mAlignment
== FL_ALIGN_BOTTOM
2364 *x
+= mBoundsInParent
.x
;
2365 *y
+= mBoundsInParent
.y
;
2369 int rx
= *x
, ry
= *y
;
2371 *x
= ry
+ mBoundsInParent
.x
;
2373 *y
= mBoundsInParent
.y
+ rx
;
2380 void cbDockPane::FrameToPane( wxRect
* pRect
)
2382 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2383 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2384 pRect
->y
+ pRect
->height
);
2386 FrameToPane( &upperLeft
.x
, &upperLeft
.y
);
2387 FrameToPane( &lowerRight
.x
, &lowerRight
.y
);
2389 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2390 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2392 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2393 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2396 void cbDockPane::PaneToFrame( wxRect
* pRect
)
2398 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2399 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2400 pRect
->y
+ pRect
->height
);
2402 PaneToFrame( &upperLeft
.x
, &upperLeft
.y
);
2403 PaneToFrame( &lowerRight
.x
, &lowerRight
.y
);
2405 //wxRect newRect = wxRect( upperLeft, lowerRight );
2407 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2408 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2410 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2411 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2414 int cbDockPane::GetRowAt( int paneY
)
2423 for ( ; i
!= mRows
.Count(); ++i
)
2425 int rowHeight
= mRows
[i
]->mRowHeight
;
2427 int third
= rowHeight
/3;
2429 if ( paneY
>= curY
&& paneY
< curY
+ third
)
2432 if ( paneY
>= curY
+ third
&& paneY
< curY
+ rowHeight
- third
)
2441 int cbDockPane::GetRowAt( int upperY
, int lowerY
)
2445 int range = lowerY - upperY;
2446 int oneThird = range / 3;
2448 wxNode* pRow = mRows.First();
2452 if ( lowerY <= 0 ) return -1;
2456 int rowHeight = GetRowHeight( (wxList*)pRow->Data() );
2458 if ( upperY >= curY &&
2459 lowerY < curY ) return row;
2461 if ( upperY <= curY &&
2463 curY - upperY >= oneThird ) return row-1;
2465 if ( ( upperY < curY + rowHeight &&
2466 lowerY >= curY + rowHeight &&
2467 curY + rowHeight - lowerY >= oneThird )
2471 if ( lowerY <= curY + rowHeight ) return row;
2475 pRow = pRow->Next();
2479 int mid
= upperY
+ (lowerY
- upperY
)/2;
2487 for ( ; i
!= mRows
.Count(); ++i
)
2489 int rowHeight
= mRows
[i
]->mRowHeight
;
2491 if ( mid
>= curY
&& mid
< curY
+ rowHeight
) return i
;
2499 int cbDockPane::GetRowY( cbRowInfo
* pRow
)
2504 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2506 if ( mRows
[i
] == pRow
)
2509 curY
+= mRows
[i
]->mRowHeight
;
2515 bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo
* pRow
)
2517 while ( pRow
->mpPrev
)
2519 pRow
= pRow
->mpPrev
;
2521 if ( pRow
->mHasOnlyFixedBars
)
2529 bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo
* pRow
)
2531 while( pRow
->mpNext
)
2533 pRow
= pRow
->mpNext
;
2535 if ( pRow
->mHasOnlyFixedBars
)
2543 bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo
* pBar
)
2545 while( pBar
->mpPrev
)
2547 pBar
= pBar
->mpPrev
;
2549 if ( pBar
->IsFixed() )
2557 bool cbDockPane::HasNotFixedBarsRight( cbBarInfo
* pBar
)
2559 while( pBar
->mpNext
)
2561 pBar
= pBar
->mpNext
;
2563 if ( pBar
->IsFixed() )
2571 void cbDockPane::CalcLengthRatios( cbRowInfo
* pInRow
)
2577 // calc current-maximal-total-length of all maximized bars
2579 for ( i
= 0; i
!= pInRow
->mBars
.GetCount(); ++i
)
2581 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2583 if ( !bar
.IsFixed() )
2584 totalWidth
+= bar
.mBounds
.width
;
2587 // set up percentages of occupied space for each maximized bar
2589 for ( i
= 0; i
!= pInRow
->mBars
.Count(); ++i
)
2591 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2593 if ( !bar
.IsFixed() )
2594 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalWidth
);
2598 void cbDockPane::RecalcRowLayout( cbRowInfo
* pRow
)
2600 cbLayoutRowEvent
evt( pRow
, this );
2602 mpLayout
->FirePluginEvent( evt
);
2605 void cbDockPane::ExpandBar( cbBarInfo
* pBar
)
2607 mpLayout
->GetUpdatesManager().OnStartChanges();
2609 if ( !pBar
->mpRow
->mpExpandedBar
)
2611 // save ratios only when there arent any bars expanded yet
2613 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2616 ratios
.Alloc( pBar
->mpRow
->mNotFixedBarsCnt
);
2618 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2622 if ( !pCur
->IsFixed() )
2625 ratios
[ ratios
.GetCount() - 1 ] = pCur
->mLenRatio
;
2628 pCur
= pCur
->mpNext
;
2632 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2636 pCur
->mLenRatio
= 0.0; // minimize the rest
2638 pCur
= pCur
->mpNext
;
2641 pBar
->mLenRatio
= 1.0; // 100%
2642 pBar
->mBounds
.width
= 0;
2644 pBar
->mpRow
->mpExpandedBar
= pBar
;
2646 mpLayout
->RecalcLayout( FALSE
);
2648 mpLayout
->GetUpdatesManager().OnFinishChanges();
2649 mpLayout
->GetUpdatesManager().UpdateNow();
2652 void cbDockPane::ContractBar( cbBarInfo
* pBar
)
2654 mpLayout
->GetUpdatesManager().OnStartChanges();
2656 // FIXME: What's the purpose of this???
2657 // double ratio = 1.0/ double( pBar->mpRow->mNotFixedBarsCnt );
2659 // restore ratios which were present before expansion
2661 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2663 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2669 if ( !pCur
->IsFixed() )
2671 pCur
->mLenRatio
= ratios
[i
];
2675 pCur
= pCur
->mpNext
;
2681 pBar
->mpRow
->mpExpandedBar
= NULL
;
2683 mpLayout
->RecalcLayout( FALSE
);
2685 mpLayout
->GetUpdatesManager().OnFinishChanges();
2686 mpLayout
->GetUpdatesManager().UpdateNow();
2689 void cbDockPane::InitLinksForRow( cbRowInfo
* pRow
)
2692 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2694 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2699 bar
.mpPrev
= pRow
->mBars
[i
-1];
2701 if ( i
== pRow
->mBars
.Count() - 1 )
2704 bar
.mpNext
= pRow
->mBars
[i
+1];
2708 void cbDockPane::InitLinksForRows()
2711 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2713 cbRowInfo
& row
= *mRows
[i
];
2718 row
.mpPrev
= mRows
[i
-1];
2720 if ( i
== mRows
.Count() - 1 )
2723 row
.mpNext
= mRows
[i
+1];
2727 void cbDockPane::DoInsertBar( cbBarInfo
* pBar
, int rowNo
)
2729 cbRowInfo
* pRow
= NULL
;
2731 if ( rowNo
== -1 || rowNo
>= (int)mRows
.Count() )
2733 pRow
= new cbRowInfo();
2735 if ( rowNo
== -1 && mRows
.Count() )
2737 mRows
.Insert( pRow
, 0 );
2745 pRow
= mRows
[rowNo
];
2747 if ( mProps
.mNonDestructFirctionOn
== TRUE
)
2749 // store original shape of the row (before the bar is inserted)
2753 GetRowShapeData( mpStoredRow
, &mRowShapeData
);
2757 if ( pRow
->mBars
.Count() )
2759 pRow
->mpExpandedBar
= NULL
;
2761 cbInsertBarEvent
insEvt( pBar
, pRow
, this );
2763 mpLayout
->FirePluginEvent( insEvt
);
2765 mpLayout
->GetUpdatesManager().OnRowWillChange( pRow
, this );
2768 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
, const wxRect
& atRect
)
2770 wxRect rect
= atRect
;
2771 FrameToPane( &rect
);
2773 pBarInfo
->mBounds
.x
= rect
.x
;
2774 pBarInfo
->mBounds
.width
= rect
.width
;
2775 pBarInfo
->mBounds
.height
= rect
.height
;
2777 int row
= GetRowAt( rect
.y
, rect
.y
+ rect
.height
);
2779 DoInsertBar( pBarInfo
, row
);
2782 void cbDockPane::InsertBar( cbBarInfo
* pBar
, cbRowInfo
* pIntoRow
)
2784 cbInsertBarEvent
insEvt( pBar
, pIntoRow
, this );
2786 mpLayout
->FirePluginEvent( insEvt
);
2788 mpLayout
->GetUpdatesManager().OnRowWillChange( pIntoRow
, this );
2791 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
)
2793 // set transient properties
2795 pBarInfo
->mpRow
= NULL
;
2796 pBarInfo
->mHasLeftHandle
= FALSE
;
2797 pBarInfo
->mHasRightHandle
= FALSE
;
2798 pBarInfo
->mLenRatio
= 0.0;
2800 // set preferred bar dimensions, according to the state in which
2801 // the bar is being inserted
2803 pBarInfo
->mBounds
.width
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].x
;
2804 pBarInfo
->mBounds
.height
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].y
;
2806 DoInsertBar( pBarInfo
, pBarInfo
->mRowNo
);
2809 void cbDockPane::RemoveRow( cbRowInfo
* pRow
)
2812 // first, hide all bar-windows in the removed row
2813 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2815 if ( pRow
->mBars
[i
]->mpBarWnd
)
2816 pRow
->mBars
[i
]->mpBarWnd
->Show( FALSE
);
2819 mRows
.Remove( pRow
);
2821 pRow
->mUMgrData
.SetDirty(TRUE
);
2824 void cbDockPane::InsertRow( cbRowInfo
* pRow
, cbRowInfo
* pBeforeRow
)
2830 mRows
.Insert( pRow
, mRows
.Index( pBeforeRow
) );
2834 pRow
->mUMgrData
.SetDirty(TRUE
);
2837 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2838 pRow
->mBars
[i
]->mUMgrData
.SetDirty( TRUE
);
2840 SyncRowFlags( pRow
);
2843 void cbDockPane::SetPaneWidth(int width
)
2845 if ( IsHorizontal() )
2846 mPaneWidth
= width
- mLeftMargin
- mRightMargin
;
2848 mPaneWidth
= width
- mTopMargin
- mBottomMargin
;
2852 void cbDockPane::SetBoundsInParent( const wxRect
& rect
)
2854 mBoundsInParent
= rect
;
2856 // set pane dimensions in local coordinates
2858 if ( IsHorizontal() )
2860 mPaneWidth
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2861 mPaneHeight
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2865 mPaneWidth
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2866 mPaneHeight
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2869 // convert bounding rectangles of all pane items into parent frame's coordinates
2871 wxBarIterator
i( mRows
);
2873 wxRect noMarginsRect
= mBoundsInParent
;
2875 noMarginsRect
.x
+= mLeftMargin
;
2876 noMarginsRect
.y
+= mTopMargin
;
2877 noMarginsRect
.width
-= ( mLeftMargin
+ mRightMargin
);
2878 noMarginsRect
.height
-= ( mTopMargin
+ mBottomMargin
);
2880 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2882 if ( mBoundsInParent
.width
< 0 ||
2883 mBoundsInParent
.height
< 0 )
2885 hide_rect( mBoundsInParent
);
2887 if ( noMarginsRect
.width
< 0 ||
2888 noMarginsRect
.height
< 0 )
2890 hide_rect( noMarginsRect
);
2892 // calculate mBoundsInParent for each item in the pane
2896 cbBarInfo
& bar
= i
.BarInfo();
2898 cbRowInfo
* pRowInfo
= bar
.mpRow
;
2900 // set up row info, if this is first bar in the row
2902 if ( pRowInfo
&& bar
.mpPrev
== NULL
)
2904 pRowInfo
->mBoundsInParent
.y
= pRowInfo
->mRowY
;
2905 pRowInfo
->mBoundsInParent
.x
= 0;
2906 pRowInfo
->mBoundsInParent
.width
= mPaneWidth
;
2907 pRowInfo
->mBoundsInParent
.height
= pRowInfo
->mRowHeight
;
2909 PaneToFrame( &pRowInfo
->mBoundsInParent
);
2911 clip_rect_against_rect( pRowInfo
->mBoundsInParent
, noMarginsRect
);
2914 wxRect bounds
= bar
.mBounds
;
2916 // exclude dimensions of handles, when calculating
2917 // bar's bounds in parent (i.e. "visual bounds")
2919 if ( bar
.mHasLeftHandle
)
2921 bounds
.x
+= mProps
.mResizeHandleSize
;
2922 bounds
.width
-= mProps
.mResizeHandleSize
;
2925 if ( bar
.mHasRightHandle
)
2927 bounds
.width
-= mProps
.mResizeHandleSize
;
2929 PaneToFrame( &bounds
);
2931 clip_rect_against_rect( bounds
, noMarginsRect
);
2933 bar
.mBoundsInParent
= bounds
;
2937 bool cbDockPane::BarPresent( cbBarInfo
* pBar
)
2939 wxBarIterator
iter( mRows
);
2941 while( iter
.Next() )
2943 if ( &iter
.BarInfo() == pBar
) return TRUE
;
2948 cbRowInfo
* cbDockPane::GetRow( int row
)
2950 if ( row
>= (int)mRows
.Count() ) return NULL
;
2952 return mRows
[ row
];
2955 int cbDockPane::GetRowIndex( cbRowInfo
* pRow
)
2958 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2960 if ( mRows
[i
] == pRow
)
2964 wxFAIL_MSG("Row must be present to call cbDockPane::GetRowIndex()");
2969 int cbDockPane::GetPaneHeight()
2971 // first, recalculate row heights and the Y-positions
2973 cbLayoutRowsEvent
evt( this );
2974 mpLayout
->FirePluginEvent( evt
);
2978 if ( IsHorizontal() )
2980 height
+= mTopMargin
+ mBottomMargin
;
2982 height
+= mLeftMargin
+ mRightMargin
;
2984 int count
= mRows
.Count();
2988 height
+= mRows
[count
-1]->mRowY
+ mRows
[count
-1]->mRowHeight
;
2993 int cbDockPane::GetAlignment()
2998 bool cbDockPane::MatchesMask( int paneMask
)
3002 // FIXME:: use array instead of switch()
3006 case FL_ALIGN_TOP
: thisMask
= FL_ALIGN_TOP_PANE
; break;
3007 case FL_ALIGN_BOTTOM
: thisMask
= FL_ALIGN_BOTTOM_PANE
;break;
3008 case FL_ALIGN_LEFT
: thisMask
= FL_ALIGN_LEFT_PANE
; break;
3009 case FL_ALIGN_RIGHT
: thisMask
= FL_ALIGN_RIGHT_PANE
; break;
3012 wxFAIL_MSG("Bad FL alignment type detected in cbDockPane::MatchesMask()");
3015 return ( thisMask
& paneMask
) != 0;
3018 void cbDockPane::RecalcLayout()
3020 // first, reposition rows and items vertically
3022 cbLayoutRowsEvent
evt( this );
3023 mpLayout
->FirePluginEvent( evt
);
3025 // then horizontally in each row
3028 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3029 RecalcRowLayout( mRows
[i
] );
3032 int cbDockPane::GetDockingState()
3034 if ( mAlignment
== FL_ALIGN_TOP
||
3035 mAlignment
== FL_ALIGN_BOTTOM
)
3037 return wxCBAR_DOCKED_HORIZONTALLY
;
3040 return wxCBAR_DOCKED_VERTICALLY
;
3043 inline bool cbDockPane::HasPoint( const wxPoint
& pos
, int x
, int y
,
3044 int width
, int height
)
3046 return ( pos
.x
>= x
&&
3048 pos
.x
< x
+ width
&&
3049 pos
.y
< y
+ height
);
3052 int cbDockPane::HitTestPaneItems( const wxPoint
& pos
,
3061 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3063 cbRowInfo
& row
= *mRows
[i
];
3067 // hit-test handles of the row, if present
3069 if ( row
.mHasUpperHandle
)
3071 if ( HasPoint( pos
, 0, row
.mRowY
,
3072 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3074 return CB_UPPER_ROW_HANDLE_HITTED
;
3077 if ( row
.mHasLowerHandle
)
3079 if ( HasPoint( pos
, 0, row
.mRowY
+ row
.mRowHeight
- mProps
.mResizeHandleSize
,
3080 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3082 return CB_LOWER_ROW_HANDLE_HITTED
;
3085 // hit-test bar handles and bar content
3088 for ( k
= 0; k
!= row
.mBars
.Count(); ++k
)
3090 cbBarInfo
& bar
= *row
.mBars
[k
];
3091 wxRect
& bounds
= bar
.mBounds
;
3095 if ( bar
.mHasLeftHandle
)
3097 if ( HasPoint( pos
, bounds
.x
, bounds
.y
,
3098 mProps
.mResizeHandleSize
, bounds
.height
) )
3100 return CB_LEFT_BAR_HANDLE_HITTED
;
3103 if ( bar
.mHasRightHandle
)
3105 if ( HasPoint( pos
, bounds
.x
+ bounds
.width
- mProps
.mResizeHandleSize
, bounds
.y
,
3106 mProps
.mResizeHandleSize
, bounds
.height
) )
3108 return CB_RIGHT_BAR_HANDLE_HITTED
;
3111 if ( HasPoint( pos
, bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
) )
3112 return CB_BAR_CONTENT_HITTED
;
3114 } // hit-test next bar
3118 return CB_NO_ITEMS_HITTED
;
3121 void cbDockPane::GetBarResizeRange( cbBarInfo
* pBar
, int* from
, int *till
,
3122 bool forLeftHandle
)
3124 cbBarInfo
* pGivenBar
= pBar
;
3128 // calc unavailable space from the left
3130 while( pBar
->mpPrev
)
3132 pBar
= pBar
->mpPrev
;
3134 if ( !pBar
->IsFixed() ) notFree
+= mProps
.mMinCBarDim
.x
;
3135 else notFree
+= pBar
->mBounds
.width
;
3144 // calc unavailable space from the right
3146 while( pBar
->mpNext
)
3148 pBar
= pBar
->mpNext
;
3150 if ( pBar
->mBounds
.x
>= mPaneWidth
) break;
3152 // treat not-fixed bars as minimized
3154 if ( !pBar
->IsFixed() )
3156 notFree
+= mProps
.mMinCBarDim
.x
;
3159 if ( pBar
->mBounds
.x
+ pBar
->mBounds
.width
>= mPaneWidth
)
3161 notFree
+= mPaneWidth
- pBar
->mBounds
.x
;
3165 notFree
+= pBar
->mBounds
.width
;
3170 *till
= mPaneWidth
- notFree
;
3172 // do not let resizing totally deform the bar itself
3174 if ( forLeftHandle
)
3176 (*till
) -= mProps
.mMinCBarDim
.x
;
3179 (*from
) += mProps
.mMinCBarDim
.x
;
3182 int cbDockPane::GetMinimalRowHeight( cbRowInfo
* pRow
)
3184 int height
= mProps
.mMinCBarDim
.y
;
3187 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3189 if ( pRow
->mBars
[i
]->IsFixed() )
3190 height
= wxMax( height
, pRow
->mBars
[i
]->mBounds
.height
);
3193 if ( pRow
->mHasUpperHandle
)
3194 height
+= mProps
.mResizeHandleSize
;
3196 if ( pRow
->mHasLowerHandle
)
3197 height
+= mProps
.mResizeHandleSize
;
3202 void cbDockPane::SetRowHeight( cbRowInfo
* pRow
, int newHeight
)
3204 if ( pRow
->mHasUpperHandle
)
3206 newHeight
-= mProps
.mResizeHandleSize
;
3208 if ( pRow
->mHasLowerHandle
)
3210 newHeight
-= mProps
.mResizeHandleSize
;
3213 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3215 if ( !pRow
->mBars
[i
]->IsFixed() )
3216 pRow
->mBars
[i
]->mBounds
.height
= newHeight
;
3220 void cbDockPane::GetRowResizeRange( cbRowInfo
* pRow
, int* from
, int* till
,
3221 bool forUpperHandle
)
3223 cbRowInfo
* pGivenRow
= pRow
;
3225 // calc unavailable space from above
3229 while( pRow
->mpPrev
)
3231 pRow
= pRow
->mpPrev
;
3233 notFree
+= GetMinimalRowHeight( pRow
);
3239 // allow accupy the client window space by resizing pane rows
3240 if ( mAlignment
== FL_ALIGN_BOTTOM
)
3242 *from
-= mpLayout
->GetClientHeight();
3244 if ( mAlignment
== FL_ALIGN_RIGHT
)
3246 *from
-= mpLayout
->GetClientWidth();
3248 // calc unavailable space from below
3254 while( pRow
->mpNext
)
3256 pRow
= pRow
->mpNext
;
3258 notFree
+= GetMinimalRowHeight( pRow
);
3262 *till
= mPaneHeight
- notFree
;
3264 // allow adjustinig pane space vs. client window space by resizing pane row heights
3266 if ( mAlignment
== FL_ALIGN_TOP
)
3268 *till
+= mpLayout
->GetClientHeight();
3270 if ( mAlignment
== FL_ALIGN_LEFT
)
3272 *till
+= mpLayout
->GetClientWidth();
3274 // do not let the resizing of the row totally squeeze the row itself
3276 cbRowInfo
& row
= *pGivenRow
;
3278 if ( forUpperHandle
)
3280 *till
= row
.mRowY
+ row
.mRowHeight
- GetMinimalRowHeight( pGivenRow
);
3282 if ( row
.mHasUpperHandle
)
3284 *till
-= mProps
.mResizeHandleSize
;
3288 *from
+= GetMinimalRowHeight( pGivenRow
);
3290 if ( row
.mHasLowerHandle
)
3292 *from
-= mProps
.mResizeHandleSize
;
3296 void cbDockPane::ResizeRow( cbRowInfo
* pRow
, int ofs
,
3297 bool forUpperHandle
)
3299 cbResizeRowEvent
evt( pRow
, ofs
, forUpperHandle
, this );
3301 mpLayout
->FirePluginEvent( evt
);
3304 void cbDockPane::ResizeBar( cbBarInfo
* pBar
, int ofs
,
3305 bool forLeftHandle
)
3307 pBar
->mpRow
->mpExpandedBar
= NULL
;
3309 mpLayout
->GetUpdatesManager().OnStartChanges();
3311 wxRect
& bounds
= pBar
->mBounds
;
3313 if ( forLeftHandle
)
3315 // do not allow bar width become less then minimal
3316 if ( bounds
.x
+ ofs
> bounds
.x
+ bounds
.width
- mProps
.mMinCBarDim
.x
)
3318 bounds
.width
= mProps
.mMinCBarDim
.x
;
3324 bounds
.width
-= ofs
;
3329 // move bar left if necessary
3330 if ( bounds
.width
+ ofs
< mProps
.mMinCBarDim
.x
)
3332 bounds
.x
= bounds
.x
+ bounds
.width
+ ofs
- mProps
.mMinCBarDim
.x
;
3333 bounds
.width
= mProps
.mMinCBarDim
.x
;
3336 // resize right border only
3337 bounds
.width
+= ofs
;
3341 cbRowInfo
* pToRow
= pBar
->mpRow
;
3343 this->RemoveBar( pBar
);
3345 InsertBar( pBar
, pToRow
);
3347 mpLayout
->RecalcLayout(FALSE
);
3349 mpLayout
->GetUpdatesManager().OnFinishChanges();
3350 mpLayout
->GetUpdatesManager().UpdateNow();
3354 /*** row/bar resizing related methods ***/
3356 void cbDockPane::DrawVertHandle( wxDC
& dc
, int x
, int y
, int height
)
3358 int lower
= y
+ height
;
3360 dc
.SetPen( mpLayout
->mLightPen
);
3361 dc
.DrawLine( x
,y
, x
, lower
);
3363 dc
.SetPen( mpLayout
->mGrayPen
);
3365 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3368 dc
.DrawLine( x
,y
, x
, lower
);
3371 dc
.SetPen( mpLayout
->mDarkPen
);
3373 dc
.DrawLine( x
,y
, x
, lower
);
3375 dc
.SetPen( mpLayout
->mBlackPen
);
3377 dc
.DrawLine( x
,y
, x
, lower
);
3380 void cbDockPane::DrawHorizHandle( wxDC
& dc
, int x
, int y
, int width
)
3382 int right
= x
+ width
;
3384 dc
.SetPen( mpLayout
->mLightPen
);
3385 dc
.DrawLine( x
,y
, right
, y
);
3387 dc
.SetPen( mpLayout
->mGrayPen
);
3390 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3393 dc
.DrawLine( x
,y
, right
, y
);
3396 dc
.SetPen( mpLayout
->mDarkPen
);
3397 dc
.DrawLine( x
,y
, right
, ++y
);
3399 dc
.SetPen( mpLayout
->mBlackPen
);
3400 dc
.DrawLine( x
,y
, right
, ++y
);
3403 cbBarInfo
* cbDockPane::GetBarInfoByWindow( wxWindow
* pBarWnd
)
3405 wxBarIterator
i( mRows
);
3409 if ( i
.BarInfo().mpBarWnd
== pBarWnd
)
3411 return &i
.BarInfo();
3416 void cbDockPane::GetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3418 pLst
->DeleteContents( TRUE
);
3422 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3424 cbBarInfo
& bar
= *pRow
->mBars
[i
];
3426 cbBarShapeData
* pData
= new cbBarShapeData();
3428 pLst
->Append( (wxObject
*)pData
);
3430 pData
->mBounds
= bar
.mBounds
;
3431 pData
->mLenRatio
= bar
.mLenRatio
;
3435 void cbDockPane::SetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3437 if ( pLst
->First() == NULL
)
3440 wxNode
* pData
= pLst
->First();
3443 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3445 wxASSERT( pData
); // DBG::
3447 cbBarInfo
& bar
= *pRow
->mBars
[i
];;
3449 cbBarShapeData
& data
= *((cbBarShapeData
*)pData
->Data());
3451 bar
.mBounds
= data
.mBounds
;
3452 bar
.mLenRatio
= data
.mLenRatio
;
3454 pData
= pData
->Next();
3458 /***** Implementation for class cbUpdatesManagerBase *****/
3460 IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase
, wxObject
)
3462 /***** Implementation for class cbPluginBase *****/
3464 IMPLEMENT_ABSTRACT_CLASS( cbPluginBase
, wxEvtHandler
)
3466 cbPluginBase::~cbPluginBase()
3471 bool cbPluginBase::ProcessEvent(wxEvent
& event
)
3473 if ( mPaneMask
== wxALL_PANES
)
3475 return wxEvtHandler::ProcessEvent( event
);
3477 // extract mask info. from received event
3479 cbPluginEvent
& evt
= *( (cbPluginEvent
*)&event
);
3481 if ( evt
.mpPane
== 0 &&
3482 mPaneMask
== wxALL_PANES
)
3484 return wxEvtHandler::ProcessEvent( event
);
3488 switch ( evt
.mpPane
->mAlignment
)
3490 case FL_ALIGN_TOP
: mask
= FL_ALIGN_TOP_PANE
; break;
3491 case FL_ALIGN_BOTTOM
: mask
= FL_ALIGN_BOTTOM_PANE
;break;
3492 case FL_ALIGN_LEFT
: mask
= FL_ALIGN_LEFT_PANE
; break;
3493 case FL_ALIGN_RIGHT
: mask
= FL_ALIGN_RIGHT_PANE
; break;
3496 // if event's pane maks matches the plugin's mask
3498 if ( mPaneMask
& mask
)
3500 return wxEvtHandler::ProcessEvent( event
);
3502 // otherwise pass to the next handler if present
3504 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event
) )