]>
git.saurik.com Git - wxWidgets.git/blob - contrib/src/fl/gcupdatesmgr.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gcupdatesmgr.cpp
3 // Purpose: cbGCUpdatesMgr class, optimizing refresh using GarbageCollector
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "gcupdatesmgr.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
27 #include "wx/fl/gcupdatesmgr.h"
31 static inline bool rect_hits_rect( const wxRect
& r1
, const wxRect
& r2
)
33 if ( ( r2
.x
>= r1
.x
&& r2
.x
<= r1
.x
+ r1
.width
) ||
34 ( r1
.x
>= r2
.x
&& r1
.x
<= r2
.x
+ r2
.width
) )
36 if ( ( r2
.y
>= r1
.y
&& r2
.y
<= r1
.y
+ r1
.height
) ||
37 ( r1
.y
>= r2
.y
&& r1
.y
<= r2
.y
+ r2
.height
) )
54 static inline cbRectInfo
& node_to_rect_info( wxNode
* pNode
)
56 return *( (cbRectInfo
*) (pNode
->GetData()) );
59 /***** Implementation for class cbSimpleUpdatesMgr *****/
61 IMPLEMENT_DYNAMIC_CLASS( cbGCUpdatesMgr
, cbSimpleUpdatesMgr
)
63 cbGCUpdatesMgr::cbGCUpdatesMgr( wxFrameLayout
* pPanel
)
64 : cbSimpleUpdatesMgr( pPanel
)
67 void cbGCUpdatesMgr::AddItem( wxList
& itemList
,
73 cbRectInfo
* pInfo
= new cbRectInfo();
76 pInfo
->mpPane
= pPane
;
77 pInfo
->mpCurBounds
= &curBounds
;
78 pInfo
->mpPrevBounds
= &prevBounds
;
80 itemList
.Append( (wxObject
*) pInfo
);
83 void cbGCUpdatesMgr::OnStartChanges()
85 // memorize states of ALL items in the layout -
86 // this is quite excessive, but OK for the decent
87 // implementation of updates manager
89 mpLayout
->GetPrevClientRect() = mpLayout
->GetClientRect();
91 cbDockPane
** panes
= mpLayout
->GetPanesArray();
93 for( int n
= 0; n
!= MAX_PANES
; ++n
)
95 cbDockPane
& pane
= *(panes
[n
]);
98 pane
.mUMgrData
.StoreItemState( pane
.mBoundsInParent
);
99 pane
.mUMgrData
.SetDirty( FALSE
);
101 cbRowInfo
* pRow
= pane
.GetFirstRow();
105 cbBarInfo
* pBar
= pRow
->GetFirstBar();
108 pRow
->mUMgrData
.StoreItemState( pRow
->mBoundsInParent
);
109 pRow
->mUMgrData
.SetDirty( FALSE
);
114 pBar
->mUMgrData
.StoreItemState( pBar
->mBoundsInParent
);
115 pBar
->mUMgrData
.SetDirty( FALSE
);
125 void cbGCUpdatesMgr::UpdateNow()
127 cbDockPane
** panes
= mpLayout
->GetPanesArray();
129 wxRect
& r1
= mpLayout
->GetClientRect();
130 wxRect
& r2
= mpLayout
->GetPrevClientRect();
132 // detect changes in client window's area
134 bool clientWindowChanged
= ( r1
.x
!= r2
.x
||
136 r1
.width
!= r2
.width
||
137 r1
.height
!= r2
.height
);
139 // step #1 - detect changes in each row of each pane,
140 // and repaint decorations around changed windows
142 wxList mBarsToResize
;
145 for ( n
= 0; n
!= MAX_PANES
; ++n
)
147 cbDockPane
& pane
= *(panes
[n
]);
149 bool paneChanged
= WasChanged( pane
.mUMgrData
, pane
.mBoundsInParent
);
153 wxClientDC
dc( &mpLayout
->GetParentFrame() );
154 pane
.PaintPaneBackground( dc
);
159 cbRowInfo
* pRow
= pane
.GetFirstRow();
165 cbBarInfo
* pBar
= pRow
->GetFirstBar();
167 bool rowChanged
= FALSE
;
168 // bool rowBkPainted = FALSE;
170 // FIXME:: the below should not be fixed
171 cbBarInfo
* barsToRepaint
[128];
172 // number of bars, that were changed in the current row
175 //wxRect r1 = pRow->mUMgrData.mPrevBounds;
176 //wxRect r2 = pRow->mBoundsInParent;
178 if ( WasChanged( pRow
->mUMgrData
, pRow
->mBoundsInParent
) )
184 if ( WasChanged( pBar
->mUMgrData
, pBar
->mBoundsInParent
) )
186 barsToRepaint
[nBars
++] = pBar
;
191 if ( nBars
|| rowChanged
)
193 realBounds
= pRow
->mBoundsInParent
;
195 // include 1-pixel thick shades around the row
198 realBounds
.width
+= 2;
199 realBounds
.height
+= 2;
201 pDc
= pane
.StartDrawInArea( realBounds
);
206 // postphone the resizement and refreshing the changed
209 cbBarInfo
* pCurBar
= pRow
->GetFirstBar();
213 if ( WasChanged( pCurBar
->mUMgrData
,
214 pCurBar
->mBoundsInParent
) )
216 AddItem( mBarsToResize
, pCurBar
, &pane
,
217 pCurBar
->mBoundsInParent
,
218 pCurBar
->mUMgrData
.mPrevBounds
);
220 pCurBar
= pCurBar
->mpNext
;
223 // draw only their decorations now
225 pane
.PaintRow( pRow
, *pDc
);
230 for ( int i
= 0; i
!= nBars
; ++i
)
232 // postphone the resizement and refreshing the changed
235 AddItem( mBarsToResize
,
238 barsToRepaint
[i
]->mBoundsInParent
,
239 barsToRepaint
[i
]->mUMgrData
.mPrevBounds
);
241 // redraw decorations of entire row, regardless of how much
242 // of the bars were changed
244 pane
.PaintRow( pRow
, *pDc
);
249 pane
.FinishDrawInArea( realBounds
);
257 wxClientDC
dc( &mpLayout
->GetParentFrame() );
258 pane
.PaintPaneDecorations( dc
);
263 if ( clientWindowChanged
&& !mpLayout
->mClientWndRefreshPending
)
265 // ptr to client-window object is "marked" as NULL
267 AddItem( mBarsToResize
, NULL
, NULL
,
268 mpLayout
->GetClientRect(),
269 mpLayout
->GetPrevClientRect() );
272 // step #2 - do ordered refreshing and resizing of bar window objects now
274 DoRepositionItems( mBarsToResize
);
277 void cbGCUpdatesMgr::DoRepositionItems( wxList
& items
)
279 wxNode
* pNode1
= items
.GetFirst();
283 cbRectInfo
& info
= node_to_rect_info( pNode1
);
285 wxNode
* pNode2
= items
.GetFirst();
289 mGC
.AddObject( &info
);
293 if ( pNode2
!= pNode1
) // node should not depend on itself
295 // Add references to objects on which this object
296 // depends. Dependency here indicates intersection of current
297 // bounds of this object with the initial bounds of the
300 cbRectInfo
& otherInfo
= node_to_rect_info( pNode2
);
302 if ( rect_hits_rect( *info
.mpCurBounds
, *otherInfo
.mpPrevBounds
) )
304 // the node depends on node
305 mGC
.AddDependency( &info
, &otherInfo
);
308 pNode2
= pNode2
->GetNext();
311 pNode1
= pNode1
->GetNext();
314 mGC
.ArrangeCollection(); // order nodes according "least-dependency" rule,
315 // and find out cycled chains
317 // Regular item nodes need to be resized, but not repainted (since
318 // they stand in linear (not cyclic) dependency with other
321 wxNode
* pNode
= mGC
.GetRegularObjects().GetFirst();
325 cbRectInfo
& info
= *((cbRectInfo
*)gc_node_to_obj(pNode
));
327 if ( info
.mpBar
== NULL
)
329 mpLayout
->PositionClientWindow();
331 info
.mpPane
->SizeBar( info
.mpBar
);
333 pNode
= pNode
->GetNext();
336 // cycled item nodes, need to be both resized and repainted
338 pNode
= mGC
.GetCycledObjects().GetFirst();
342 cbRectInfo
& info
= *((cbRectInfo
*)gc_node_to_obj(pNode
));
344 if ( info
.mpBar
== NULL
)
346 wxWindow
* pClntWnd
= mpLayout
->GetFrameClient();
348 mpLayout
->PositionClientWindow();
350 // FIXME FIXME:: excessive!
352 pClntWnd
->Show( FALSE
);
353 pClntWnd
->Show( TRUE
);
355 // OLD STUFF:: mpLayout->PositionClientWindow();
358 if ( info
.mpBar
->mpBarWnd
)
360 wxWindow
* pWnd
= info
.mpBar
->mpBarWnd
;
363 info
.mpPane
->SizeBar( info
.mpBar
);
367 /* OLD STUFF:: bool isChoice = info.mpBar->IsKindOf( CLASSINFO( wxChoice ) );
370 //int result = ::SendMessage( (HWND)pWnd->m_hWnd, WM_NCPAINT, 0, 0 );
374 // FIXME FIXME:: there's no other way to repaint non-client area of the wxWindow!!
375 // so we do *excessive* "hide 'n show"
383 pNode
= pNode
->GetNext();
386 // release data prepared for GC alg.
388 pNode
= items
.GetFirst();
392 cbRectInfo
* pInfo
= (cbRectInfo
*)(pNode
->GetData());
396 pNode
= pNode
->GetNext();
399 mGC
.Reset(); // reinit GC
401 // FIXME:: this is a dirty-workaround for messy client-area,
402 // as a result of docking bar out of floated-container window
404 if ( mpLayout
->mClientWndRefreshPending
)
406 mpLayout
->PositionClientWindow();
407 mpLayout
->GetFrameClient()->Refresh();