]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/fl/gcupdatesmgr.cpp
Typo correction
[wxWidgets.git] / contrib / src / fl / gcupdatesmgr.cpp
CommitLineData
8e08b761 1/////////////////////////////////////////////////////////////////////////////
4cbc57f0
JS
2// Name: gcupdatesmgr.cpp
3// Purpose: cbGCUpdatesMgr class, optimizing refresh using GarbageCollector
8e08b761
JS
4// Author: Aleksandras Gluchovas
5// Modified by:
6// Created: 19/10/98
7// RCS-ID: $Id$
8// Copyright: (c) Aleksandras Gluchovas
c82c42d4 9// Licence: wxWindows licence
8e08b761
JS
10/////////////////////////////////////////////////////////////////////////////
11
8e08b761
JS
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16#pragma hdrstop
17#endif
18
19#ifndef WX_PRECOMP
20#include "wx/wx.h"
21#endif
22
23#include "wx/fl/gcupdatesmgr.h"
24
25// helper function
26
27static inline bool rect_hits_rect( const wxRect& r1, const wxRect& r2 )
28{
4cbc57f0
JS
29 if ( ( r2.x >= r1.x && r2.x <= r1.x + r1.width ) ||
30 ( r1.x >= r2.x && r1.x <= r2.x + r2.width ) )
8e08b761 31
4cbc57f0
JS
32 if ( ( r2.y >= r1.y && r2.y <= r1.y + r1.height ) ||
33 ( r1.y >= r2.y && r1.y <= r2.y + r2.height ) )
34
35 return 1;
8e08b761 36
4cbc57f0 37 return 0;
8e08b761
JS
38}
39
40// helper structure
41
42struct cbRectInfo
43{
4cbc57f0
JS
44 cbBarInfo* mpBar;
45 cbDockPane* mpPane;
46 wxRect* mpCurBounds;
47 wxRect* mpPrevBounds;
8e08b761
JS
48};
49
50static inline cbRectInfo& node_to_rect_info( wxNode* pNode )
51{
8495ba53 52 return *( (cbRectInfo*) (pNode->GetData()) );
8e08b761
JS
53}
54
55/***** Implementation for class cbSimpleUpdatesMgr *****/
56
57IMPLEMENT_DYNAMIC_CLASS( cbGCUpdatesMgr, cbSimpleUpdatesMgr )
58
59cbGCUpdatesMgr::cbGCUpdatesMgr( wxFrameLayout* pPanel )
4cbc57f0 60 : cbSimpleUpdatesMgr( pPanel )
8e08b761
JS
61{}
62
63void cbGCUpdatesMgr::AddItem( wxList& itemList,
4cbc57f0
JS
64 cbBarInfo* pBar,
65 cbDockPane* pPane,
66 wxRect& curBounds,
67 wxRect& prevBounds )
8e08b761 68{
4cbc57f0 69 cbRectInfo* pInfo = new cbRectInfo();
8e08b761 70
4cbc57f0
JS
71 pInfo->mpBar = pBar;
72 pInfo->mpPane = pPane;
73 pInfo->mpCurBounds = &curBounds;
74 pInfo->mpPrevBounds = &prevBounds;
8e08b761 75
4cbc57f0 76 itemList.Append( (wxObject*) pInfo );
8e08b761
JS
77}
78
79void cbGCUpdatesMgr::OnStartChanges()
80{
4cbc57f0
JS
81 // memorize states of ALL items in the layout -
82 // this is quite excessive, but OK for the decent
83 // implementation of updates manager
8e08b761 84
4cbc57f0 85 mpLayout->GetPrevClientRect() = mpLayout->GetClientRect();
8e08b761 86
4cbc57f0 87 cbDockPane** panes = mpLayout->GetPanesArray();
8e08b761 88
4cbc57f0
JS
89 for( int n = 0; n != MAX_PANES; ++n )
90 {
91 cbDockPane& pane = *(panes[n]);
8e08b761 92
4cbc57f0
JS
93 // store pane state
94 pane.mUMgrData.StoreItemState( pane.mBoundsInParent );
c82c42d4 95 pane.mUMgrData.SetDirty( false );
8e08b761 96
4cbc57f0 97 cbRowInfo* pRow = pane.GetFirstRow();
8e08b761 98
4cbc57f0
JS
99 while ( pRow )
100 {
101 cbBarInfo* pBar = pRow->GetFirstBar();
8e08b761 102
4cbc57f0
JS
103 // store row state
104 pRow->mUMgrData.StoreItemState( pRow->mBoundsInParent );
c82c42d4 105 pRow->mUMgrData.SetDirty( false );
8e08b761 106
4cbc57f0
JS
107 while( pBar )
108 {
109 // store bar state
110 pBar->mUMgrData.StoreItemState( pBar->mBoundsInParent );
c82c42d4 111 pBar->mUMgrData.SetDirty( false );
8e08b761 112
4cbc57f0
JS
113 pBar = pBar->mpNext;
114 }
8e08b761 115
4cbc57f0
JS
116 pRow = pRow->mpNext;
117 }
118 }
8e08b761
JS
119}
120
121void cbGCUpdatesMgr::UpdateNow()
122{
4cbc57f0 123 cbDockPane** panes = mpLayout->GetPanesArray();
8e08b761 124
4cbc57f0
JS
125 wxRect& r1 = mpLayout->GetClientRect();
126 wxRect& r2 = mpLayout->GetPrevClientRect();
8e08b761 127
4cbc57f0 128 // detect changes in client window's area
8e08b761 129
4cbc57f0
JS
130 bool clientWindowChanged = ( r1.x != r2.x ||
131 r1.y != r2.y ||
132 r1.width != r2.width ||
133 r1.height != r2.height );
8e08b761 134
4cbc57f0
JS
135 // step #1 - detect changes in each row of each pane,
136 // and repaint decorations around changed windows
8e08b761 137
4cbc57f0 138 wxList mBarsToResize;
8e08b761 139
4cbc57f0
JS
140 int n;
141 for ( n = 0; n != MAX_PANES; ++n )
142 {
143 cbDockPane& pane = *(panes[n]);
8e08b761 144
4cbc57f0 145 bool paneChanged = WasChanged( pane.mUMgrData, pane.mBoundsInParent );
8e08b761 146
4cbc57f0
JS
147 if ( paneChanged )
148 {
149 wxClientDC dc( &mpLayout->GetParentFrame() );
150 pane.PaintPaneBackground( dc );
151 }
8e08b761 152
4cbc57f0 153 wxRect realBounds;
8e08b761 154
4cbc57f0 155 cbRowInfo* pRow = pane.GetFirstRow();
8e08b761 156
4cbc57f0
JS
157 while ( pRow )
158 {
159 wxDC* pDc = 0;
8e08b761 160
4cbc57f0 161 cbBarInfo* pBar = pRow->GetFirstBar();
8e08b761 162
c82c42d4
WS
163 bool rowChanged = false;
164// bool rowBkPainted = false;
8e08b761 165
4cbc57f0
JS
166 // FIXME:: the below should not be fixed
167 cbBarInfo* barsToRepaint[128];
168 // number of bars, that were changed in the current row
169 int nBars = 0;
8e08b761 170
12a3f227
RL
171 //wxRect r1 = pRow->mUMgrData.mPrevBounds;
172 //wxRect r2 = pRow->mBoundsInParent;
8e08b761 173
4cbc57f0
JS
174 if ( WasChanged( pRow->mUMgrData, pRow->mBoundsInParent ) )
175
c82c42d4 176 rowChanged = true;
4cbc57f0
JS
177 else
178 while( pBar )
179 {
180 if ( WasChanged( pBar->mUMgrData, pBar->mBoundsInParent ) )
181
182 barsToRepaint[nBars++] = pBar;
8e08b761 183
4cbc57f0
JS
184 pBar = pBar->mpNext;
185 }
8e08b761 186
4cbc57f0
JS
187 if ( nBars || rowChanged )
188 {
189 realBounds = pRow->mBoundsInParent;
8e08b761 190
4cbc57f0
JS
191 // include 1-pixel thick shades around the row
192 realBounds.x -= 1;
193 realBounds.y -= 1;
194 realBounds.width += 2;
195 realBounds.height += 2;
8e08b761 196
4cbc57f0
JS
197 pDc = pane.StartDrawInArea( realBounds );
198 }
8e08b761 199
4cbc57f0
JS
200 if ( rowChanged )
201 {
202 // postphone the resizement and refreshing the changed
203 // bar windows
8e08b761 204
4cbc57f0 205 cbBarInfo* pCurBar = pRow->GetFirstBar();
8e08b761 206
4cbc57f0
JS
207 while ( pCurBar )
208 {
209 if ( WasChanged( pCurBar->mUMgrData,
210 pCurBar->mBoundsInParent ) )
8e08b761 211
4cbc57f0
JS
212 AddItem( mBarsToResize, pCurBar, &pane,
213 pCurBar->mBoundsInParent,
214 pCurBar->mUMgrData.mPrevBounds );
8e08b761 215
4cbc57f0
JS
216 pCurBar = pCurBar->mpNext;
217 }
8e08b761 218
4cbc57f0 219 // draw only their decorations now
8e08b761 220
4cbc57f0
JS
221 pane.PaintRow( pRow, *pDc );
222 }
223 else
224 if ( nBars != 0 )
225 {
226 for ( int i = 0; i != nBars; ++i )
8e08b761 227
4cbc57f0
JS
228 // postphone the resizement and refreshing the changed
229 // bar windows
8e08b761 230
4cbc57f0
JS
231 AddItem( mBarsToResize,
232 barsToRepaint[i],
233 &pane,
234 barsToRepaint[i]->mBoundsInParent,
235 barsToRepaint[i]->mUMgrData.mPrevBounds );
8e08b761 236
4cbc57f0
JS
237 // redraw decorations of entire row, regardless of how much
238 // of the bars were changed
8e08b761 239
4cbc57f0
JS
240 pane.PaintRow( pRow, *pDc );
241 }
8e08b761 242
4cbc57f0
JS
243 if ( pDc )
244
245 pane.FinishDrawInArea( realBounds );
8e08b761 246
4cbc57f0 247 pRow = pRow->mpNext;
8e08b761 248
4cbc57f0 249 } // end of while
8e08b761 250
4cbc57f0
JS
251 if ( paneChanged )
252 {
253 wxClientDC dc( &mpLayout->GetParentFrame() );
254 pane.PaintPaneDecorations( dc );
255 }
8e08b761 256
4cbc57f0 257 } // end of for
8e08b761 258
4cbc57f0
JS
259 if ( clientWindowChanged && !mpLayout->mClientWndRefreshPending )
260 {
261 // ptr to client-window object is "marked" as NULL
8e08b761 262
4cbc57f0
JS
263 AddItem( mBarsToResize, NULL, NULL,
264 mpLayout->GetClientRect(),
265 mpLayout->GetPrevClientRect() );
266 }
8e08b761 267
4cbc57f0 268 // step #2 - do ordered refreshing and resizing of bar window objects now
8e08b761 269
4cbc57f0 270 DoRepositionItems( mBarsToResize );
8e08b761
JS
271}
272
273void cbGCUpdatesMgr::DoRepositionItems( wxList& items )
274{
8495ba53 275 wxNode* pNode1 = items.GetFirst();
8e08b761 276
4cbc57f0
JS
277 while( pNode1 )
278 {
279 cbRectInfo& info = node_to_rect_info( pNode1 );
8e08b761 280
8495ba53 281 wxNode* pNode2 = items.GetFirst();
8e08b761 282
4cbc57f0 283 // and node itself
8e08b761 284
4cbc57f0 285 mGC.AddObject( &info );
8e08b761 286
4cbc57f0
JS
287 while( pNode2 )
288 {
289 if ( pNode2 != pNode1 ) // node should not depend on itself
290 {
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
294 // other object.
8e08b761 295
4cbc57f0 296 cbRectInfo& otherInfo = node_to_rect_info( pNode2 );
8e08b761 297
4cbc57f0
JS
298 if ( rect_hits_rect( *info.mpCurBounds, *otherInfo.mpPrevBounds ) )
299
300 // the node depends on node
301 mGC.AddDependency( &info, &otherInfo );
302 }
8e08b761 303
8495ba53 304 pNode2 = pNode2->GetNext();
4cbc57f0 305 }
8e08b761 306
8495ba53 307 pNode1 = pNode1->GetNext();
4cbc57f0 308 }
8e08b761 309
4cbc57f0
JS
310 mGC.ArrangeCollection(); // order nodes according "least-dependency" rule,
311 // and find out cycled chains
8e08b761 312
4cbc57f0
JS
313 // Regular item nodes need to be resized, but not repainted (since
314 // they stand in linear (not cyclic) dependency with other
315 // regular nodes).
8e08b761 316
8495ba53 317 wxNode* pNode = mGC.GetRegularObjects().GetFirst();
8e08b761 318
4cbc57f0
JS
319 while ( pNode )
320 {
321 cbRectInfo& info = *((cbRectInfo*)gc_node_to_obj(pNode));
8e08b761 322
4cbc57f0
JS
323 if ( info.mpBar == NULL )
324
325 mpLayout->PositionClientWindow();
326 else
327 info.mpPane->SizeBar( info.mpBar );
8e08b761 328
8495ba53 329 pNode = pNode->GetNext();
4cbc57f0 330 }
8e08b761 331
4cbc57f0 332 // cycled item nodes, need to be both resized and repainted
8e08b761 333
8495ba53 334 pNode = mGC.GetCycledObjects().GetFirst();
8e08b761 335
4cbc57f0
JS
336 while ( pNode )
337 {
338 cbRectInfo& info = *((cbRectInfo*)gc_node_to_obj(pNode));
8e08b761 339
4cbc57f0
JS
340 if ( info.mpBar == NULL )
341 {
342 wxWindow* pClntWnd = mpLayout->GetFrameClient();
8e08b761 343
4cbc57f0 344 mpLayout->PositionClientWindow();
8e08b761 345
4cbc57f0 346 // FIXME FIXME:: excessive!
8e08b761 347
c82c42d4
WS
348 pClntWnd->Show( false );
349 pClntWnd->Show( true );
8e08b761 350
4cbc57f0
JS
351 // OLD STUFF:: mpLayout->PositionClientWindow();
352 }
353 else
354 if ( info.mpBar->mpBarWnd )
355 {
356 wxWindow* pWnd = info.mpBar->mpBarWnd;
8e08b761 357
4cbc57f0
JS
358 // resize
359 info.mpPane->SizeBar( info.mpBar );
8e08b761 360
4cbc57f0 361 // repaint
8e08b761 362
4cbc57f0 363 /* OLD STUFF:: bool isChoice = info.mpBar->IsKindOf( CLASSINFO( wxChoice ) );
8e08b761 364
4cbc57f0
JS
365 //#ifdef __WINDOWS__
366 //int result = ::SendMessage( (HWND)pWnd->m_hWnd, WM_NCPAINT, 0, 0 );
367 //#endif
368 */
8e08b761 369
4cbc57f0
JS
370 // FIXME FIXME:: there's no other way to repaint non-client area of the wxWindow!!
371 // so we do *excessive* "hide 'n show"
8e08b761 372
c82c42d4
WS
373 pWnd->Show(false);
374 pWnd->Show(true);
4cbc57f0
JS
375
376 pWnd->Refresh();
377 }
8e08b761 378
8495ba53 379 pNode = pNode->GetNext();
4cbc57f0 380 }
8e08b761 381
4cbc57f0 382 // release data prepared for GC alg.
8e08b761 383
8495ba53 384 pNode = items.GetFirst();
8e08b761 385
4cbc57f0
JS
386 while( pNode )
387 {
8495ba53 388 cbRectInfo* pInfo = (cbRectInfo*)(pNode->GetData());
8e08b761 389
4cbc57f0 390 delete pInfo;
8e08b761 391
8495ba53 392 pNode = pNode->GetNext();
4cbc57f0 393 }
8e08b761 394
4cbc57f0 395 mGC.Reset(); // reinit GC
8e08b761 396
4cbc57f0
JS
397 // FIXME:: this is a dirty-workaround for messy client-area,
398 // as a result of docking bar out of floated-container window
8e08b761 399
4cbc57f0
JS
400 if ( mpLayout->mClientWndRefreshPending )
401 {
402 mpLayout->PositionClientWindow();
403 mpLayout->GetFrameClient()->Refresh();
404 }
8e08b761
JS
405}
406