]>
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 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
23 #include "wx/fl/gcupdatesmgr.h"
27 static inline bool rect_hits_rect( const wxRect
& r1
, const wxRect
& r2
)
29 if ( ( r2
.x
>= r1
.x
&& r2
.x
<= r1
.x
+ r1
.width
) ||
30 ( r1
.x
>= r2
.x
&& r1
.x
<= r2
.x
+ r2
.width
) )
32 if ( ( r2
.y
>= r1
.y
&& r2
.y
<= r1
.y
+ r1
.height
) ||
33 ( r1
.y
>= r2
.y
&& r1
.y
<= r2
.y
+ r2
.height
) )
50 static inline cbRectInfo
& node_to_rect_info( wxNode
* pNode
)
52 return *( (cbRectInfo
*) (pNode
->GetData()) );
55 /***** Implementation for class cbSimpleUpdatesMgr *****/
57 IMPLEMENT_DYNAMIC_CLASS( cbGCUpdatesMgr
, cbSimpleUpdatesMgr
)
59 cbGCUpdatesMgr::cbGCUpdatesMgr( wxFrameLayout
* pPanel
)
60 : cbSimpleUpdatesMgr( pPanel
)
63 void cbGCUpdatesMgr::AddItem( wxList
& itemList
,
69 cbRectInfo
* pInfo
= new cbRectInfo();
72 pInfo
->mpPane
= pPane
;
73 pInfo
->mpCurBounds
= &curBounds
;
74 pInfo
->mpPrevBounds
= &prevBounds
;
76 itemList
.Append( (wxObject
*) pInfo
);
79 void cbGCUpdatesMgr::OnStartChanges()
81 // memorize states of ALL items in the layout -
82 // this is quite excessive, but OK for the decent
83 // implementation of updates manager
85 mpLayout
->GetPrevClientRect() = mpLayout
->GetClientRect();
87 cbDockPane
** panes
= mpLayout
->GetPanesArray();
89 for( int n
= 0; n
!= MAX_PANES
; ++n
)
91 cbDockPane
& pane
= *(panes
[n
]);
94 pane
.mUMgrData
.StoreItemState( pane
.mBoundsInParent
);
95 pane
.mUMgrData
.SetDirty( false );
97 cbRowInfo
* pRow
= pane
.GetFirstRow();
101 cbBarInfo
* pBar
= pRow
->GetFirstBar();
104 pRow
->mUMgrData
.StoreItemState( pRow
->mBoundsInParent
);
105 pRow
->mUMgrData
.SetDirty( false );
110 pBar
->mUMgrData
.StoreItemState( pBar
->mBoundsInParent
);
111 pBar
->mUMgrData
.SetDirty( false );
121 void cbGCUpdatesMgr::UpdateNow()
123 cbDockPane
** panes
= mpLayout
->GetPanesArray();
125 wxRect
& r1
= mpLayout
->GetClientRect();
126 wxRect
& r2
= mpLayout
->GetPrevClientRect();
128 // detect changes in client window's area
130 bool clientWindowChanged
= ( r1
.x
!= r2
.x
||
132 r1
.width
!= r2
.width
||
133 r1
.height
!= r2
.height
);
135 // step #1 - detect changes in each row of each pane,
136 // and repaint decorations around changed windows
138 wxList mBarsToResize
;
141 for ( n
= 0; n
!= MAX_PANES
; ++n
)
143 cbDockPane
& pane
= *(panes
[n
]);
145 bool paneChanged
= WasChanged( pane
.mUMgrData
, pane
.mBoundsInParent
);
149 wxClientDC
dc( &mpLayout
->GetParentFrame() );
150 pane
.PaintPaneBackground( dc
);
155 cbRowInfo
* pRow
= pane
.GetFirstRow();
161 cbBarInfo
* pBar
= pRow
->GetFirstBar();
163 bool rowChanged
= false;
164 // bool rowBkPainted = false;
166 // FIXME:: the below should not be fixed
167 cbBarInfo
* barsToRepaint
[128];
168 // number of bars, that were changed in the current row
171 //wxRect r1 = pRow->mUMgrData.mPrevBounds;
172 //wxRect r2 = pRow->mBoundsInParent;
174 if ( WasChanged( pRow
->mUMgrData
, pRow
->mBoundsInParent
) )
180 if ( WasChanged( pBar
->mUMgrData
, pBar
->mBoundsInParent
) )
182 barsToRepaint
[nBars
++] = pBar
;
187 if ( nBars
|| rowChanged
)
189 realBounds
= pRow
->mBoundsInParent
;
191 // include 1-pixel thick shades around the row
194 realBounds
.width
+= 2;
195 realBounds
.height
+= 2;
197 pDc
= pane
.StartDrawInArea( realBounds
);
202 // postphone the resizement and refreshing the changed
205 cbBarInfo
* pCurBar
= pRow
->GetFirstBar();
209 if ( WasChanged( pCurBar
->mUMgrData
,
210 pCurBar
->mBoundsInParent
) )
212 AddItem( mBarsToResize
, pCurBar
, &pane
,
213 pCurBar
->mBoundsInParent
,
214 pCurBar
->mUMgrData
.mPrevBounds
);
216 pCurBar
= pCurBar
->mpNext
;
219 // draw only their decorations now
221 pane
.PaintRow( pRow
, *pDc
);
226 for ( int i
= 0; i
!= nBars
; ++i
)
228 // postphone the resizement and refreshing the changed
231 AddItem( mBarsToResize
,
234 barsToRepaint
[i
]->mBoundsInParent
,
235 barsToRepaint
[i
]->mUMgrData
.mPrevBounds
);
237 // redraw decorations of entire row, regardless of how much
238 // of the bars were changed
240 pane
.PaintRow( pRow
, *pDc
);
245 pane
.FinishDrawInArea( realBounds
);
253 wxClientDC
dc( &mpLayout
->GetParentFrame() );
254 pane
.PaintPaneDecorations( dc
);
259 if ( clientWindowChanged
&& !mpLayout
->mClientWndRefreshPending
)
261 // ptr to client-window object is "marked" as NULL
263 AddItem( mBarsToResize
, NULL
, NULL
,
264 mpLayout
->GetClientRect(),
265 mpLayout
->GetPrevClientRect() );
268 // step #2 - do ordered refreshing and resizing of bar window objects now
270 DoRepositionItems( mBarsToResize
);
273 void cbGCUpdatesMgr::DoRepositionItems( wxList
& items
)
275 wxNode
* pNode1
= items
.GetFirst();
279 cbRectInfo
& info
= node_to_rect_info( pNode1
);
281 wxNode
* pNode2
= items
.GetFirst();
285 mGC
.AddObject( &info
);
289 if ( pNode2
!= pNode1
) // node should not depend on itself
291 // Add references to objects on which this object
292 // depends. Dependency here indicates intersection of current
293 // bounds of this object with the initial bounds of the
296 cbRectInfo
& otherInfo
= node_to_rect_info( pNode2
);
298 if ( rect_hits_rect( *info
.mpCurBounds
, *otherInfo
.mpPrevBounds
) )
300 // the node depends on node
301 mGC
.AddDependency( &info
, &otherInfo
);
304 pNode2
= pNode2
->GetNext();
307 pNode1
= pNode1
->GetNext();
310 mGC
.ArrangeCollection(); // order nodes according "least-dependency" rule,
311 // and find out cycled chains
313 // Regular item nodes need to be resized, but not repainted (since
314 // they stand in linear (not cyclic) dependency with other
317 wxNode
* pNode
= mGC
.GetRegularObjects().GetFirst();
321 cbRectInfo
& info
= *((cbRectInfo
*)gc_node_to_obj(pNode
));
323 if ( info
.mpBar
== NULL
)
325 mpLayout
->PositionClientWindow();
327 info
.mpPane
->SizeBar( info
.mpBar
);
329 pNode
= pNode
->GetNext();
332 // cycled item nodes, need to be both resized and repainted
334 pNode
= mGC
.GetCycledObjects().GetFirst();
338 cbRectInfo
& info
= *((cbRectInfo
*)gc_node_to_obj(pNode
));
340 if ( info
.mpBar
== NULL
)
342 wxWindow
* pClntWnd
= mpLayout
->GetFrameClient();
344 mpLayout
->PositionClientWindow();
346 // FIXME FIXME:: excessive!
348 pClntWnd
->Show( false );
349 pClntWnd
->Show( true );
351 // OLD STUFF:: mpLayout->PositionClientWindow();
354 if ( info
.mpBar
->mpBarWnd
)
356 wxWindow
* pWnd
= info
.mpBar
->mpBarWnd
;
359 info
.mpPane
->SizeBar( info
.mpBar
);
363 /* OLD STUFF:: bool isChoice = info.mpBar->IsKindOf( CLASSINFO( wxChoice ) );
366 //int result = ::SendMessage( (HWND)pWnd->m_hWnd, WM_NCPAINT, 0, 0 );
370 // FIXME FIXME:: there's no other way to repaint non-client area of the wxWindow!!
371 // so we do *excessive* "hide 'n show"
379 pNode
= pNode
->GetNext();
382 // release data prepared for GC alg.
384 pNode
= items
.GetFirst();
388 cbRectInfo
* pInfo
= (cbRectInfo
*)(pNode
->GetData());
392 pNode
= pNode
->GetNext();
395 mGC
.Reset(); // reinit GC
397 // FIXME:: this is a dirty-workaround for messy client-area,
398 // as a result of docking bar out of floated-container window
400 if ( mpLayout
->mClientWndRefreshPending
)
402 mpLayout
->PositionClientWindow();
403 mpLayout
->GetFrameClient()->Refresh();