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