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 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
26 #include "wx/string.h"
27 #include "wx/utils.h" // import wxMin,wxMax macros
28 #include "wx/minifram.h"
30 #include "wx/fl/controlbar.h"
32 // import classes of default plugins
34 #include "wx/fl/panedrawpl.h"
35 #include "wx/fl/rowlayoutpl.h"
36 #include "wx/fl/antiflickpl.h"
37 #include "wx/fl/bardragpl.h"
38 #include "wx/fl/cbcustom.h"
40 #include "wx/fl/gcupdatesmgr.h" // import default updates manager class ("garbage-collecting" one)
41 #include "wx/fl/updatesmgr.h"
43 #include "wx/fl/toolwnd.h"
45 // These are the event IDs being initialized to a value to
46 // meet the new event paradigm as of wx2.3.0. Probably we
47 // should find a way to make these be non-global, but this
48 // works for right now.
49 wxEventType cbEVT_PL_LEFT_DOWN
= wxNewEventType();
50 wxEventType cbEVT_PL_LEFT_UP
= wxNewEventType();
51 wxEventType cbEVT_PL_RIGHT_DOWN
= wxNewEventType();
52 wxEventType cbEVT_PL_RIGHT_UP
= wxNewEventType();
53 wxEventType cbEVT_PL_MOTION
= wxNewEventType();
55 wxEventType cbEVT_PL_LEFT_DCLICK
= wxNewEventType();
57 wxEventType cbEVT_PL_LAYOUT_ROW
= wxNewEventType();
58 wxEventType cbEVT_PL_RESIZE_ROW
= wxNewEventType();
59 wxEventType cbEVT_PL_LAYOUT_ROWS
= wxNewEventType();
60 wxEventType cbEVT_PL_INSERT_BAR
= wxNewEventType();
61 wxEventType cbEVT_PL_RESIZE_BAR
= wxNewEventType();
62 wxEventType cbEVT_PL_REMOVE_BAR
= wxNewEventType();
63 wxEventType cbEVT_PL_SIZE_BAR_WND
= wxNewEventType();
65 wxEventType cbEVT_PL_DRAW_BAR_DECOR
= wxNewEventType();
66 wxEventType cbEVT_PL_DRAW_ROW_DECOR
= wxNewEventType();
67 wxEventType cbEVT_PL_DRAW_PANE_DECOR
= wxNewEventType();
68 wxEventType cbEVT_PL_DRAW_BAR_HANDLES
= wxNewEventType();
69 wxEventType cbEVT_PL_DRAW_ROW_HANDLES
= wxNewEventType();
70 wxEventType cbEVT_PL_DRAW_ROW_BKGROUND
= wxNewEventType();
71 wxEventType cbEVT_PL_DRAW_PANE_BKGROUND
= wxNewEventType();
73 wxEventType cbEVT_PL_START_BAR_DRAGGING
= wxNewEventType();
74 wxEventType cbEVT_PL_DRAW_HINT_RECT
= wxNewEventType();
76 wxEventType cbEVT_PL_START_DRAW_IN_AREA
= wxNewEventType();
77 wxEventType cbEVT_PL_FINISH_DRAW_IN_AREA
= wxNewEventType();
79 wxEventType cbEVT_PL_CUSTOMIZE_BAR
= wxNewEventType();
80 wxEventType cbEVT_PL_CUSTOMIZE_LAYOUT
= wxNewEventType();
82 wxEventType wxCUSTOM_CB_PLUGIN_EVENTS_START_AT
= wxNewEventType();
84 // some ascii-art, still can't get these *nice* cursors working on wx... :-(
87 // FIXME:: see places where _gHorizCursorImg is used
89 static const char* _gHorizCursorImg[] =
91 "............XX....XX............",
92 "............XX....XX............",
93 "............XX....XX............",
94 "............XX....XX............",
95 "............XX....XX............",
96 "...X........XX....XX........X...",
97 "..XX........XX....XX........XX..",
98 ".XXX........XX....XX........XXX.",
99 "XXXXXXXXXXXXXX....XXXXXXXXXXXXXX",
100 ".XXX........XX....XX........XXX.",
101 "..XX........XX....XX........XX..",
102 "...X........XX....XX........X...",
103 "............XX....XX............",
104 "............XX....XX............",
105 "............XX....XX............",
106 "............XX....XX............"
109 static const char* _gVertCursorImg[] =
111 "................X...............",
112 "...............XXX..............",
113 "..............XXXXX.............",
114 ".............XXXXXXX............",
115 "................X...............",
116 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
117 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
118 "................................",
119 "................................",
120 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
121 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
122 "................X...............",
123 ".............XXXXXXX............",
124 "..............XXXXX.............",
125 "...............XXX..............",
126 "................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
)
258 EVT_ERASE_BACKGROUND( wxFrameLayout::OnEraseBackground
)
262 // FIXME:: how to eliminate these cut&pasted constructors?
264 wxFrameLayout::wxFrameLayout(void)
267 mpFrameClient( NULL
),
269 mDarkPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
270 mLightPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT
), 1, wxSOLID
),
271 mGrayPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
272 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID
),
273 mBorderPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
275 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT
),
277 mpPaneInFocus( NULL
),
281 mpTopPlugin ( NULL
),
282 mpCaputesInput( NULL
),
284 mClientWndRefreshPending( false ),
285 mRecalcPending( true ),
286 mCheckFocusWhenIdle( false )
291 for ( i
= 0; i
!= MAX_PANES
; ++i
)
294 mFloatingOn
= CanReparent();
297 wxFrameLayout::wxFrameLayout( wxWindow
* pParentFrame
, wxWindow
* pFrameClient
, bool activateNow
)
299 : mpFrame( pParentFrame
),
300 mpFrameClient(pFrameClient
),
302 mDarkPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
303 mLightPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT
), 1, wxSOLID
),
304 mGrayPen ( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
305 mBlackPen ( wxColour( 0, 0, 0), 1, wxSOLID
),
306 mBorderPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
308 mNullPen( wxColour(0,0,0), 1, wxTRANSPARENT
),
310 mpPaneInFocus( NULL
),
313 mFloatingOn ( true ),
315 mpTopPlugin ( NULL
),
316 mpCaputesInput( NULL
),
318 mClientWndRefreshPending( false ),
319 mRecalcPending( true ),
320 mCheckFocusWhenIdle( false ),
327 for ( i
= 0; i
!= MAX_PANES
; ++i
)
328 mPanes
[i
] = new cbDockPane( i
, this );
335 // DBG:: set RED color of frame's background for the
336 // prurpose of tracking engine bugs "visually"
338 GetParentFrame().SetBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
) );
341 mFloatingOn
= CanReparent();
344 // NOTE:: below are the only platform-check "ifdef"s in the docking system!
346 bool wxFrameLayout::CanReparent()
350 #elif defined(__WXGTK20__)
352 #elif defined (__WXGTK__)
357 return false; // reparenting is not yet supported by Motif and others
367 void wxFrameLayout::ReparentWindow( wxWindow
* pChild
, wxWindow
* pNewParent
)
372 if ( pChild
->GetParent() )
374 bool success
= pChild
->GetParent()->GetChildren().DeleteObject( pChild
);
376 wxASSERT( success
); // DBG::
379 ::SetParent( (HWND
)pChild
->m_hWnd
, (HWND
)pNewParent
->m_hWnd
);
381 pNewParent
->GetChildren().Append( pChild
);
383 pChild
->SetParent( pNewParent
);
385 pChild
->Reparent(pNewParent
);
388 #elif defined(__WXGTK20__)
389 pChild
->Reparent(pNewParent
);
392 #elif defined(__WXGTK__) || defined(__WXX11__)
393 // FOR NOW:: floating with wxGtk still very buggy
397 //pChild->ReParent( pNewParent );
402 wxUnusedVar(pNewParent
);
403 wxMessageBox( "Sorry, docking is not supported for ports other than MSW and wxGTK" );
407 void wxFrameLayout::DestroyBarWindows()
409 wxObjectList::compatibility_iterator pSpy
= mBarSpyList
.GetFirst();
413 cbBarSpy
& spy
= *((cbBarSpy
*)pSpy
->GetData());
415 if ( spy
.mpBarWnd
->GetEventHandler() == &spy
)
417 spy
.mpBarWnd
->PopEventHandler();
421 pSpy
= pSpy
->GetNext();
427 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
429 if ( mAllBars
[i
]->mpBarWnd
)
431 mAllBars
[i
]->mpBarWnd
->Destroy();
432 mAllBars
[i
]->mpBarWnd
= NULL
;
437 void wxFrameLayout::ShowFloatedWindows( bool show
)
439 wxObjectList::compatibility_iterator pNode
= mFloatedFrames
.GetFirst();
443 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->GetData());
447 pNode
= pNode
->GetNext();
451 wxFrameLayout::~wxFrameLayout()
462 // destoy the chain of plugins from left to right
464 wxEvtHandler
* pCur
= mpTopPlugin
;
468 while ( pCur
->GetPreviousHandler() )
470 pCur
= pCur
->GetPreviousHandler();
474 wxEvtHandler
* pNext
= pCur
->GetNextHandler();
481 // destroy contents of arrays and lists
483 for ( i
= 0; i
!= MAX_PANES
; ++i
)
489 delete mpHorizCursor
;
492 if ( mpNormalCursor
)
493 delete mpNormalCursor
;
499 wxObjectList::compatibility_iterator pSpy
= mBarSpyList
.GetFirst();
503 cbBarSpy
& spy
= *((cbBarSpy
*)pSpy
->GetData());
505 if ( spy
.mpBarWnd
->GetEventHandler() == &spy
)
507 spy
.mpBarWnd
->PopEventHandler();
511 pSpy
= pSpy
->GetNext();
514 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
518 void wxFrameLayout::EnableFloating( bool enable
)
520 mFloatingOn
= enable
&& CanReparent();
523 void wxFrameLayout::Activate()
529 ShowFloatedWindows( true );
532 void wxFrameLayout::Deactivate()
534 ShowFloatedWindows( false );
541 void wxFrameLayout::SetFrameClient( wxWindow
* pFrameClient
)
543 mpFrameClient
= pFrameClient
;
546 wxWindow
* wxFrameLayout::GetFrameClient()
548 return mpFrameClient
;
551 cbUpdatesManagerBase
& wxFrameLayout::GetUpdatesManager()
554 mpUpdatesMgr
= CreateUpdatesManager();
556 return *mpUpdatesMgr
;
559 void wxFrameLayout::SetUpdatesManager( cbUpdatesManagerBase
* pUMgr
)
564 mpUpdatesMgr
= pUMgr
;
566 mpUpdatesMgr
->SetLayout( this );
569 cbUpdatesManagerBase
* wxFrameLayout::CreateUpdatesManager()
571 return new cbGCUpdatesMgr( this );
572 //return new cbSimpleUpdatesMgr( this );
575 void wxFrameLayout::AddBar( wxWindow
* pBarWnd
,
576 const cbDimInfo
& dimInfo
,
580 const wxString
& name
,
585 if ( pBarWnd
&& spyEvents
)
587 // hook up spy to bar window
588 cbBarSpy
* pSpy
= new cbBarSpy( this );
590 pSpy
->SetBarWindow( pBarWnd
);
591 pBarWnd
->PushEventHandler( pSpy
);
593 mBarSpyList
.Append( pSpy
);
596 cbBarInfo
* pInfo
= new cbBarInfo();
599 pInfo
->mpBarWnd
= pBarWnd
;
600 pInfo
->mDimInfo
= dimInfo
;
601 pInfo
->mDimInfo
.mLRUPane
= alignment
;
602 pInfo
->mState
= state
;
603 pInfo
->mAlignment
= alignment
;
604 pInfo
->mRowNo
= rowNo
;
605 pInfo
->mBounds
.x
= columnPos
;
607 mAllBars
.Add( pInfo
);
609 DoSetBarState( pInfo
);
612 bool wxFrameLayout::RedockBar( cbBarInfo
* pBar
,
613 const wxRect
& shapeInParent
,
619 pToPane
= HitTestPanes( shapeInParent
, NULL
);
623 return false; // bar's shape does not hit any pane
624 // - redocking is NOT possible
626 cbDockPane
* pBarPane
= GetBarPane( pBar
);
630 GetUpdatesManager().OnStartChanges();
632 pBarPane
->RemoveBar( pBar
);
634 // FIXME FIXME:: the recalculation below may be a *huge* performance
635 // hit, it could be eliminated though...
636 // but first the "pane-postion-changed" problem
639 RecalcLayout( false );
641 pToPane
->InsertBar( pBar
, shapeInParent
);
643 RecalcLayout( false );
645 // finish update "transaction"
649 GetUpdatesManager().OnFinishChanges();
650 GetUpdatesManager().UpdateNow();
656 cbBarInfo
* wxFrameLayout::FindBarByName( const wxString
& name
)
659 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
660 if ( mAllBars
[i
]->mName
== name
)
666 cbBarInfo
* wxFrameLayout::FindBarByWindow( const wxWindow
* pWnd
)
669 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
670 if ( mAllBars
[i
]->mpBarWnd
== pWnd
)
676 BarArrayT
& wxFrameLayout::GetBars()
681 void wxFrameLayout::SetBarState( cbBarInfo
* pBar
, int newState
, bool updateNow
)
683 if ( newState
== wxCBAR_FLOATING
&& !(mFloatingOn
&& pBar
->mFloatingOn
))
689 GetUpdatesManager().OnStartChanges();
691 pBar
->mUMgrData
.SetDirty(true);
693 // check bar's previous state
695 if ( pBar
->mState
!= wxCBAR_HIDDEN
&& pBar
->mState
!= wxCBAR_FLOATING
)
703 LocateBar( pBar
, &pRow
, &pPane
);
705 wxASSERT( success
); // DBG::
707 // save LRU-dim info before removing bar
709 pBar
->mDimInfo
.mLRUPane
= pPane
->GetAlignment();
710 pBar
->mDimInfo
.mBounds
[ pPane
->GetAlignment() ] = pBar
->mBounds
;
712 // remove it from the pane it was docked on
714 pPane
->RemoveBar( pBar
);
718 if ( pBar
->mState
== wxCBAR_FLOATING
&& newState
!= wxCBAR_FLOATING
)
720 // remove bar's window from the containing mini-frame
721 // and set its parent to be layout's parent frame
723 if ( pBar
->mpBarWnd
)
725 pBar
->mpBarWnd
->Show(false); // to avoid flicker upon reparenting
727 wxObjectList::compatibility_iterator pNode
= mFloatedFrames
.GetFirst();
731 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->GetData());
733 if ( pFFrm
->GetBar() == pBar
)
735 pFFrm
->Show( false ); // reduces flicker sligthly
737 ReparentWindow( pBar
->mpBarWnd
, &GetParentFrame() );
739 pBar
->mBounds
= pBar
->mDimInfo
.mBounds
[ pBar
->mDimInfo
.mLRUPane
];
741 if ( newState
!= wxCBAR_HIDDEN
)
743 pBar
->mAlignment
= pBar
->mDimInfo
.mLRUPane
;
745 mFloatedFrames
.Erase( pNode
);
747 pFFrm
->Show( false );
748 pFFrm
->Destroy(); break;
751 pNode
= pNode
->GetNext();
754 // FOR NOW:: excessive!
755 //if ( mpFrameClient ) mpFrameClient->Refresh();
757 mClientWndRefreshPending
= true;
761 if ( pBar
->mDimInfo
.GetDimHandler() )
763 pBar
->mDimInfo
.GetDimHandler()->OnChangeBarState( pBar
, newState
);
766 pBar
->mState
= newState
;
768 DoSetBarState( pBar
);
774 GetUpdatesManager().OnFinishChanges();
775 GetUpdatesManager().UpdateNow();
779 void wxFrameLayout::InverseVisibility( cbBarInfo
* pBar
)
781 wxASSERT( pBar
); // DBG::
783 // "inverse" bar-visibility of the selected bar
787 if ( pBar
->mState
== wxCBAR_HIDDEN
)
789 if ( pBar
->mAlignment
== -1 )
791 pBar
->mAlignment
= 0; // just remove "-1" marking
792 newState
= wxCBAR_FLOATING
;
795 if ( pBar
->mAlignment
== FL_ALIGN_TOP
||
796 pBar
->mAlignment
== FL_ALIGN_BOTTOM
)
798 newState
= wxCBAR_DOCKED_HORIZONTALLY
;
800 newState
= wxCBAR_DOCKED_VERTICALLY
;
804 newState
= wxCBAR_HIDDEN
;
806 if ( pBar
->mState
== wxCBAR_FLOATING
)
808 pBar
->mAlignment
= -1;
811 this->SetBarState( pBar
, newState
, true );
813 if ( newState
== wxCBAR_FLOATING
)
815 this->RepositionFloatedBar( pBar
);
818 void wxFrameLayout::ApplyBarProperties( cbBarInfo
* pBar
)
820 if ( pBar
->mState
== wxCBAR_FLOATING
)
822 RepositionFloatedBar( pBar
);
825 if ( pBar
->mState
== wxCBAR_DOCKED_HORIZONTALLY
||
826 pBar
->mState
== wxCBAR_DOCKED_VERTICALLY
834 void wxFrameLayout::RepositionFloatedBar( cbBarInfo
* pBar
)
836 if ( !(mFloatingOn
&& pBar
->mFloatingOn
)) return;
838 wxObjectList::compatibility_iterator pNode
= mFloatedFrames
.GetFirst();
842 cbFloatedBarWindow
* pFFrm
= ((cbFloatedBarWindow
*)pNode
->GetData());
844 if ( pFFrm
->GetBar() == pBar
)
846 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
851 GetParentFrame().ClientToScreen( &x
, &y
);
853 pFFrm
->PositionFloatedWnd( x
,y
,
860 pNode
= pNode
->GetNext();
864 void wxFrameLayout::DoSetBarState( cbBarInfo
* pBar
)
866 if ( pBar
->mState
!= wxCBAR_FLOATING
&&
867 pBar
->mState
!= wxCBAR_HIDDEN
)
871 mPanes
[pBar
->mAlignment
]->InsertBar( pBar
);
873 if ( pBar
->mState
== wxCBAR_HIDDEN
)
877 if ( pBar
->mpBarWnd
)
879 pBar
->mpBarWnd
->Show( false );
883 if ( !(mFloatingOn
&& pBar
->mFloatingOn
) )
888 if ( pBar
->mpBarWnd
== NULL
|| !CanReparent() )
890 // FOR NOW:: just hide it
892 if ( pBar
->mpBarWnd
)
894 pBar
->mpBarWnd
->Show( false );
896 pBar
->mState
= wxCBAR_HIDDEN
;
901 cbFloatedBarWindow
* pMiniFrm
= new cbFloatedBarWindow();
903 pMiniFrm
->SetBar( pBar
);
904 pMiniFrm
->SetLayout( this );
906 pMiniFrm
->Create( &GetParentFrame(), wxID_ANY
, pBar
->mName
,
909 wxFRAME_FLOAT_ON_PARENT
|
914 pMiniFrm
->SetClient( pBar
->mpBarWnd
);
916 ReparentWindow( pBar
->mpBarWnd
, pMiniFrm
);
918 mFloatedFrames
.Append( pMiniFrm
);
920 wxRect
& bounds
= pBar
->mDimInfo
.mBounds
[wxCBAR_FLOATING
];
922 // check if it wasn't floated anytime before
924 if ( bounds
.width
== -1 )
926 wxRect
& clntRect
= GetClientRect();
928 // adjust position into which the next floated bar will be placed
930 if ( mNextFloatedWndPos
.x
+ bounds
.width
> clntRect
.width
)
932 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
934 if ( mNextFloatedWndPos
.y
+ bounds
.height
> clntRect
.height
)
936 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
938 bounds
.x
= mNextFloatedWndPos
.x
+ clntRect
.x
;
939 bounds
.y
= mNextFloatedWndPos
.y
+ clntRect
.y
;
941 bounds
.width
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].x
;
942 bounds
.height
= pBar
->mDimInfo
.mSizes
[wxCBAR_FLOATING
].y
;
944 mNextFloatedWndPos
.x
+= mFloatingPosStep
.x
;
945 mNextFloatedWndPos
.y
+= mFloatingPosStep
.y
;
948 pMiniFrm
->Show( true );
949 RepositionFloatedBar(pMiniFrm
->GetBar());
951 // FIXME:: this is excessive
952 pBar
->mpBarWnd
->Show(true);
956 void wxFrameLayout::RemoveBar( cbBarInfo
* pBarInfo
)
958 // first, try to "guess" what was the perviouse state of the bar
963 if ( LocateBar( pBarInfo
, &pRow
, &pPane
) )
965 // ...aha, bar was docked into one of the panes,
966 // remove it from there
968 pPane
->RemoveBar( pBarInfo
);
972 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
974 if ( mAllBars
[i
] == pBarInfo
)
976 #if wxCHECK_VERSION(2,3,2)
977 mAllBars
.RemoveAt(i
);
981 if ( pBarInfo
->mpBarWnd
) // hides it's window
983 pBarInfo
->mpBarWnd
->Show( false );
990 wxFAIL_MSG(wxT("bar info should be present in the list of all bars of all panes"));
993 bool wxFrameLayout::LocateBar( cbBarInfo
* pBarInfo
,
995 cbDockPane
** ppPane
)
1001 for ( n
= 0; n
!= MAX_PANES
; ++n
)
1003 wxBarIterator
i( mPanes
[n
]->GetRowList() );
1007 if ( &i
.BarInfo() == pBarInfo
)
1009 (*ppPane
) = mPanes
[n
];
1010 (*ppRow
) = &i
.RowInfo();
1019 void wxFrameLayout::RecalcLayout( bool repositionBarsNow
)
1021 mRecalcPending
= false;
1023 int frmWidth
, frmHeight
;
1024 mpFrame
->GetClientSize( &frmWidth
, &frmHeight
);
1030 // pane positioning priorities in decreasing order:
1031 // top, bottom, left, right
1035 cbDockPane
* pPane
= mPanes
[ FL_ALIGN_TOP
];
1037 pPane
->SetPaneWidth( frmWidth
);
1038 pPane
->RecalcLayout();
1040 int paneHeight
= pPane
->GetPaneHeight();
1044 rect
.width
= frmWidth
;
1045 rect
.height
= wxMin( paneHeight
, frmHeight
- curY
);
1047 pPane
->SetBoundsInParent( rect
);
1051 // setup BOTTOM pane
1053 pPane
= mPanes
[ FL_ALIGN_BOTTOM
];
1055 pPane
->SetPaneWidth( frmWidth
);
1056 pPane
->RecalcLayout();
1058 paneHeight
= pPane
->GetPaneHeight();
1061 rect
.y
= wxMax( frmHeight
- paneHeight
, curY
);
1062 rect
.width
= frmWidth
;
1063 rect
.height
= frmHeight
- rect
.y
;
1065 pPane
->SetBoundsInParent( rect
);
1069 pPane
= mPanes
[ FL_ALIGN_LEFT
];
1072 pPane
->SetPaneWidth( rect
.y
- curY
);
1074 pPane
->RecalcLayout();
1075 paneHeight
= pPane
->GetPaneHeight();
1078 rect
.height
= rect
.y
- curY
;
1081 rect
.width
= wxMin( paneHeight
, frmWidth
);
1083 pPane
->SetBoundsInParent( rect
);
1089 pPane
= mPanes
[ FL_ALIGN_RIGHT
];
1091 // left pane's height
1092 pPane
->SetPaneWidth( rect
.height
);
1094 pPane
->RecalcLayout();
1095 paneHeight
= pPane
->GetPaneHeight();
1097 // left pane's height
1098 rect
.height
= rect
.height
;
1099 rect
.x
= wxMax( frmWidth
- paneHeight
, curX
);
1101 rect
.width
= frmWidth
- rect
.x
;
1103 pPane
->SetBoundsInParent( rect
);
1105 // recalc bounds of the client-window
1107 mClntWndBounds
.x
= mPanes
[FL_ALIGN_LEFT
]->mBoundsInParent
.x
+
1108 mPanes
[FL_ALIGN_LEFT
]->mBoundsInParent
.width
;
1109 mClntWndBounds
.y
= mPanes
[FL_ALIGN_TOP
]->mBoundsInParent
.y
+
1110 mPanes
[FL_ALIGN_TOP
]->mBoundsInParent
.height
;
1112 mClntWndBounds
.width
= mPanes
[FL_ALIGN_RIGHT
]->mBoundsInParent
.x
-
1114 mClntWndBounds
.height
= mPanes
[FL_ALIGN_BOTTOM
]->mBoundsInParent
.y
-
1117 if ( repositionBarsNow
)
1122 int wxFrameLayout::GetClientHeight()
1124 // for better portablility wxWindow::GetSzie() is not used here
1126 return mClntWndBounds
.height
;
1129 int wxFrameLayout::GetClientWidth()
1131 // for better portablility wxWindow::GetSzie() is not used here
1133 return mClntWndBounds
.width
;
1136 void wxFrameLayout::PositionClientWindow()
1138 if ( mpFrameClient
)
1140 if ( mClntWndBounds
.width
>= 1 && mClntWndBounds
.height
>= 1 )
1142 mpFrameClient
->SetSize( mClntWndBounds
.x
, mClntWndBounds
.y
,
1143 mClntWndBounds
.width
, mClntWndBounds
.height
, 0 );
1145 if ( !mpFrameClient
->IsShown() )
1147 mpFrameClient
->Show( true );
1150 mpFrameClient
->Show( false );
1154 void wxFrameLayout::PositionPanes()
1156 PositionClientWindow();
1158 // FOR NOW:: excessive updates!
1159 // reposition bars within all panes
1162 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1163 mPanes
[i
]->SizePaneObjects();
1166 void wxFrameLayout::OnSize( wxSizeEvent
& event
)
1168 mpFrame
->ProcessEvent( event
);
1169 event
.Skip( false ); // stop its progpagation
1171 if ( event
.GetEventObject() == (wxObject
*) mpFrame
)
1173 GetUpdatesManager().OnStartChanges();
1175 GetUpdatesManager().OnFinishChanges();
1176 GetUpdatesManager().UpdateNow();
1181 /*** protected members ***/
1183 void wxFrameLayout::HideBarWindows()
1186 for ( i
= 0; i
!= mAllBars
.Count(); ++i
)
1187 if ( mAllBars
[i
]->mpBarWnd
&& mAllBars
[i
]->mState
!= wxCBAR_FLOATING
)
1188 mAllBars
[i
]->mpBarWnd
->Show( false );
1190 // then floated frames
1192 ShowFloatedWindows( false );
1194 if ( mpFrameClient
)
1196 mpFrameClient
->Show( false );
1199 void wxFrameLayout::UnhookFromFrame()
1201 // NOTE:: the SetEvtHandlerEnabled() method is not used
1202 // here, since it is assumed that unhooking layout
1203 // from window may result destroying of the layout itself
1205 // BUG BUG BUG (wx):: this would not be a problem if
1206 // wxEvtHandler's destructor checked if
1207 // this handler is currently the top-most
1208 // handler of some window, and additionally
1209 // to the reconnecting itself from the chain.
1210 // It would also re-setup current event handler
1211 // of the window using wxWindow::SetEventHandler()
1215 if ( mpFrame
->GetEventHandler() == this )
1217 mpFrame
->PopEventHandler();
1223 if ( this == mpFrame
->GetEventHandler() )
1225 mpFrame
->SetEventHandler( this->GetNextHandler() );
1229 wxEvtHandler
* pCur
= mpFrame
->GetEventHandler();
1236 pCur
= pCur
->GetNextHandler();
1239 // do not try to unhook ourselves if we're not hooked yet
1244 if ( GetPreviousHandler() )
1245 GetPreviousHandler()->SetNextHandler( GetNextHandler() );
1248 mpFrame
->PopEventHandler();
1252 if ( GetNextHandler() )
1253 GetNextHandler()->SetPreviousHandler( GetPreviousHandler() );
1255 SetNextHandler( NULL
);
1256 SetPreviousHandler( NULL
);
1260 void wxFrameLayout::HookUpToFrame()
1262 // unhook us first, we're already hooked up
1266 // put ourselves on top
1268 mpFrame
->PushEventHandler( this );
1271 cbDockPane
* wxFrameLayout::GetBarPane( cbBarInfo
* pBar
)
1274 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1275 if ( mPanes
[i
]->BarPresent( pBar
) )
1281 void wxFrameLayout::CreateCursors()
1284 // FIXME:: The below code somehow doesn't work - cursors remain unchanged
1287 set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
1289 mpHorizCursor = new wxCursor( bits, 32, 16 );
1291 set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
1293 mpVertCursor = new wxCursor( bits, 32, 16 );
1296 // FOR NOW:: use standard ones
1298 mpHorizCursor
= new wxCursor(wxCURSOR_SIZEWE
);
1299 mpVertCursor
= new wxCursor(wxCURSOR_SIZENS
);
1300 mpNormalCursor
= new wxCursor(wxCURSOR_ARROW
);
1301 mpDragCursor
= new wxCursor(wxCURSOR_CROSS
);
1302 mpNECursor
= new wxCursor(wxCURSOR_NO_ENTRY
);
1304 mFloatingPosStep
.x
= 25;
1305 mFloatingPosStep
.y
= 25;
1307 mNextFloatedWndPos
.x
= mFloatingPosStep
.x
;
1308 mNextFloatedWndPos
.y
= mFloatingPosStep
.y
;
1311 bool wxFrameLayout::HitTestPane( cbDockPane
* pPane
, int x
, int y
)
1313 return rect_contains_point( pPane
->GetRealRect(), x
, y
);
1316 cbDockPane
* wxFrameLayout::HitTestPanes( const wxRect
& rect
,
1317 cbDockPane
* pCurPane
)
1319 // first, give the privilege to the current pane
1321 if ( pCurPane
&& rect_hits_rect( pCurPane
->GetRealRect(), rect
) )
1326 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1328 if ( pCurPane
!= mPanes
[i
] &&
1329 rect_hits_rect( mPanes
[i
]->GetRealRect(), rect
) )
1337 void wxFrameLayout::ForwardMouseEvent( wxMouseEvent
& event
,
1338 cbDockPane
* pToPane
,
1341 wxPoint
pos( event
.m_x
, event
.m_y
);
1342 pToPane
->FrameToPane( &pos
.x
, &pos
.y
);
1344 if ( eventType
== cbEVT_PL_LEFT_DOWN
)
1346 cbLeftDownEvent
evt( pos
, pToPane
);
1347 FirePluginEvent( evt
);
1349 else if ( eventType
== cbEVT_PL_LEFT_DCLICK
)
1351 cbLeftDClickEvent
evt( pos
, pToPane
);
1352 FirePluginEvent( evt
);
1354 else if ( eventType
== cbEVT_PL_LEFT_UP
)
1356 cbLeftUpEvent
evt( pos
, pToPane
);
1357 FirePluginEvent( evt
);
1359 else if ( eventType
== cbEVT_PL_RIGHT_DOWN
)
1361 cbRightDownEvent
evt( pos
, pToPane
);
1362 FirePluginEvent( evt
);
1364 else if ( eventType
== cbEVT_PL_RIGHT_UP
)
1366 cbRightUpEvent
evt( pos
, pToPane
);
1367 FirePluginEvent( evt
);
1369 else if ( eventType
== cbEVT_PL_MOTION
)
1371 cbMotionEvent
evt( pos
, pToPane
);
1372 FirePluginEvent( evt
);
1374 } // wxFrameLayout::ForwardMouseEvent()
1377 void wxFrameLayout::RouteMouseEvent( wxMouseEvent
& event
, int pluginEvtType
)
1379 if ( mpPaneInFocus
)
1381 ForwardMouseEvent( event
, mpPaneInFocus
, pluginEvtType
);
1385 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1387 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1389 ForwardMouseEvent( event
, mPanes
[i
], pluginEvtType
);
1396 /*** event handlers ***/
1398 void wxFrameLayout::OnRButtonDown( wxMouseEvent
& event
)
1400 RouteMouseEvent( event
, cbEVT_PL_RIGHT_DOWN
);
1403 void wxFrameLayout::OnRButtonUp( wxMouseEvent
& event
)
1405 RouteMouseEvent( event
, cbEVT_PL_RIGHT_UP
);
1408 void wxFrameLayout::OnLButtonDown( wxMouseEvent
& event
)
1410 RouteMouseEvent( event
, cbEVT_PL_LEFT_DOWN
);
1413 void wxFrameLayout::OnLDblClick( wxMouseEvent
& event
)
1415 RouteMouseEvent( event
, cbEVT_PL_LEFT_DCLICK
);
1418 void wxFrameLayout::OnLButtonUp( wxMouseEvent
& event
)
1420 RouteMouseEvent( event
, cbEVT_PL_LEFT_UP
);
1423 void wxFrameLayout::OnMouseMove( wxMouseEvent
& event
)
1425 if ( mpPaneInFocus
)
1427 ForwardMouseEvent( event
, mpPaneInFocus
, cbEVT_PL_MOTION
);
1431 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1433 if ( HitTestPane( mPanes
[i
], event
.m_x
, event
.m_y
) )
1435 if ( mpLRUPane
&& mpLRUPane
!= mPanes
[i
] )
1437 // simulate "mouse-leave" event
1438 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1441 ForwardMouseEvent( event
, mPanes
[i
], cbEVT_PL_MOTION
);
1443 mpLRUPane
= mPanes
[i
];
1452 // simulate "mouse-leave" event
1453 ForwardMouseEvent( event
, mpLRUPane
, cbEVT_PL_MOTION
);
1458 void wxFrameLayout::OnPaint( wxPaintEvent
& event
)
1460 if ( mRecalcPending
)
1461 RecalcLayout( true );
1463 wxPaintDC
dc(mpFrame
);
1466 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1468 wxRect
& rect
= mPanes
[i
]->mBoundsInParent
;
1470 dc
.SetClippingRegion( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1472 mPanes
[i
]->PaintPane(dc
);
1474 dc
.DestroyClippingRegion();
1480 void wxFrameLayout::OnEraseBackground( wxEraseEvent
& WXUNUSED(event
) )
1485 void wxFrameLayout::OnIdle( wxIdleEvent
& event
)
1487 wxWindow
* focus
= wxWindow::FindFocus();
1489 if ( !focus
&& mCheckFocusWhenIdle
)
1491 wxMessageBox(wxT("Hi, no more focus in this app!"));
1493 mCheckFocusWhenIdle
= false;
1494 //ShowFloatedWindows( false );
1497 mCheckFocusWhenIdle
= false;
1502 void wxFrameLayout::GetPaneProperties( cbCommonPaneProperties
& props
, int alignment
)
1504 props
= mPanes
[alignment
]->mProps
;
1507 void wxFrameLayout::SetPaneProperties( const cbCommonPaneProperties
& props
, int paneMask
)
1510 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1512 if ( mPanes
[i
]->MatchesMask( paneMask
) )
1513 mPanes
[i
]->mProps
= props
;
1517 void wxFrameLayout::SetMargins( int top
, int bottom
, int left
, int right
,
1521 for ( i
= 0; i
!= MAX_PANES
; ++i
)
1523 cbDockPane
& pane
= *mPanes
[i
];
1525 if ( pane
.MatchesMask( paneMask
) )
1527 pane
.mTopMargin
= top
;
1528 pane
.mBottomMargin
= bottom
;
1529 pane
.mLeftMargin
= left
;
1530 pane
.mRightMargin
= right
;
1535 void wxFrameLayout::SetPaneBackground( const wxColour
& colour
)
1537 mBorderPen
.SetColour( colour
);
1540 void wxFrameLayout::RefreshNow( bool recalcLayout
)
1543 RecalcLayout( true );
1549 /*** plugin-related methods ***/
1551 void wxFrameLayout::FirePluginEvent( cbPluginEvent
& event
)
1553 // check state of input capture, before processing the event
1555 if ( mpCaputesInput
)
1557 bool isInputEvt
= true;
1558 #if wxCHECK_VERSION(2,3,0)
1559 if ( event
.GetEventType() != cbEVT_PL_LEFT_DOWN
&&
1560 event
.GetEventType() != cbEVT_PL_LEFT_UP
&&
1561 event
.GetEventType() != cbEVT_PL_RIGHT_DOWN
&&
1562 event
.GetEventType() != cbEVT_PL_RIGHT_UP
&&
1563 event
.GetEventType() != cbEVT_PL_MOTION
)
1566 switch ( event
.m_eventType
)
1568 case cbEVT_PL_LEFT_DOWN
: break;
1569 case cbEVT_PL_LEFT_UP
: break;
1570 case cbEVT_PL_RIGHT_DOWN
: break;
1571 case cbEVT_PL_RIGHT_UP
: break;
1572 case cbEVT_PL_MOTION
: break;
1574 default : isInputEvt
= false; break;
1576 #endif // #if wxCHECK_VERSION(2,3,0)
1580 mpCaputesInput
->ProcessEvent( event
);
1585 GetTopPlugin().ProcessEvent( event
);
1588 void wxFrameLayout::CaptureEventsForPlugin ( cbPluginBase
* pPlugin
)
1590 // cannot capture events for more than one plugin at a time
1591 wxASSERT( mpCaputesInput
== NULL
);
1593 mpCaputesInput
= pPlugin
;
1597 void wxFrameLayout::ReleaseEventsFromPlugin( cbPluginBase
* WXUNUSED(pPlugin
) )
1599 // events should be captured first
1600 wxASSERT( mpCaputesInput
!= NULL
);
1602 mpCaputesInput
= NULL
;
1605 void wxFrameLayout::CaptureEventsForPane( cbDockPane
* toPane
)
1607 // cannot capture events twice (without releasing)
1608 wxASSERT( mpPaneInFocus
== NULL
);
1610 mpFrame
->CaptureMouse();
1612 mpPaneInFocus
= toPane
;
1615 void wxFrameLayout::ReleaseEventsFromPane( cbDockPane
* WXUNUSED(fromPane
) )
1617 // cannot release events without capturing them
1618 wxASSERT( mpPaneInFocus
!= NULL
);
1620 mpFrame
->ReleaseMouse();
1622 mpPaneInFocus
= NULL
;
1625 cbPluginBase
& wxFrameLayout::GetTopPlugin()
1629 PushDefaultPlugins(); // automatic configuration
1631 return *mpTopPlugin
;
1634 void wxFrameLayout::SetTopPlugin( cbPluginBase
* pPlugin
)
1636 mpTopPlugin
= pPlugin
;
1639 bool wxFrameLayout::HasTopPlugin()
1641 return ( mpTopPlugin
!= NULL
);
1644 void wxFrameLayout::PushPlugin( cbPluginBase
* pPlugin
)
1648 mpTopPlugin
= pPlugin
;
1651 pPlugin
->SetNextHandler( mpTopPlugin
);
1653 mpTopPlugin
->SetPreviousHandler( pPlugin
);
1655 mpTopPlugin
= pPlugin
;
1658 mpTopPlugin
->OnInitPlugin(); // notification
1661 void wxFrameLayout::PopPlugin()
1663 wxASSERT( mpTopPlugin
); // DBG:: at least one plugin should be present
1665 cbPluginBase
* pPopped
= mpTopPlugin
;
1667 mpTopPlugin
= (cbPluginBase
*)mpTopPlugin
->GetNextHandler();
1672 void wxFrameLayout::PopAllPlugins()
1674 while( mpTopPlugin
) PopPlugin();
1677 void wxFrameLayout::PushDefaultPlugins()
1679 // FIXME:: to much of the stuff for the default...
1681 AddPlugin( CLASSINFO( cbRowLayoutPlugin
) );
1682 AddPlugin( CLASSINFO( cbBarDragPlugin
) );
1683 AddPlugin( CLASSINFO( cbPaneDrawPlugin
) );
1686 void wxFrameLayout::AddPlugin( wxClassInfo
* pPlInfo
, int paneMask
)
1688 if ( FindPlugin ( pPlInfo
) ) return; // same type of plugin cannot be added twice
1690 cbPluginBase
* pObj
= (cbPluginBase
*)pPlInfo
->CreateObject();
1692 wxASSERT(pObj
); // DBG:: plugin's class should be dynamic
1694 pObj
->mPaneMask
= paneMask
;
1695 pObj
->mpLayout
= this;
1700 void wxFrameLayout::AddPluginBefore( wxClassInfo
* pNextPlInfo
, wxClassInfo
* pPlInfo
,
1703 wxASSERT( pNextPlInfo
!= pPlInfo
); // DBG:: no sense
1705 cbPluginBase
* pNextPl
= FindPlugin( pNextPlInfo
);
1709 AddPlugin( pPlInfo
, paneMask
);
1714 // remove existing one if present
1716 cbPluginBase
* pExistingPl
= FindPlugin( pPlInfo
);
1718 if ( pExistingPl
) RemovePlugin( pPlInfo
);
1720 // create an instance
1722 cbPluginBase
* pNewPl
= (cbPluginBase
*)pPlInfo
->CreateObject();
1724 wxASSERT(pNewPl
); // DBG:: plugin's class should be dynamic
1726 // insert it to the chain
1728 if ( pNextPl
->GetPreviousHandler() )
1729 pNextPl
->GetPreviousHandler()->SetNextHandler( pNewPl
);
1731 mpTopPlugin
= pNewPl
;
1733 pNewPl
->SetNextHandler( pNextPl
);
1735 pNewPl
->SetPreviousHandler( pNextPl
->GetPreviousHandler() );
1737 pNextPl
->SetPreviousHandler( pNewPl
);
1741 pNewPl
->mPaneMask
= paneMask
;
1742 pNewPl
->mpLayout
= this;
1744 pNewPl
->OnInitPlugin();
1747 void wxFrameLayout::RemovePlugin( wxClassInfo
* pPlInfo
)
1749 cbPluginBase
* pPlugin
= FindPlugin( pPlInfo
);
1751 if ( !pPlugin
) return; // it's OK to remove not-existing plugin ;-)
1753 if ( pPlugin
->GetPreviousHandler() == NULL
)
1755 mpTopPlugin
= (cbPluginBase
*)pPlugin
->GetNextHandler();
1760 cbPluginBase
* wxFrameLayout::FindPlugin( wxClassInfo
* pPlInfo
)
1762 cbPluginBase
*pCur
= mpTopPlugin
;
1766 // NOTE:: it might appear useful matching plugin
1767 // classes "polymorphically":
1769 if ( pCur
->GetClassInfo()->IsKindOf( pPlInfo
) )
1773 pCur
= (cbPluginBase
*)pCur
->GetNextHandler();
1779 /***** Implementation for class cbUpdateMgrData *****/
1781 IMPLEMENT_DYNAMIC_CLASS( cbUpdateMgrData
, wxObject
)
1783 cbUpdateMgrData::cbUpdateMgrData()
1785 : mPrevBounds( -1,-1,0,0 ),
1786 mIsDirty( true ), // inidicate initial change
1790 void cbUpdateMgrData::StoreItemState( const wxRect
& boundsInParent
)
1792 mPrevBounds
= boundsInParent
;
1795 void cbUpdateMgrData::SetDirty( bool isDirty
)
1800 void cbUpdateMgrData::SetCustomData( wxObject
* pCustomData
)
1802 mpCustomData
= pCustomData
;
1805 /***** Implementation for class cbDockPane *****/
1807 void wxBarIterator::Reset()
1809 mpRow
= ( mpRows
->Count() ) ? (*mpRows
)[0] : NULL
;
1813 wxBarIterator::wxBarIterator( RowArrayT
& rows
)
1822 bool wxBarIterator::Next()
1827 mpBar
= mpBar
->mpNext
;
1830 if ( mpRow
->mBars
.GetCount() == 0 )
1835 mpBar
= mpRow
->mBars
[0];
1840 // skip to the next row
1842 mpRow
= mpRow
->mpNext
;
1845 mpBar
= mpRow
->mBars
[0];
1856 cbBarInfo
& wxBarIterator::BarInfo()
1861 cbRowInfo
& wxBarIterator::RowInfo()
1866 /***** Implementation for class cbBarDimHandlerBase *****/
1868 IMPLEMENT_ABSTRACT_CLASS( cbBarDimHandlerBase
, wxObject
)
1870 cbBarDimHandlerBase::cbBarDimHandlerBase()
1874 void cbBarDimHandlerBase::AddRef()
1879 void cbBarDimHandlerBase::RemoveRef()
1881 if ( --mRefCount
<= 0 ) delete this;
1884 /***** Implementation for class cbDimInfo *****/
1886 IMPLEMENT_DYNAMIC_CLASS( cbDimInfo
, wxObject
)
1888 cbDimInfo::cbDimInfo()
1897 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1902 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1906 cbDimInfo::cbDimInfo( cbBarDimHandlerBase
* pDimHandler
,
1911 mIsFixed ( isFixed
),
1913 mpHandler( pDimHandler
)
1917 // int vtad = *((int*)mpHandler);
1918 mpHandler
->AddRef();
1922 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1927 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1931 cbDimInfo::cbDimInfo( int dh_x
, int dh_y
,
1939 cbBarDimHandlerBase
* pDimHandler
1941 : mVertGap ( vertGap
),
1942 mHorizGap ( horizGap
),
1943 mIsFixed ( isFixed
),
1944 mpHandler( pDimHandler
)
1948 // int vtad = *((int*)mpHandler);
1949 mpHandler
->AddRef();
1952 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= dh_x
;
1953 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= dh_y
;
1954 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= dv_x
;
1955 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= dv_y
;
1956 mSizes
[wxCBAR_FLOATING
].x
= f_x
;
1957 mSizes
[wxCBAR_FLOATING
].y
= f_y
;
1960 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1961 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1964 cbDimInfo::cbDimInfo( int x
, int y
,
1965 bool isFixed
, int gap
,
1966 cbBarDimHandlerBase
* pDimHandler
)
1969 mIsFixed ( isFixed
),
1970 mpHandler( pDimHandler
)
1974 // int vtad = *((int*)mpHandler);
1975 mpHandler
->AddRef();
1978 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].x
= x
;
1979 mSizes
[wxCBAR_DOCKED_HORIZONTALLY
].y
= y
;
1980 mSizes
[wxCBAR_DOCKED_VERTICALLY
].x
= x
;
1981 mSizes
[wxCBAR_DOCKED_VERTICALLY
].y
= y
;
1982 mSizes
[wxCBAR_FLOATING
].x
= x
;
1983 mSizes
[wxCBAR_FLOATING
].y
= y
;
1986 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
1987 mBounds
[i
] = wxRect( -1,-1,-1,-1 );
1990 cbDimInfo::~cbDimInfo()
1994 mpHandler
->RemoveRef();
1997 const cbDimInfo
& cbDimInfo::operator=( const cbDimInfo
& other
)
1999 if ( this == &other
)
2003 for ( i
= 0; i
!= MAX_BAR_STATES
; ++i
)
2004 mSizes
[i
] = other
.mSizes
[i
];
2006 mIsFixed
= other
.mIsFixed
;
2007 mpHandler
= other
.mpHandler
;
2009 mVertGap
= other
.mVertGap
;
2010 mHorizGap
= other
.mHorizGap
;
2014 mpHandler
->AddRef();
2019 /***** Implementation for structure cbCommonPaneProperties *****/
2021 IMPLEMENT_DYNAMIC_CLASS( cbCommonPaneProperties
, wxObject
)
2023 cbCommonPaneProperties::cbCommonPaneProperties(void)
2025 : mRealTimeUpdatesOn ( true ),
2026 mOutOfPaneDragOn ( true ),
2027 mExactDockPredictionOn( false ),
2028 mNonDestructFrictionOn( false ),
2029 mShow3DPaneBorderOn ( true ),
2030 mBarFloatingOn ( false ),
2031 mRowProportionsOn ( false ),
2032 mColProportionsOn ( true ),
2033 mBarCollapseIconsOn ( false ),
2034 mBarDragHintsOn ( false ),
2036 mMinCBarDim( 16, 16 ),
2037 mResizeHandleSize( 4 )
2040 cbCommonPaneProperties::cbCommonPaneProperties(const cbCommonPaneProperties
& props
)
2043 mRealTimeUpdatesOn (props
.mRealTimeUpdatesOn
),
2044 mOutOfPaneDragOn (props
.mOutOfPaneDragOn
),
2045 mExactDockPredictionOn(props
.mExactDockPredictionOn
),
2046 mNonDestructFrictionOn(props
.mNonDestructFrictionOn
),
2047 mShow3DPaneBorderOn (props
.mShow3DPaneBorderOn
),
2048 mBarFloatingOn (props
.mBarFloatingOn
),
2049 mRowProportionsOn (props
.mRowProportionsOn
),
2050 mColProportionsOn (props
.mColProportionsOn
),
2051 mBarCollapseIconsOn (props
.mBarCollapseIconsOn
),
2052 mBarDragHintsOn (props
.mBarDragHintsOn
),
2054 mMinCBarDim(props
.mMinCBarDim
),
2055 mResizeHandleSize(props
.mResizeHandleSize
)
2058 cbCommonPaneProperties
& cbCommonPaneProperties::operator=(const cbCommonPaneProperties
& props
)
2060 mRealTimeUpdatesOn
= props
.mRealTimeUpdatesOn
;
2061 mOutOfPaneDragOn
= props
.mOutOfPaneDragOn
;
2062 mExactDockPredictionOn
= props
.mExactDockPredictionOn
;
2063 mNonDestructFrictionOn
= props
.mNonDestructFrictionOn
;
2064 mShow3DPaneBorderOn
= props
.mShow3DPaneBorderOn
;
2065 mBarFloatingOn
= props
.mBarFloatingOn
;
2066 mRowProportionsOn
= props
.mRowProportionsOn
;
2067 mColProportionsOn
= props
.mColProportionsOn
;
2068 mBarCollapseIconsOn
= props
.mBarCollapseIconsOn
;
2069 mBarDragHintsOn
= props
.mBarDragHintsOn
;
2071 mMinCBarDim
= props
.mMinCBarDim
;
2072 mResizeHandleSize
= props
.mResizeHandleSize
;
2077 /***** Implementation for class cbRowInfo *****/
2079 IMPLEMENT_DYNAMIC_CLASS( cbRowInfo
, wxObject
)
2081 cbRowInfo::cbRowInfo(void)
2083 : mNotFixedBarsCnt( false ),
2086 mpExpandedBar ( NULL
)
2089 cbRowInfo::~cbRowInfo()
2091 // nothing! all bars are removed using global bar
2092 // list in wxFrameLayout class
2095 /***** Implementation for class cbBarInfo *****/
2097 IMPLEMENT_DYNAMIC_CLASS( cbBarInfo
, wxObject
)
2099 cbBarInfo::cbBarInfo(void)
2102 mFloatingOn( true ),
2107 cbBarInfo::~cbBarInfo()
2112 /***** Implementation for class cbDockPane *****/
2114 IMPLEMENT_DYNAMIC_CLASS( cbDockPane
, wxObject
)
2116 // FIXME:: how to eliminate these cut&pasted constructors?
2118 cbDockPane::cbDockPane(void)
2119 : mLeftMargin ( 1 ),
2123 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2124 // since the real dimensions of the pane may not
2125 // be known, while inserting bars initially
2126 mPaneHeight( 32768 ),
2132 cbDockPane::cbDockPane( int alignment
, wxFrameLayout
* pPanel
)
2134 : mLeftMargin ( 1 ),
2138 mPaneWidth ( 32768 ), // fake-up very large pane dims,
2139 // since the real dimensions of the pane may not
2140 // be known, while inserting bars initially
2141 mPaneHeight( 32768 ),
2142 mAlignment ( alignment
),
2143 mpLayout ( pPanel
),
2147 cbDockPane::~cbDockPane()
2150 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2153 WX_CLEAR_LIST(wxList
,mRowShapeData
)
2155 // NOTE:: control bar infromation structures are cleaned-up
2156 // in wxFrameLayout's destructor, using global control-bar list
2159 void cbDockPane::SetMargins( int top
, int bottom
, int left
, int right
)
2162 mBottomMargin
= bottom
;
2164 mRightMargin
= right
;
2167 /*** helpers of cbDockPane ***/
2169 void cbDockPane::PaintBarDecorations( cbBarInfo
* pBar
, wxDC
& dc
)
2171 cbDrawBarDecorEvent
evt( pBar
, dc
, this );
2173 mpLayout
->FirePluginEvent( evt
);
2176 void cbDockPane::PaintBarHandles( cbBarInfo
* pBar
, wxDC
& dc
)
2178 cbDrawBarHandlesEvent
evt( pBar
, dc
, this );
2180 mpLayout
->FirePluginEvent( evt
);
2183 void cbDockPane::PaintBar( cbBarInfo
* pBar
, wxDC
& dc
)
2185 PaintBarDecorations( pBar
, dc
);
2186 PaintBarHandles( pBar
, dc
);
2189 void cbDockPane::PaintRowHandles( cbRowInfo
* pRow
, wxDC
& dc
)
2191 cbDrawRowHandlesEvent
evt( pRow
, dc
, this );
2193 mpLayout
->FirePluginEvent( evt
);
2195 cbDrawRowDecorEvent
evt1( pRow
, dc
, this );
2197 mpLayout
->FirePluginEvent( evt1
);
2200 void cbDockPane::PaintRowBackground ( cbRowInfo
* pRow
, wxDC
& dc
)
2202 cbDrawRowBkGroundEvent
evt( pRow
, dc
, this );
2204 mpLayout
->FirePluginEvent( evt
);
2207 void cbDockPane::PaintRowDecorations( cbRowInfo
* pRow
, wxDC
& dc
)
2211 // decorations first
2212 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2214 PaintBarDecorations( pRow
->mBars
[i
], dc
);
2216 // then handles if present
2217 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2219 PaintBarHandles( pRow
->mBars
[i
], dc
);
2222 void cbDockPane::PaintRow( cbRowInfo
* pRow
, wxDC
& dc
)
2224 PaintRowBackground ( pRow
, dc
);
2225 PaintRowDecorations( pRow
, dc
);
2226 PaintRowHandles ( pRow
, dc
);
2229 void cbDockPane::PaintPaneBackground( wxDC
& dc
)
2231 cbDrawPaneBkGroundEvent
evt( dc
, this );
2233 mpLayout
->FirePluginEvent( evt
);
2236 void cbDockPane::PaintPaneDecorations( wxDC
& dc
)
2238 cbDrawPaneDecorEvent
evt( dc
, this );
2240 mpLayout
->FirePluginEvent( evt
);
2243 void cbDockPane::PaintPane( wxDC
& dc
)
2247 PaintPaneBackground( dc
);
2249 // first decorations
2250 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2252 PaintRowBackground( mRows
[i
], dc
);
2253 PaintRowDecorations( mRows
[i
], dc
);
2257 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2258 PaintRowHandles( mRows
[i
], dc
);
2261 PaintPaneDecorations( dc
);
2264 void cbDockPane::SizeBar( cbBarInfo
* pBar
)
2266 cbSizeBarWndEvent
evt( pBar
, this );
2268 mpLayout
->FirePluginEvent( evt
);
2272 void cbDockPane::SizeRowObjects( cbRowInfo
* pRow
)
2275 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2276 SizeBar( pRow
->mBars
[i
] );
2279 void cbDockPane::SizePaneObjects()
2282 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2283 SizeRowObjects( mRows
[i
] );
2286 wxDC
* cbDockPane::StartDrawInArea( const wxRect
& area
)
2290 cbStartDrawInAreaEvent
evt( area
, &pDc
, this );
2292 mpLayout
->FirePluginEvent( evt
);
2297 void cbDockPane::FinishDrawInArea( const wxRect
& area
)
2299 cbFinishDrawInAreaEvent
evt( area
, this );
2301 mpLayout
->FirePluginEvent( evt
);
2304 bool cbDockPane::IsFixedSize( cbBarInfo
* pInfo
)
2306 return ( pInfo
->mDimInfo
.mIsFixed
);
2309 int cbDockPane::GetNotFixedBarsCount( cbRowInfo
* pRow
)
2314 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2316 if ( !pRow
->mBars
[i
]->IsFixed() )
2323 void cbDockPane::RemoveBar( cbBarInfo
* pBar
)
2325 bool needsRestoring
= mProps
.mNonDestructFrictionOn
&&
2326 mpStoredRow
== pBar
->mpRow
;
2328 cbRemoveBarEvent
evt( pBar
, this );
2330 mpLayout
->FirePluginEvent( evt
);
2332 if ( needsRestoring
)
2334 SetRowShapeData( mpStoredRow
, &mRowShapeData
);
2340 void cbDockPane::SyncRowFlags( cbRowInfo
* pRow
)
2342 // setup mHasOnlyFixedBars flag for the row information
2343 pRow
->mHasOnlyFixedBars
= true;
2345 pRow
->mNotFixedBarsCnt
= 0;
2348 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2350 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2354 if ( !bar
.IsFixed() )
2356 pRow
->mHasOnlyFixedBars
= false;
2357 ++pRow
->mNotFixedBarsCnt
;
2362 void cbDockPane::FrameToPane( 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
.y
;
2380 *y
= rx
- mBoundsInParent
.x
;
2384 void cbDockPane::PaneToFrame( int* x
, int* y
)
2386 if ( mAlignment
== FL_ALIGN_TOP
||
2387 mAlignment
== FL_ALIGN_BOTTOM
2390 *x
+= mBoundsInParent
.x
;
2391 *y
+= mBoundsInParent
.y
;
2395 int rx
= *x
, ry
= *y
;
2397 *x
= ry
+ mBoundsInParent
.x
;
2399 *y
= mBoundsInParent
.y
+ rx
;
2406 void cbDockPane::FrameToPane( wxRect
* pRect
)
2408 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2409 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2410 pRect
->y
+ pRect
->height
);
2412 FrameToPane( &upperLeft
.x
, &upperLeft
.y
);
2413 FrameToPane( &lowerRight
.x
, &lowerRight
.y
);
2415 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2416 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2418 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2419 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2422 void cbDockPane::PaneToFrame( wxRect
* pRect
)
2424 wxPoint
upperLeft ( pRect
->x
, pRect
->y
);
2425 wxPoint
lowerRight( pRect
->x
+ pRect
->width
,
2426 pRect
->y
+ pRect
->height
);
2428 PaneToFrame( &upperLeft
.x
, &upperLeft
.y
);
2429 PaneToFrame( &lowerRight
.x
, &lowerRight
.y
);
2431 //wxRect newRect = wxRect( upperLeft, lowerRight );
2433 pRect
->x
= wxMin(upperLeft
.x
,lowerRight
.x
);
2434 pRect
->y
= wxMin(upperLeft
.y
,lowerRight
.y
);
2436 pRect
->width
= abs( lowerRight
.x
- upperLeft
.x
);
2437 pRect
->height
= abs( lowerRight
.y
- upperLeft
.y
);
2440 int cbDockPane::GetRowAt( int paneY
)
2449 for ( ; i
!= mRows
.Count(); ++i
)
2451 int rowHeight
= mRows
[i
]->mRowHeight
;
2453 int third
= rowHeight
/3;
2455 if ( paneY
>= curY
&& paneY
< curY
+ third
)
2458 if ( paneY
>= curY
+ third
&& paneY
< curY
+ rowHeight
- third
)
2467 int cbDockPane::GetRowAt( int upperY
, int lowerY
)
2471 int range = lowerY - upperY;
2472 int oneThird = range / 3;
2474 wxNode* pRow = mRows.GetFirst();
2478 if ( lowerY <= 0 ) return -1;
2482 int rowHeight = GetRowHeight( (wxList*)pRow->GetData() );
2484 if ( upperY >= curY &&
2485 lowerY < curY ) return row;
2487 if ( upperY <= curY &&
2489 curY - upperY >= oneThird ) return row-1;
2491 if ( ( upperY < curY + rowHeight &&
2492 lowerY >= curY + rowHeight &&
2493 curY + rowHeight - lowerY >= oneThird )
2497 if ( lowerY <= curY + rowHeight ) return row;
2501 pRow = pRow->GetNext();
2505 int mid
= upperY
+ (lowerY
- upperY
)/2;
2513 for ( ; i
!= mRows
.Count(); ++i
)
2515 int rowHeight
= mRows
[i
]->mRowHeight
;
2517 if ( mid
>= curY
&& mid
< curY
+ rowHeight
) return i
;
2525 int cbDockPane::GetRowY( cbRowInfo
* pRow
)
2530 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2532 if ( mRows
[i
] == pRow
)
2535 curY
+= mRows
[i
]->mRowHeight
;
2541 bool cbDockPane::HasNotFixedRowsAbove( cbRowInfo
* pRow
)
2543 while ( pRow
->mpPrev
)
2545 pRow
= pRow
->mpPrev
;
2547 if ( pRow
->mHasOnlyFixedBars
)
2555 bool cbDockPane::HasNotFixedRowsBelow( cbRowInfo
* pRow
)
2557 while( pRow
->mpNext
)
2559 pRow
= pRow
->mpNext
;
2561 if ( pRow
->mHasOnlyFixedBars
)
2569 bool cbDockPane::HasNotFixedBarsLeft( cbBarInfo
* pBar
)
2571 while( pBar
->mpPrev
)
2573 pBar
= pBar
->mpPrev
;
2575 if ( pBar
->IsFixed() )
2583 bool cbDockPane::HasNotFixedBarsRight( cbBarInfo
* pBar
)
2585 while( pBar
->mpNext
)
2587 pBar
= pBar
->mpNext
;
2589 if ( pBar
->IsFixed() )
2597 void cbDockPane::CalcLengthRatios( cbRowInfo
* pInRow
)
2603 // calc current-maximal-total-length of all maximized bars
2605 for ( i
= 0; i
!= pInRow
->mBars
.GetCount(); ++i
)
2607 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2609 if ( !bar
.IsFixed() )
2610 totalWidth
+= bar
.mBounds
.width
;
2613 // set up percentages of occupied space for each maximized bar
2615 for ( i
= 0; i
!= pInRow
->mBars
.Count(); ++i
)
2617 cbBarInfo
& bar
= *pInRow
->mBars
[i
];
2619 if ( !bar
.IsFixed() )
2620 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalWidth
);
2624 void cbDockPane::RecalcRowLayout( cbRowInfo
* pRow
)
2626 cbLayoutRowEvent
evt( pRow
, this );
2628 mpLayout
->FirePluginEvent( evt
);
2631 void cbDockPane::ExpandBar( cbBarInfo
* pBar
)
2633 mpLayout
->GetUpdatesManager().OnStartChanges();
2635 if ( !pBar
->mpRow
->mpExpandedBar
)
2637 // save ratios only when there arent any bars expanded yet
2639 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2642 ratios
.Alloc( pBar
->mpRow
->mNotFixedBarsCnt
);
2644 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2648 if ( !pCur
->IsFixed() )
2651 ratios
[ ratios
.GetCount() - 1 ] = pCur
->mLenRatio
;
2654 pCur
= pCur
->mpNext
;
2658 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2662 pCur
->mLenRatio
= 0.0; // minimize the rest
2664 pCur
= pCur
->mpNext
;
2667 pBar
->mLenRatio
= 1.0; // 100%
2668 pBar
->mBounds
.width
= 0;
2670 pBar
->mpRow
->mpExpandedBar
= pBar
;
2672 mpLayout
->RecalcLayout( false );
2674 mpLayout
->GetUpdatesManager().OnFinishChanges();
2675 mpLayout
->GetUpdatesManager().UpdateNow();
2678 void cbDockPane::ContractBar( cbBarInfo
* pBar
)
2680 mpLayout
->GetUpdatesManager().OnStartChanges();
2682 // FIXME: What's the purpose of this???
2683 // double ratio = 1.0/ double( pBar->mpRow->mNotFixedBarsCnt );
2685 // restore ratios which were present before expansion
2687 cbBarInfo
* pCur
= pBar
->mpRow
->mBars
[0];
2689 cbArrayFloat
& ratios
= pBar
->mpRow
->mSavedRatios
;
2695 if ( !pCur
->IsFixed() )
2697 pCur
->mLenRatio
= ratios
[i
];
2701 pCur
= pCur
->mpNext
;
2707 pBar
->mpRow
->mpExpandedBar
= NULL
;
2709 mpLayout
->RecalcLayout( false );
2711 mpLayout
->GetUpdatesManager().OnFinishChanges();
2712 mpLayout
->GetUpdatesManager().UpdateNow();
2715 void cbDockPane::InitLinksForRow( cbRowInfo
* pRow
)
2718 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2720 cbBarInfo
& bar
= *pRow
->mBars
[i
];
2725 bar
.mpPrev
= pRow
->mBars
[i
-1];
2727 if ( i
== pRow
->mBars
.Count() - 1 )
2730 bar
.mpNext
= pRow
->mBars
[i
+1];
2734 void cbDockPane::InitLinksForRows()
2737 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2739 cbRowInfo
& row
= *mRows
[i
];
2744 row
.mpPrev
= mRows
[i
-1];
2746 if ( i
== mRows
.Count() - 1 )
2749 row
.mpNext
= mRows
[i
+1];
2753 void cbDockPane::DoInsertBar( cbBarInfo
* pBar
, int rowNo
)
2757 if ( rowNo
== -1 || rowNo
>= (int)mRows
.Count() )
2759 pRow
= new cbRowInfo();
2761 if ( rowNo
== -1 && mRows
.Count() )
2763 mRows
.Insert( pRow
, 0 );
2771 pRow
= mRows
[rowNo
];
2773 if ( mProps
.mNonDestructFrictionOn
== true )
2775 // store original shape of the row (before the bar is inserted)
2779 GetRowShapeData( mpStoredRow
, &mRowShapeData
);
2783 if ( pRow
->mBars
.Count() )
2785 pRow
->mpExpandedBar
= NULL
;
2787 cbInsertBarEvent
insEvt( pBar
, pRow
, this );
2789 mpLayout
->FirePluginEvent( insEvt
);
2791 mpLayout
->GetUpdatesManager().OnRowWillChange( pRow
, this );
2794 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
, const wxRect
& atRect
)
2796 wxRect rect
= atRect
;
2797 FrameToPane( &rect
);
2799 pBarInfo
->mBounds
.x
= rect
.x
;
2800 pBarInfo
->mBounds
.width
= rect
.width
;
2801 pBarInfo
->mBounds
.height
= rect
.height
;
2803 int row
= GetRowAt( rect
.y
, rect
.y
+ rect
.height
);
2805 DoInsertBar( pBarInfo
, row
);
2808 void cbDockPane::InsertBar( cbBarInfo
* pBar
, cbRowInfo
* pIntoRow
)
2810 cbInsertBarEvent
insEvt( pBar
, pIntoRow
, this );
2812 mpLayout
->FirePluginEvent( insEvt
);
2814 mpLayout
->GetUpdatesManager().OnRowWillChange( pIntoRow
, this );
2817 void cbDockPane::InsertBar( cbBarInfo
* pBarInfo
)
2819 // set transient properties
2821 pBarInfo
->mpRow
= NULL
;
2822 pBarInfo
->mHasLeftHandle
= false;
2823 pBarInfo
->mHasRightHandle
= false;
2824 pBarInfo
->mLenRatio
= 0.0;
2826 // set preferred bar dimensions, according to the state in which
2827 // the bar is being inserted
2829 pBarInfo
->mBounds
.width
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].x
;
2830 pBarInfo
->mBounds
.height
= pBarInfo
->mDimInfo
.mSizes
[ pBarInfo
->mState
].y
;
2832 DoInsertBar( pBarInfo
, pBarInfo
->mRowNo
);
2835 void cbDockPane::RemoveRow( cbRowInfo
* pRow
)
2838 // first, hide all bar-windows in the removed row
2839 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2841 if ( pRow
->mBars
[i
]->mpBarWnd
)
2842 pRow
->mBars
[i
]->mpBarWnd
->Show( false );
2845 mRows
.Remove( pRow
);
2847 pRow
->mUMgrData
.SetDirty(true);
2850 void cbDockPane::InsertRow( cbRowInfo
* pRow
, cbRowInfo
* pBeforeRow
)
2856 mRows
.Insert( pRow
, mRows
.Index( pBeforeRow
) );
2860 pRow
->mUMgrData
.SetDirty(true);
2863 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
2864 pRow
->mBars
[i
]->mUMgrData
.SetDirty( true );
2866 SyncRowFlags( pRow
);
2869 void cbDockPane::SetPaneWidth(int width
)
2871 if ( IsHorizontal() )
2872 mPaneWidth
= width
- mLeftMargin
- mRightMargin
;
2874 mPaneWidth
= width
- mTopMargin
- mBottomMargin
;
2878 void cbDockPane::SetBoundsInParent( const wxRect
& rect
)
2880 mBoundsInParent
= rect
;
2882 // set pane dimensions in local coordinates
2884 if ( IsHorizontal() )
2886 mPaneWidth
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2887 mPaneHeight
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2891 mPaneWidth
= mBoundsInParent
.height
- ( mTopMargin
+ mBottomMargin
);
2892 mPaneHeight
= mBoundsInParent
.width
- ( mRightMargin
+ mLeftMargin
);
2895 // convert bounding rectangles of all pane items into parent frame's coordinates
2897 wxBarIterator
i( mRows
);
2899 wxRect noMarginsRect
= mBoundsInParent
;
2901 noMarginsRect
.x
+= mLeftMargin
;
2902 noMarginsRect
.y
+= mTopMargin
;
2903 noMarginsRect
.width
-= ( mLeftMargin
+ mRightMargin
);
2904 noMarginsRect
.height
-= ( mTopMargin
+ mBottomMargin
);
2906 // hide the whole pane, if it's bounds became reverted (i.e. pane vanished)
2908 if ( mBoundsInParent
.width
< 0 ||
2909 mBoundsInParent
.height
< 0 )
2911 hide_rect( mBoundsInParent
);
2913 if ( noMarginsRect
.width
< 0 ||
2914 noMarginsRect
.height
< 0 )
2916 hide_rect( noMarginsRect
);
2918 // calculate mBoundsInParent for each item in the pane
2922 cbBarInfo
& bar
= i
.BarInfo();
2924 cbRowInfo
* pRowInfo
= bar
.mpRow
;
2926 // set up row info, if this is first bar in the row
2928 if ( pRowInfo
&& bar
.mpPrev
== NULL
)
2930 pRowInfo
->mBoundsInParent
.y
= pRowInfo
->mRowY
;
2931 pRowInfo
->mBoundsInParent
.x
= 0;
2932 pRowInfo
->mBoundsInParent
.width
= mPaneWidth
;
2933 pRowInfo
->mBoundsInParent
.height
= pRowInfo
->mRowHeight
;
2935 PaneToFrame( &pRowInfo
->mBoundsInParent
);
2937 clip_rect_against_rect( pRowInfo
->mBoundsInParent
, noMarginsRect
);
2940 wxRect bounds
= bar
.mBounds
;
2942 // exclude dimensions of handles, when calculating
2943 // bar's bounds in parent (i.e. "visual bounds")
2945 if ( bar
.mHasLeftHandle
)
2947 bounds
.x
+= mProps
.mResizeHandleSize
;
2948 bounds
.width
-= mProps
.mResizeHandleSize
;
2951 if ( bar
.mHasRightHandle
)
2953 bounds
.width
-= mProps
.mResizeHandleSize
;
2955 PaneToFrame( &bounds
);
2957 clip_rect_against_rect( bounds
, noMarginsRect
);
2959 bar
.mBoundsInParent
= bounds
;
2963 bool cbDockPane::BarPresent( cbBarInfo
* pBar
)
2965 wxBarIterator
iter( mRows
);
2967 while( iter
.Next() )
2969 if ( &iter
.BarInfo() == pBar
) return true;
2974 cbRowInfo
* cbDockPane::GetRow( int row
)
2976 if ( row
>= (int)mRows
.Count() ) return NULL
;
2978 return mRows
[ row
];
2981 int cbDockPane::GetRowIndex( cbRowInfo
* pRow
)
2984 for ( i
= 0; i
!= mRows
.Count(); ++i
)
2986 if ( mRows
[i
] == pRow
)
2990 wxFAIL_MSG(wxT("Row must be present to call cbDockPane::GetRowIndex()"));
2995 int cbDockPane::GetPaneHeight()
2997 // first, recalculate row heights and the Y-positions
2999 cbLayoutRowsEvent
evt( this );
3000 mpLayout
->FirePluginEvent( evt
);
3004 if ( IsHorizontal() )
3005 height
+= mTopMargin
+ mBottomMargin
;
3007 height
+= mLeftMargin
+ mRightMargin
;
3009 int count
= mRows
.Count();
3012 height
+= mRows
[count
-1]->mRowY
+ mRows
[count
-1]->mRowHeight
;
3017 int cbDockPane::GetAlignment()
3022 bool cbDockPane::MatchesMask( int paneMask
)
3026 // FIXME:: use array instead of switch()
3030 case FL_ALIGN_TOP
: thisMask
= FL_ALIGN_TOP_PANE
; break;
3031 case FL_ALIGN_BOTTOM
: thisMask
= FL_ALIGN_BOTTOM_PANE
;break;
3032 case FL_ALIGN_LEFT
: thisMask
= FL_ALIGN_LEFT_PANE
; break;
3033 case FL_ALIGN_RIGHT
: thisMask
= FL_ALIGN_RIGHT_PANE
; break;
3036 wxFAIL_MSG(wxT("Bad FL alignment type detected in cbDockPane::MatchesMask()"));
3039 return ( thisMask
& paneMask
) != 0;
3042 void cbDockPane::RecalcLayout()
3044 // first, reposition rows and items vertically
3046 cbLayoutRowsEvent
evt( this );
3047 mpLayout
->FirePluginEvent( evt
);
3049 // then horizontally in each row
3052 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3053 RecalcRowLayout( mRows
[i
] );
3056 int cbDockPane::GetDockingState()
3058 if ( mAlignment
== FL_ALIGN_TOP
||
3059 mAlignment
== FL_ALIGN_BOTTOM
)
3061 return wxCBAR_DOCKED_HORIZONTALLY
;
3064 return wxCBAR_DOCKED_VERTICALLY
;
3067 inline bool cbDockPane::HasPoint( const wxPoint
& pos
, int x
, int y
,
3068 int width
, int height
)
3070 return ( pos
.x
>= x
&&
3072 pos
.x
< x
+ width
&&
3073 pos
.y
< y
+ height
);
3076 int cbDockPane::HitTestPaneItems( const wxPoint
& pos
,
3085 for ( i
= 0; i
!= mRows
.Count(); ++i
)
3087 cbRowInfo
& row
= *mRows
[i
];
3091 // hit-test handles of the row, if present
3093 if ( row
.mHasUpperHandle
)
3095 if ( HasPoint( pos
, 0, row
.mRowY
,
3096 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3098 return CB_UPPER_ROW_HANDLE_HITTED
;
3101 if ( row
.mHasLowerHandle
)
3103 if ( HasPoint( pos
, 0, row
.mRowY
+ row
.mRowHeight
- mProps
.mResizeHandleSize
,
3104 row
.mRowWidth
, mProps
.mResizeHandleSize
) )
3106 return CB_LOWER_ROW_HANDLE_HITTED
;
3109 // hit-test bar handles and bar content
3112 for ( k
= 0; k
!= row
.mBars
.Count(); ++k
)
3114 cbBarInfo
& bar
= *row
.mBars
[k
];
3115 wxRect
& bounds
= bar
.mBounds
;
3119 if ( bar
.mHasLeftHandle
)
3121 if ( HasPoint( pos
, bounds
.x
, bounds
.y
,
3122 mProps
.mResizeHandleSize
, bounds
.height
) )
3124 return CB_LEFT_BAR_HANDLE_HITTED
;
3127 if ( bar
.mHasRightHandle
)
3129 if ( HasPoint( pos
, bounds
.x
+ bounds
.width
- mProps
.mResizeHandleSize
, bounds
.y
,
3130 mProps
.mResizeHandleSize
, bounds
.height
) )
3132 return CB_RIGHT_BAR_HANDLE_HITTED
;
3135 if ( HasPoint( pos
, bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
) )
3136 return CB_BAR_CONTENT_HITTED
;
3138 } // hit-test next bar
3142 return CB_NO_ITEMS_HITTED
;
3145 void cbDockPane::GetBarResizeRange( cbBarInfo
* pBar
, int* from
, int *till
,
3146 bool forLeftHandle
)
3148 cbBarInfo
* pGivenBar
= pBar
;
3152 // calc unavailable space from the left
3154 while( pBar
->mpPrev
)
3156 pBar
= pBar
->mpPrev
;
3158 if ( !pBar
->IsFixed() ) notFree
+= mProps
.mMinCBarDim
.x
;
3159 else notFree
+= pBar
->mBounds
.width
;
3168 // calc unavailable space from the right
3170 while( pBar
->mpNext
)
3172 pBar
= pBar
->mpNext
;
3174 if ( pBar
->mBounds
.x
>= mPaneWidth
) break;
3176 // treat not-fixed bars as minimized
3178 if ( !pBar
->IsFixed() )
3179 notFree
+= mProps
.mMinCBarDim
.x
;
3182 if ( pBar
->mBounds
.x
+ pBar
->mBounds
.width
>= mPaneWidth
)
3184 notFree
+= mPaneWidth
- pBar
->mBounds
.x
;
3188 notFree
+= pBar
->mBounds
.width
;
3193 *till
= mPaneWidth
- notFree
;
3195 // do not let resizing totally deform the bar itself
3197 if ( forLeftHandle
)
3198 (*till
) -= mProps
.mMinCBarDim
.x
;
3200 (*from
) += mProps
.mMinCBarDim
.x
;
3203 int cbDockPane::GetMinimalRowHeight( cbRowInfo
* pRow
)
3205 int height
= mProps
.mMinCBarDim
.y
;
3208 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3210 if ( pRow
->mBars
[i
]->IsFixed() )
3211 height
= wxMax( height
, pRow
->mBars
[i
]->mBounds
.height
);
3214 if ( pRow
->mHasUpperHandle
)
3215 height
+= mProps
.mResizeHandleSize
;
3217 if ( pRow
->mHasLowerHandle
)
3218 height
+= mProps
.mResizeHandleSize
;
3223 void cbDockPane::SetRowHeight( cbRowInfo
* pRow
, int newHeight
)
3225 if ( pRow
->mHasUpperHandle
)
3227 newHeight
-= mProps
.mResizeHandleSize
;
3229 if ( pRow
->mHasLowerHandle
)
3231 newHeight
-= mProps
.mResizeHandleSize
;
3234 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3236 if ( !pRow
->mBars
[i
]->IsFixed() )
3237 pRow
->mBars
[i
]->mBounds
.height
= newHeight
;
3241 void cbDockPane::GetRowResizeRange( cbRowInfo
* pRow
, int* from
, int* till
,
3242 bool forUpperHandle
)
3244 cbRowInfo
* pGivenRow
= pRow
;
3246 // calc unavailable space from above
3250 while( pRow
->mpPrev
)
3252 pRow
= pRow
->mpPrev
;
3254 notFree
+= GetMinimalRowHeight( pRow
);
3260 // allow accupy the client window space by resizing pane rows
3261 if ( mAlignment
== FL_ALIGN_BOTTOM
)
3263 *from
-= mpLayout
->GetClientHeight();
3265 if ( mAlignment
== FL_ALIGN_RIGHT
)
3267 *from
-= mpLayout
->GetClientWidth();
3269 // calc unavailable space from below
3275 while( pRow
->mpNext
)
3277 pRow
= pRow
->mpNext
;
3279 notFree
+= GetMinimalRowHeight( pRow
);
3283 *till
= mPaneHeight
- notFree
;
3285 // allow adjustinig pane space vs. client window space by resizing pane row heights
3287 if ( mAlignment
== FL_ALIGN_TOP
)
3289 *till
+= mpLayout
->GetClientHeight();
3291 if ( mAlignment
== FL_ALIGN_LEFT
)
3293 *till
+= mpLayout
->GetClientWidth();
3295 // do not let the resizing of the row totally squeeze the row itself
3297 cbRowInfo
& row
= *pGivenRow
;
3299 if ( forUpperHandle
)
3301 *till
= row
.mRowY
+ row
.mRowHeight
- GetMinimalRowHeight( pGivenRow
);
3303 if ( row
.mHasUpperHandle
)
3305 *till
-= mProps
.mResizeHandleSize
;
3309 *from
+= GetMinimalRowHeight( pGivenRow
);
3311 if ( row
.mHasLowerHandle
)
3313 *from
-= mProps
.mResizeHandleSize
;
3317 void cbDockPane::ResizeRow( cbRowInfo
* pRow
, int ofs
,
3318 bool forUpperHandle
)
3320 cbResizeRowEvent
evt( pRow
, ofs
, forUpperHandle
, this );
3322 mpLayout
->FirePluginEvent( evt
);
3325 void cbDockPane::ResizeBar( cbBarInfo
* pBar
, int ofs
,
3326 bool forLeftHandle
)
3328 pBar
->mpRow
->mpExpandedBar
= NULL
;
3330 mpLayout
->GetUpdatesManager().OnStartChanges();
3332 wxRect
& bounds
= pBar
->mBounds
;
3334 if ( forLeftHandle
)
3336 // do not allow bar width become less then minimal
3337 if ( bounds
.x
+ ofs
> bounds
.x
+ bounds
.width
- mProps
.mMinCBarDim
.x
)
3339 bounds
.width
= mProps
.mMinCBarDim
.x
;
3345 bounds
.width
-= ofs
;
3350 // move bar left if necessary
3351 if ( bounds
.width
+ ofs
< mProps
.mMinCBarDim
.x
)
3353 bounds
.x
= bounds
.x
+ bounds
.width
+ ofs
- mProps
.mMinCBarDim
.x
;
3354 bounds
.width
= mProps
.mMinCBarDim
.x
;
3357 // resize right border only
3358 bounds
.width
+= ofs
;
3362 cbRowInfo
* pToRow
= pBar
->mpRow
;
3364 this->RemoveBar( pBar
);
3366 InsertBar( pBar
, pToRow
);
3368 mpLayout
->RecalcLayout(false);
3370 mpLayout
->GetUpdatesManager().OnFinishChanges();
3371 mpLayout
->GetUpdatesManager().UpdateNow();
3375 /*** row/bar resizing related methods ***/
3377 void cbDockPane::DrawVertHandle( wxDC
& dc
, int x
, int y
, int height
)
3379 int lower
= y
+ height
;
3381 dc
.SetPen( mpLayout
->mLightPen
);
3382 dc
.DrawLine( x
,y
, x
, lower
);
3384 dc
.SetPen( mpLayout
->mGrayPen
);
3386 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3389 dc
.DrawLine( x
,y
, x
, lower
);
3392 dc
.SetPen( mpLayout
->mDarkPen
);
3394 dc
.DrawLine( x
,y
, x
, lower
);
3396 dc
.SetPen( mpLayout
->mBlackPen
);
3398 dc
.DrawLine( x
,y
, x
, lower
);
3401 void cbDockPane::DrawHorizHandle( wxDC
& dc
, int x
, int y
, int width
)
3403 int right
= x
+ width
;
3405 dc
.SetPen( mpLayout
->mLightPen
);
3406 dc
.DrawLine( x
,y
, right
, y
);
3408 dc
.SetPen( mpLayout
->mGrayPen
);
3411 for ( i
= 0; i
!= mProps
.mResizeHandleSize
-1; ++i
)
3414 dc
.DrawLine( x
,y
, right
, y
);
3418 dc
.SetPen( mpLayout
->mDarkPen
);
3419 dc
.DrawLine( x
,y
, right
, y
);
3422 dc
.SetPen( mpLayout
->mBlackPen
);
3423 dc
.DrawLine( x
,y
, right
, y
);
3426 cbBarInfo
* cbDockPane::GetBarInfoByWindow( wxWindow
* pBarWnd
)
3428 wxBarIterator
i( mRows
);
3432 if ( i
.BarInfo().mpBarWnd
== pBarWnd
)
3434 return &i
.BarInfo();
3439 void cbDockPane::GetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3443 WX_CLEAR_LIST(wxList
,*pLst
);
3449 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3451 cbBarInfo
& bar
= *pRow
->mBars
[i
];
3453 cbBarShapeData
* pData
= new cbBarShapeData();
3455 pLst
->Append( (wxObject
*)pData
);
3457 pData
->mBounds
= bar
.mBounds
;
3458 pData
->mLenRatio
= bar
.mLenRatio
;
3462 void cbDockPane::SetRowShapeData( cbRowInfo
* pRow
, wxList
* pLst
)
3464 if ( pLst
->GetFirst() == NULL
)
3467 wxObjectList::compatibility_iterator pData
= pLst
->GetFirst();
3470 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
3472 wxASSERT( pData
); // DBG::
3474 cbBarInfo
& bar
= *pRow
->mBars
[i
];;
3476 cbBarShapeData
& data
= *((cbBarShapeData
*)pData
->GetData());
3478 bar
.mBounds
= data
.mBounds
;
3479 bar
.mLenRatio
= data
.mLenRatio
;
3481 pData
= pData
->GetNext();
3485 /***** Implementation for class cbUpdatesManagerBase *****/
3487 IMPLEMENT_ABSTRACT_CLASS( cbUpdatesManagerBase
, wxObject
)
3489 /***** Implementation for class cbPluginBase *****/
3491 IMPLEMENT_ABSTRACT_CLASS( cbPluginBase
, wxEvtHandler
)
3493 cbPluginBase::~cbPluginBase()
3498 bool cbPluginBase::ProcessEvent(wxEvent
& event
)
3500 if ( mPaneMask
== wxALL_PANES
)
3502 return wxEvtHandler::ProcessEvent( event
);
3504 // extract mask info. from received event
3506 cbPluginEvent
& evt
= *( (cbPluginEvent
*)&event
);
3508 if ( evt
.mpPane
== 0 &&
3509 mPaneMask
== wxALL_PANES
)
3511 return wxEvtHandler::ProcessEvent( event
);
3515 switch ( evt
.mpPane
->mAlignment
)
3517 case FL_ALIGN_TOP
: mask
= FL_ALIGN_TOP_PANE
; break;
3518 case FL_ALIGN_BOTTOM
: mask
= FL_ALIGN_BOTTOM_PANE
;break;
3519 case FL_ALIGN_LEFT
: mask
= FL_ALIGN_LEFT_PANE
; break;
3520 case FL_ALIGN_RIGHT
: mask
= FL_ALIGN_RIGHT_PANE
; break;
3523 // if event's pane maks matches the plugin's mask
3525 if ( mPaneMask
& mask
)
3527 return wxEvtHandler::ProcessEvent( event
);
3529 // otherwise pass to the next handler if present
3531 if ( GetNextHandler() && GetNextHandler()->ProcessEvent( event
) )