]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/fl/rowlayoutpl.cpp
minor corrections for compilation with gcc 3.3 (use cast of address instead
[wxWidgets.git] / contrib / src / fl / rowlayoutpl.cpp
CommitLineData
8e08b761 1/////////////////////////////////////////////////////////////////////////////
4cbc57f0
JS
2// Name: rowlayoutpl.cpp
3// Purpose: cbRowLayoutPlugin implementation.
8e08b761
JS
4// Author: Aleksandras Gluchovas
5// Modified by:
6// Created: 09/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Aleksandras Gluchovas
4cbc57f0 9// Licence: wxWindows licence
8e08b761
JS
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13 #pragma implementation "rowlayoutpl.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/rowlayoutpl.h"
28
29// exerimental "features" are still buggy
30#undef __EXPERIMENTAL
31
32/***** Implementation for class cbRowLayoutPlugin *****/
33
34IMPLEMENT_DYNAMIC_CLASS( cbRowLayoutPlugin, cbPluginBase )
35
36BEGIN_EVENT_TABLE( cbRowLayoutPlugin, cbPluginBase )
37
11a68fa3
GT
38 EVT_PL_LAYOUT_ROW ( cbRowLayoutPlugin::OnLayoutRow )
39 EVT_PL_LAYOUT_ROWS( cbRowLayoutPlugin::OnLayoutRows )
40 EVT_PL_RESIZE_ROW ( cbRowLayoutPlugin::OnResizeRow )
8e08b761 41
11a68fa3
GT
42 EVT_PL_INSERT_BAR ( cbRowLayoutPlugin::OnInsertBar )
43 EVT_PL_REMOVE_BAR ( cbRowLayoutPlugin::OnRemoveBar )
8e08b761
JS
44
45END_EVENT_TABLE()
46
47cbRowLayoutPlugin::cbRowLayoutPlugin(void)
11a68fa3 48 : mpPane( 0 )
8e08b761
JS
49{}
50
51cbRowLayoutPlugin::cbRowLayoutPlugin( wxFrameLayout* pPanel, int paneMask )
52
11a68fa3
GT
53 : cbPluginBase( pPanel, paneMask ),
54 mpPane( 0 )
8e08b761
JS
55{}
56
57void cbRowLayoutPlugin::CheckIfAtTheBoundary( cbBarInfo* pTheBar, cbRowInfo& rowInfo )
58{
11a68fa3
GT
59 // this method handles situation, when fixed bar is inserted
60 // into the row, where among fixed bars not-fixed ones are present.
61 // In this case we need to check if the pBarNode appears to be inserted
62 // chain of fixed-bars on the very right or left side of the row,
63 // then all the white-space, such chain should be eliminated,
64 // and the resulting chain justified to the right or the left
65 // side of the row
8e08b761 66
11a68fa3 67 if ( !pTheBar->IsFixed() || rowInfo.mHasOnlyFixedBars )
8e08b761 68
11a68fa3 69 return;
8e08b761 70
11a68fa3 71 cbBarInfo* pBar = rowInfo.mBars[ rowInfo.mBars.Count() - 1 ];
8e08b761 72
11a68fa3 73 // slide fixed bars to the right on the right side relative to the pBarNode
8e08b761 74
11a68fa3 75 int prevX = mpPane->mPaneWidth;
8e08b761 76
11a68fa3
GT
77 do
78 {
79 if ( !pBar->IsFixed() )
80 break;
8e08b761 81
11a68fa3 82 wxRect& bounds = pBar->mBounds;
8e08b761 83
11a68fa3 84 bounds.x = prevX - bounds.width;
8e08b761 85
11a68fa3 86 prevX = bounds.x;
8e08b761 87
11a68fa3 88 if ( pBar == pTheBar ) break;
8e08b761 89
11a68fa3
GT
90 pBar = pBar->mpPrev;
91 }
92 while( 1 );
8e08b761 93
11a68fa3 94 // slide fixed bars to the left on the left side relative to the pBarNode
8e08b761 95
11a68fa3 96 pBar = rowInfo.mBars[0];
8e08b761 97
11a68fa3
GT
98 prevX = 0;
99
100 do
101 {
102 if ( pBar->IsFixed() )
8e08b761 103
11a68fa3 104 break;
8e08b761 105
11a68fa3 106 wxRect& bounds = pBar->mBounds;
8e08b761 107
11a68fa3 108 bounds.x = prevX;
8e08b761 109
11a68fa3 110 prevX = bounds.x + bounds.width;
8e08b761 111
11a68fa3 112 if ( pBar == pTheBar ) break;
8e08b761 113
11a68fa3
GT
114 pBar = pBar->mpNext;
115 }
116 while( 1 );
8e08b761
JS
117}
118
119void cbRowLayoutPlugin::ExpandNotFixedBars( cbRowInfo* pRow )
120{
11a68fa3 121 ApplyLengthRatios( pRow );
8e08b761 122
11a68fa3
GT
123 // FIXME:: something's wrong?
124 return;
8e08b761 125
11a68fa3 126 double freeSpc = (double)GetRowFreeSpace( pRow );
8e08b761 127
11a68fa3 128 // calculate sum of precents
8e08b761 129
11a68fa3 130 double pcntSum = 0.0;
8e08b761 131
11a68fa3
GT
132 size_t i;
133 for ( i = 0; i != pRow->mBars.Count(); ++i )
134 {
135 if ( !pRow->mBars[i]->IsFixed() )
136 pcntSum += pRow->mBars[i]->mLenRatio;
137 }
8e08b761 138
11a68fa3 139 // setup bar lengths
8e08b761 140
11a68fa3 141 int curX = 0;
8e08b761 142
11a68fa3
GT
143 for ( i = 0; i != pRow->mBars.Count(); ++i )
144 {
145 cbBarInfo& bar = *pRow->mBars[i];
146
147 if ( !bar.IsFixed() )
148 {
149 bar.mLenRatio = bar.mLenRatio/(pcntSum);
150
151 bar.mBounds.width =
152
153 wxMax( mpPane->mProps.mMinCBarDim.x, int( freeSpc*bar.mLenRatio ) );
154 }
155
156 bar.mBounds.x = curX;
157 curX = bar.mBounds.x + bar.mBounds.width;
158 }
8e08b761
JS
159}
160
161void cbRowLayoutPlugin::AdjustLengthOfInserted( cbRowInfo* pRow, cbBarInfo* pTheBar )
162{
11a68fa3 163 return; // TBD: Makes following code unreachable
8e08b761 164
11a68fa3 165 // pTheBar is not-fixed
8e08b761
JS
166
167
11a68fa3 168 // FIXME:: what is this for??
8e08b761
JS
169
170#if 1
171
11a68fa3 172 int totalLen = 0;
8e08b761
JS
173
174 size_t i;
11a68fa3 175 for ( i = 0; i != pRow->mBars.Count(); ++i )
8e08b761 176 {
11a68fa3
GT
177 if ( !pRow->mBars[i]->IsFixed() )
178 totalLen += pRow->mBars[i]->mBounds.width;
8e08b761
JS
179 }
180
11a68fa3 181 double curWidth = pTheBar->mBounds.width;
8e08b761 182
11a68fa3 183 if ( pRow->mBars.Count() )
8e08b761 184
11a68fa3 185 pTheBar->mBounds.width = int( mpPane->mPaneWidth * (curWidth / double(totalLen)) );
8e08b761
JS
186#else
187
11a68fa3 188 double freeSpc = (double)GetRowFreeSpace( pRow );
8e08b761 189
11a68fa3 190 double pcntSum = 0.0;
8e08b761 191
11a68fa3
GT
192 size_t i;
193 for ( i = 0; i != pRow->mBars.Count(); ++i )
194 {
195 if ( !pRow->mBars[i]->IsFixed() )
196 pcntSum += pRow->mBars[i]->mLenRatio;
197 }
8e08b761 198
11a68fa3
GT
199 // if no longer "balanced", assume that `pTheBar' was previously
200 // removed from this row (kind of AI...)
8e08b761 201
11a68fa3
GT
202 if ( pcntSum < 0.98 )
203
204 pTheBar->mBounds.width = freeSpc * (1.0 - pcntSum);
8e08b761
JS
205#endif
206}
207
11a68fa3
GT
208void cbRowLayoutPlugin::FitBarsToRange( int from, int till,
209 cbBarInfo* pTheBar, cbRowInfo* pRow )
8e08b761 210{
11a68fa3
GT
211 cbBarInfo* pFromBar = NULL;
212 cbBarInfo* pTillBar = NULL;
213
214 if ( pTheBar->mBounds.x > from )
215 {
216 // it's range from the left
217 pFromBar = pRow->mBars[0];
218 pTillBar = pTheBar;
219 }
220 else
221 {
222 pFromBar = pTheBar->mpNext;
223 pTillBar = NULL;
224 }
225
226 // calc free space in the range
227
228 cbBarInfo* pBar = pFromBar;
229 int freeSpc = till-from;
230 double pcntSum = 0;
231
232 while( pBar != pTillBar )
233 {
234 if ( pBar->IsFixed() )
235 freeSpc -= pBar->mBounds.width;
236 else
237 pcntSum += pBar->mLenRatio;
238
239 pBar = pBar->mpNext;
240 }
241
242 // adjust not-fixed bar sizes in the range
243
244 pBar = pFromBar;
245
246 while ( pBar != pTillBar )
247 {
248 if ( !pBar->IsFixed() )
249 {
250 pBar->mBounds.width =
251 wxMax( mpPane->mProps.mMinCBarDim.x,
252 int( double(freeSpc) * (pBar->mLenRatio/pcntSum) )
253 );
254 }
255 pBar = pBar->mpNext;
256 }
257
258 // layout range, starting from the left-most bar
259
260 pBar = pFromBar;
261 int prevX = from;
262 bool hasNotFixedBars = FALSE;
263
264 while ( pBar != pTillBar )
265 {
266 wxRect& bounds = pBar->mBounds;
267
268 if ( !pBar->IsFixed() )
269 {
270 hasNotFixedBars = TRUE;
271
272 freeSpc -= bounds.width;
273 }
274
275 bounds.x = prevX;
276
277 prevX = bounds.x + bounds.width;
278
279 pBar = pBar->mpNext;
280 }
281
282 // make width adjustment for the right-most bar in the range, due to
283 // lost precision when seting widths using f.p. length-ratios
284
285 if ( hasNotFixedBars )
286 {
287 if ( pTheBar->mBounds.x > from )
288 {
289 if ( pTillBar->mpPrev )
290 {
291 wxRect& tillBar = pTillBar->mpPrev->mBounds;
292
293 //tillBar.width = bar.mBounds.x - tillBar.x;
294 tillBar.width += freeSpc;
295 }
296 }
297 else
298 {
299 cbBarInfo* pLast = pRow->mBars[ pRow->mBars.Count() - 1 ];
300
301 if ( pLast != pTheBar )
302 {
303 pTheBar->mBounds.width += freeSpc;
304
305 SlideRightSideBars( pTheBar );
306 }
307 }
308 }
8e08b761
JS
309}
310
311void cbRowLayoutPlugin::MinimzeNotFixedBars( cbRowInfo* pRow, cbBarInfo* pBarToPreserve )
312{
313 size_t i;
11a68fa3 314 for ( i = 0; i != pRow->mBars.Count(); ++i )
8e08b761 315 {
11a68fa3
GT
316 if ( !pRow->mBars[i]->IsFixed() && pRow->mBars[i] != pBarToPreserve )
317 pRow->mBars[i]->mBounds.width = mpPane->mProps.mMinCBarDim.x;
8e08b761
JS
318 }
319}
320
321int cbRowLayoutPlugin::GetRowFreeSpace( cbRowInfo* pRow )
322{
11a68fa3 323 int freeSpc = mpPane->mPaneWidth;
8e08b761
JS
324
325 size_t i;
11a68fa3 326 for ( i = 0; i != pRow->mBars.Count(); ++i )
8e08b761 327 {
11a68fa3
GT
328 // not-fixed bars variable length, thus their
329 // dimensions are ignored
330 if ( pRow->mBars[i]->IsFixed() )
331 freeSpc -= pRow->mBars[i]->mBounds.width;
8e08b761
JS
332 }
333
11a68fa3 334 return freeSpc;
8e08b761
JS
335}
336
337void cbRowLayoutPlugin::RecalcLengthRatios( cbRowInfo* pRow )
338{
11a68fa3 339 double freeSpc = double( GetRowFreeSpace( pRow ) );
8e08b761 340
11a68fa3
GT
341 cbBarInfo* pBar = pRow->mBars[0];
342 cbBarInfo* pLastNotFixed = NULL;
8e08b761 343
11a68fa3 344 double pcntLeft = 1.0; // (100%)
8e08b761
JS
345
346#ifdef __EXPERIMENTAL
347
11a68fa3 348 int totalLen = 0;
8e08b761
JS
349
350 size_t i;
11a68fa3 351 for ( i = 0; i != pRow->mBars.Count(); ++i )
8e08b761 352 {
11a68fa3
GT
353 if ( !pRow->mBars[i]->IsFixed() )
354 totalLen += pRow->mBars[i]->mBounds.width;
8e08b761
JS
355 }
356#endif
357
358 size_t i;
11a68fa3
GT
359 for ( i = 0; i != pRow->mBars.Count(); ++i )
360 {
361 cbBarInfo& bar = *pRow->mBars[i];
8e08b761 362
11a68fa3
GT
363 if ( !bar.IsFixed() )
364 {
8e08b761
JS
365
366#ifdef __EXPERIMENTAL
367
11a68fa3 368 bar.mLenRatio = double(bar.mBounds.width)/double(totalLen);
8e08b761 369#else
11a68fa3 370 bar.mLenRatio = double(bar.mBounds.width)/freeSpc;
8e08b761
JS
371#endif
372
11a68fa3
GT
373 pcntLeft -= bar.mLenRatio;
374 pLastNotFixed = pBar;
375 }
376 }
8e08b761 377
11a68fa3
GT
378 // attach remainder (the result of lost precision) to the
379 // last not-fixed bar
8e08b761 380
11a68fa3 381#if !defined(__EXPERIMENTAL)
8e08b761 382
11a68fa3
GT
383 if ( pLastNotFixed )
384
385 pLastNotFixed->mLenRatio += pcntLeft;
8e08b761
JS
386#endif
387
388}
389
390void cbRowLayoutPlugin::ApplyLengthRatios( cbRowInfo* pRow )
391{
11a68fa3 392 double pcntSum = 0;
8e08b761 393
11a68fa3 394 // FOR NOW:: all-in-one
8e08b761 395
11a68fa3
GT
396 size_t i = 0;
397 for ( i = 0; i != pRow->mBars.Count(); ++i )
8e08b761 398 {
11a68fa3
GT
399 if ( !pRow->mBars[i]->IsFixed() )
400 pcntSum += pRow->mBars[i]->mLenRatio;
8e08b761
JS
401 }
402
11a68fa3
GT
403 /*
404 pBar = node_to_first_bar_node( pRow );
405
406 while( pBar )
407 {
408 cbBarInfo& bar = node_to_bar( pBar );
409
410 if ( !bar.IsFixed() )
411
412 bar.mLenRatio = pcntSum / bar.mLenRatio;
413
414 pBar = pBar->Next();
415 }
416 */
417
418 int prevX = 0;
419 double freeSpc = GetRowFreeSpace( pRow );
420
421 // tricky stuff (improtant!):
422 // when not-fixed bar is removed from the row and there are
423 // still some other not-fixed ones left in that row, then
424 // the sum of mLenRatio's is no longer 1.0 - this is left
425 // intintionally to handle the case when the removed bar
426 // is returned right back to the row - so that it would retain
427 // it's original dimensions in this row (this is kind of AI...)
428 //
429 // The problem is - when it's remvoed, the sum of
430 // mLenRatio's is not in "balance", i.e. is < 1.0,
431 // it's possible to restore balance, but instead of that
432 // we artifically ajdust freeSpc value in a way that it would
433 // look like total of mLetRatio's is 1.0, thus original
434 // len. ratios are _preserved_:
435
8ca3dfcd
JS
436 if (pcntSum == 0.0)
437 pcntSum = 1.0;
438
11a68fa3
GT
439 double unit = freeSpc / pcntSum;
440
441 bool haveSquished = FALSE;
442
443 for ( i = 0; i != pRow->mBars.Count(); ++i )
8e08b761 444 {
11a68fa3
GT
445 if ( !pRow->mBars[i]->IsFixed() )
446 {
447 cbBarInfo& bar = *pRow->mBars[i];
448
449 if ( int( unit * bar.mLenRatio ) < mpPane->mProps.mMinCBarDim.x )
450 {
451 haveSquished = TRUE;
8e08b761 452
11a68fa3 453 bar.mBounds.width = -1; // mark as "squished"
8e08b761 454
11a68fa3 455 pcntSum -= bar.mLenRatio;
8e08b761 456
11a68fa3
GT
457 freeSpc -= mpPane->mProps.mMinCBarDim.x;
458 }
459 }
8e08b761
JS
460 } // for
461
11a68fa3
GT
462 if ( haveSquished )
463 unit = freeSpc / pcntSum;
8e08b761 464
11a68fa3
GT
465 for ( i = 0; i != pRow->mBars.Count(); ++i )
466 {
467 cbBarInfo& bar = *pRow->mBars[i];
8e08b761 468
11a68fa3 469 bar.mBounds.x = prevX;
8e08b761 470
11a68fa3
GT
471 if ( !bar.IsFixed() )
472 {
473 if ( bar.mBounds.width == -1 )
8e08b761 474
11a68fa3
GT
475 bar.mBounds.width = mpPane->mProps.mMinCBarDim.x;
476 else
477 bar.mBounds.width = int( unit * bar.mLenRatio );
8e08b761 478
11a68fa3
GT
479 // a little bit of AI:
480 // memorize bar's height and width, when docked in
481 // the current orientation - by making the current
482 // dimensions to be "preffered" ones for this docking state
8e08b761 483
11a68fa3
GT
484 if ( !bar.IsFixed() )
485 {
486 bar.mDimInfo.mSizes[ bar.mState ].x = bar.mBounds.width;
487 bar.mDimInfo.mSizes[ bar.mState ].y = bar.mBounds.height;
488 }
489 }
8e08b761 490
11a68fa3
GT
491 prevX = bar.mBounds.x + bar.mBounds.width;
492 }
8e08b761
JS
493}
494
495void cbRowLayoutPlugin::DetectBarHandles( cbRowInfo* pRow )
496{
11a68fa3 497 // first pass from left to right (detect left-side handles)
8e08b761 498
11a68fa3 499 bool foundNotFixed = FALSE;
8e08b761
JS
500
501 size_t i;
11a68fa3
GT
502 for ( i = 0; i != pRow->mBars.Count(); ++i )
503 {
504 cbBarInfo& bar = *pRow->mBars[i];
505
506 bar.mHasLeftHandle = FALSE;
507
508 if ( !bar.IsFixed() )
509 {
510 if ( foundNotFixed )
511
512 if ( bar.mpPrev &&
513 bar.mpPrev->IsFixed() )
514
515 bar.mHasLeftHandle = TRUE;
516
517 foundNotFixed = TRUE;
518 }
519 }
8e08b761 520
11a68fa3 521 // pass from right to left (detect right-side handles)
8e08b761 522
11a68fa3 523 foundNotFixed = FALSE;
8e08b761 524
11a68fa3 525 cbBarInfo* pBar = pRow->mBars[ pRow->mBars.Count() - 1 ];
8e08b761 526
11a68fa3
GT
527 while( pBar )
528 {
529 pBar->mHasRightHandle = FALSE;
8e08b761 530
11a68fa3
GT
531 if ( !pBar->IsFixed() )
532 {
533 if ( foundNotFixed )
8e08b761 534
11a68fa3 535 if ( pBar->mpNext )
8e08b761 536
11a68fa3 537 pBar->mHasRightHandle = TRUE;
8e08b761 538
11a68fa3
GT
539 foundNotFixed = TRUE;
540 }
8e08b761 541
11a68fa3
GT
542 pBar = pBar->mpPrev;
543 }
8e08b761
JS
544}
545
546void cbRowLayoutPlugin::RelayoutNotFixedBarsAround( cbBarInfo* pTheBar, cbRowInfo* pRow )
547{
11a68fa3
GT
548 if ( !pTheBar->mpPrev )
549 {
550 if ( !pTheBar->IsFixed() )
551 {
552 // this bar the first in the row, move it's
553 // left edge to the very left
554 pTheBar->mBounds.width += pTheBar->mBounds.x;
555 pTheBar->mBounds.x = 0;
556 }
557 }
558 else
559 FitBarsToRange( 0, pTheBar->mBounds.x, pTheBar, pRow );
560
561 if ( !pTheBar->mpNext )
562 {
563 if ( !pTheBar->IsFixed() )
564 {
565 // this bar is the last one, move it's
566 // right edge to the very right
567
568 pTheBar->mBounds.width = mpPane->mPaneWidth - pTheBar->mBounds.x;
569 }
570 }
571 else
572 FitBarsToRange( pTheBar->mBounds.x + pTheBar->mBounds.width, mpPane->mPaneWidth,
573 pTheBar, pRow
574 );
8e08b761
JS
575}
576
577void cbRowLayoutPlugin::LayoutItemsVertically( cbRowInfo& row )
578{
579 size_t i;
11a68fa3
GT
580 for ( i = 0; i != row.mBars.Count(); ++i )
581 {
582 cbBarInfo& bar = *row.mBars[i];
8e08b761 583
11a68fa3 584 bar.mBounds.y = row.mRowY;
8e08b761 585
11a68fa3 586 if ( !bar.IsFixed() )
8e08b761 587
11a68fa3
GT
588 // make all not-fixed bars of equal height
589 bar.mBounds.height = row.mRowHeight;
8e08b761 590
11a68fa3 591 if ( row.mHasUpperHandle )
8e08b761 592
11a68fa3
GT
593 bar.mBounds.y += mpPane->mProps.mResizeHandleSize;
594 }
8e08b761
JS
595}
596
597int cbRowLayoutPlugin::CalcRowHeight( cbRowInfo& row )
598{
11a68fa3 599 int maxHeight = 0;
8e08b761
JS
600
601 size_t i;
11a68fa3
GT
602 for ( i = 0; i != row.mBars.Count(); ++i )
603
604 maxHeight = wxMax( maxHeight, row.mBars[i]->mBounds.height );
8e08b761 605
11a68fa3 606 return maxHeight;
8e08b761
JS
607}
608
609void cbRowLayoutPlugin::StickRightSideBars( cbBarInfo* pToBar )
610{
11a68fa3
GT
611 cbBarInfo* pBar = pToBar->mpNext;
612 cbBarInfo* pPrev = pToBar;
8e08b761 613
11a68fa3
GT
614 while( pBar )
615 {
616 wxRect& cur = pBar->mBounds;
617 wxRect& prev = pPrev->mBounds;
8e08b761 618
11a68fa3 619 cur.x = prev.x + prev.width;
8e08b761 620
11a68fa3
GT
621 pPrev = pBar;
622 pBar = pBar->mpNext;
623 }
8e08b761
JS
624}
625
626void cbRowLayoutPlugin::SlideLeftSideBars( cbBarInfo* pTheBar )
627{
11a68fa3
GT
628 // shift left-side-bars to the left (with respect to "theBar"),
629 // so that they would not obscured by each other
8e08b761 630
11a68fa3
GT
631 cbBarInfo* pBar = pTheBar->mpPrev;
632 cbBarInfo* pPrev = pTheBar;
8e08b761 633
11a68fa3
GT
634 while( pBar )
635 {
636 wxRect& cur = pBar->mBounds;
637 wxRect& prev = pPrev->mBounds;
8e08b761 638
11a68fa3 639 if ( cur.x + cur.width > prev.x )
8e08b761 640
11a68fa3 641 cur.x = prev.x - cur.width;
8e08b761 642
11a68fa3
GT
643 pPrev = pBar;
644 pBar = pBar->mpPrev;
645 }
8e08b761
JS
646}
647
648void cbRowLayoutPlugin::SlideRightSideBars( cbBarInfo* pTheBar )
649{
11a68fa3
GT
650 // shift right-side-bars to the right (with respect to "theBar"),
651 // so that they would not be obscured by each other
8e08b761 652
11a68fa3
GT
653 cbBarInfo* pBar = pTheBar->mpNext;
654 cbBarInfo* pPrev = pTheBar;
8e08b761 655
11a68fa3
GT
656 while( pBar )
657 {
658 wxRect& cur = pBar->mBounds;
659 wxRect& prev = pPrev->mBounds;
8e08b761 660
11a68fa3 661 if ( cur.x < prev.x + prev.width )
8e08b761 662
11a68fa3 663 cur.x = prev.x + prev.width;
8e08b761 664
11a68fa3
GT
665 pPrev = pBar;
666 pBar = pBar->mpNext;
667 }
8e08b761
JS
668}
669
670void cbRowLayoutPlugin::ShiftLeftTrashold( cbBarInfo* pTheBar, cbRowInfo& row )
671{
11a68fa3 672 wxRect& first = row.mBars[0]->mBounds;
8e08b761 673
11a68fa3
GT
674 if ( first.x < 0 )
675 {
676 row.mBars[0]->mBounds.x = 0;
8e08b761 677
11a68fa3
GT
678 SlideRightSideBars( row.mBars[0] );
679 }
8e08b761
JS
680}
681
682void cbRowLayoutPlugin::ShiftRightTrashold( cbBarInfo* pTheBar, cbRowInfo& row )
683{
11a68fa3 684 wxRect& theBar = pTheBar->mBounds;
8e08b761 685
11a68fa3
GT
686 do
687 {
688 cbBarInfo* pBar = pTheBar;
8e08b761 689
11a68fa3 690 // calculate free spece on the left side
8e08b761 691
11a68fa3 692 int leftFreeSpc = 0;
8e08b761 693
11a68fa3
GT
694 while( pBar )
695 {
696 wxRect& cur = pBar->mBounds;
8e08b761 697
11a68fa3
GT
698 if ( pBar->mpPrev )
699 {
700 wxRect& prev = pBar->mpPrev->mBounds;
8e08b761 701
11a68fa3
GT
702 leftFreeSpc += cur.x - prev.x - prev.width;
703 }
704 else
705 leftFreeSpc += cur.x;
8e08b761 706
11a68fa3
GT
707 if ( cur.x < 0 )
708 {
709 leftFreeSpc = 0;
710 break;
711 }
8e08b761 712
11a68fa3
GT
713 pBar = pBar->mpPrev;
714 }
8e08b761 715
11a68fa3 716 pBar = pTheBar;
8e08b761 717
11a68fa3 718 int rightOverflow = 0;
8e08b761 719
11a68fa3 720 if ( pTheBar->IsFixed() )
8e08b761 721
11a68fa3
GT
722 while( pBar )
723 {
724 if ( !pBar->mpNext )
725 {
726 wxRect& cur = pBar->mBounds;
8e08b761 727
11a68fa3 728 if ( cur.x + cur.width > mpPane->mPaneWidth )
8e08b761 729
11a68fa3
GT
730 rightOverflow = cur.x + cur.width - mpPane->mPaneWidth;
731 }
8e08b761 732
11a68fa3
GT
733 pBar = pBar->mpNext;
734 }
8e08b761 735
11a68fa3
GT
736 if ( rightOverflow > 0 )
737 {
738 if ( leftFreeSpc <= 0 ) return;
8e08b761 739
11a68fa3
GT
740 if ( pTheBar->mpNext )
741 {
742 wxRect& next = pTheBar->mpNext->mBounds;
8e08b761 743
11a68fa3
GT
744 // if there's enough space on the left, move over one half-obscured
745 // bar from the right to the left side with respect to "theBar"
8e08b761 746
11a68fa3
GT
747 if ( next.width < leftFreeSpc )
748 {
749 cbBarInfo* pNext = pTheBar->mpNext;
8e08b761 750
11a68fa3 751 row.mBars.Remove( pNext );
8e08b761 752
11a68fa3 753 row.mBars.Insert( pNext, row.mBars.Index( pTheBar ) );
8e08b761 754
11a68fa3 755 next.x = theBar.x - next.width;
8e08b761 756
11a68fa3 757 // re-setup mpPrev/mpNext references after insertion
8e08b761 758
11a68fa3 759 mpPane->InitLinksForRow( &row );
8e08b761 760
11a68fa3 761 // tighten things
8e08b761 762
11a68fa3
GT
763 StickRightSideBars( pTheBar );
764 SlideLeftSideBars ( pTheBar );
8e08b761 765
11a68fa3
GT
766 continue;
767 }
768 }
8e08b761 769
11a68fa3
GT
770 int leftShift = ( rightOverflow > leftFreeSpc )
771 ? leftFreeSpc
772 : rightOverflow;
8e08b761 773
11a68fa3 774 theBar.x -= leftShift;
8e08b761 775
11a68fa3
GT
776 StickRightSideBars( pTheBar );
777 SlideLeftSideBars ( pTheBar );
8e08b761 778
11a68fa3 779 break;
8e08b761 780
11a68fa3
GT
781 } // end of if ( rightOverflow )
782 else
783 break;
8e08b761 784
11a68fa3 785 } while(1);
8e08b761
JS
786}
787
788void cbRowLayoutPlugin::InsertBefore( cbBarInfo* pBeforeBar,
11a68fa3
GT
789 cbBarInfo* pTheBar,
790 cbRowInfo& row )
8e08b761 791{
11a68fa3 792 if ( pBeforeBar )
8e08b761 793
11a68fa3
GT
794 row.mBars.Insert( pTheBar, row.mBars.Index( pBeforeBar ) );
795 else
796 row.mBars.Add( pTheBar );
8e08b761 797
11a68fa3 798 pTheBar->mpRow = &row;
8e08b761
JS
799}
800
801void cbRowLayoutPlugin::DoInsertBar( cbBarInfo* pTheBar, cbRowInfo& row )
802{
11a68fa3 803 wxRect& theBar = pTheBar->mBounds;
8e08b761 804
11a68fa3
GT
805 /* OLD STUFF::
806 if ( theBar.x < 0 && !node_to_bar( pTheBar ).IsFixed() )
807 {
808 // AI::
809 theBar.width += theBar.x;
810 theBar.x = 0;
811 } */
8e08b761
JS
812
813 size_t i;
11a68fa3
GT
814 for ( i = 0; i != row.mBars.Count(); ++i )
815 {
816 cbBarInfo& bar = *row.mBars[i];
817
818 wxRect& cur = bar.mBounds;
819
820 // if bar hits the left edge
821 if ( theBar.x <= cur.x )
822 {
823 InsertBefore( &bar, pTheBar, row );
824 return;
825 }
826
827 else
828 // if bar hits the right edge
829 if ( theBar.x <= cur.x + cur.width )
830 {
831 if ( theBar.x + theBar.width > cur.x + cur.width )
832 {
833 InsertBefore( bar.mpNext, pTheBar, row );
834 return;
835 }
836
837 // otherwise the bar lies within the bounds of current bar
838
839 int leftDist = theBar.x - cur.x;
840 int rightDist = cur.x + cur.width - (theBar.x + theBar.width);
841
842 if ( leftDist < rightDist )
843
844 InsertBefore( &bar, pTheBar, row );
845 else
846 InsertBefore( bar.mpNext, pTheBar, row );
847
848 return;
849 }
850 }
851
852 InsertBefore( NULL, pTheBar, row ); // insert at the end
8e08b761
JS
853}
854
855// evnet handlers
856
857void cbRowLayoutPlugin::OnInsertBar( cbInsertBarEvent& event )
858{
11a68fa3
GT
859 cbBarInfo* pBarToInsert = event.mpBar;
860 cbRowInfo* pIntoRow = event.mpRow;
861 mpPane = event.mpPane;
8e08b761 862
11a68fa3 863 if ( !pBarToInsert->IsFixed() )
8e08b761 864
11a68fa3 865 AdjustLengthOfInserted( pIntoRow, pBarToInsert );
8e08b761 866
11a68fa3 867 DoInsertBar( pBarToInsert, *pIntoRow );
8e08b761 868
11a68fa3 869 mpPane->InitLinksForRow( pIntoRow ); // relink "mpNext/mpPrev"s
8e08b761 870
11a68fa3 871 // perform relayouting of the bars after insertion
8e08b761 872
11a68fa3
GT
873 // init bar location info
874 pBarToInsert->mAlignment = event.mpPane->mAlignment;
875 pBarToInsert->mRowNo = event.mpPane->GetRowIndex( pIntoRow );
8e08b761
JS
876
877#ifdef __EXPERIMENTAL
878
11a68fa3 879 if ( !pIntoRow->mHasOnlyFixedBars || !pBarToInsert->IsFixed() )
8e08b761 880
11a68fa3 881 RecalcLengthRatios( pIntoRow );
8e08b761
JS
882
883#endif
884
11a68fa3 885 MinimzeNotFixedBars( pIntoRow, pBarToInsert );
8e08b761 886
11a68fa3
GT
887 SlideLeftSideBars ( pBarToInsert );
888 SlideRightSideBars( pBarToInsert );
8e08b761 889
11a68fa3
GT
890 ShiftLeftTrashold ( pBarToInsert, *pIntoRow );
891 ShiftRightTrashold( pBarToInsert, *pIntoRow );
8e08b761 892
11a68fa3 893 mpPane->SyncRowFlags( pIntoRow );
8e08b761 894
11a68fa3 895 CheckIfAtTheBoundary( pBarToInsert, *pIntoRow );
8e08b761 896
11a68fa3 897 if ( event.mpPane->IsHorizontal() )
8e08b761 898
11a68fa3
GT
899 pBarToInsert->mState = wxCBAR_DOCKED_HORIZONTALLY;
900 else
901 pBarToInsert->mState = wxCBAR_DOCKED_VERTICALLY;
8e08b761 902
11a68fa3
GT
903 if ( !pIntoRow->mHasOnlyFixedBars )
904 {
8e08b761
JS
905
906#ifdef __EXPERIMENTAL
907
11a68fa3 908 ExpandNotFixedBars( pIntoRow );
8e08b761
JS
909#else
910
11a68fa3
GT
911 RelayoutNotFixedBarsAround( pBarToInsert, pIntoRow );
912 RecalcLengthRatios( pIntoRow );
8e08b761
JS
913
914#endif
915
11a68fa3 916 DetectBarHandles( pIntoRow );
8e08b761 917
11a68fa3
GT
918 // do proportional resizing of not-fixed bars
919 ApplyLengthRatios( pIntoRow );
920 }
8e08b761 921
11a68fa3 922 // adjust the bar's docking state
8e08b761 923
11a68fa3
GT
924 // a little bit of AI:
925 // memorize bar's height and width, when docked in
926 // the current orientation - by making the current
927 // dimensions to be "preferred" ones for this docking state
8e08b761 928
11a68fa3
GT
929 if ( !pBarToInsert->IsFixed() )
930 {
931 cbBarInfo& bar = *pBarToInsert;
8e08b761 932
11a68fa3
GT
933 bar.mDimInfo.mSizes[ bar.mState ].x = bar.mBounds.width;
934 bar.mDimInfo.mSizes[ bar.mState ].y = bar.mBounds.height;
935 }
8e08b761
JS
936}
937
938void cbRowLayoutPlugin::OnRemoveBar ( cbRemoveBarEvent& event )
939{
11a68fa3
GT
940 cbBarInfo* pBar = event.mpBar;
941 mpPane = event.mpPane;
8e08b761 942
11a68fa3 943 cbRowInfo* pRow = pBar->mpRow;
8e08b761 944
11a68fa3 945 mpLayout->GetUpdatesManager().OnBarWillChange( pBar, pRow, event.mpPane );
8e08b761 946
11a68fa3
GT
947 // invalidate the whole row
948 //pFirst->mpRowInfo->mMgrData.mPrevBounds.x = -1;
8e08b761 949
11a68fa3 950 pRow->mBars.Remove( pBar );
8e08b761 951
11a68fa3
GT
952 // rest bar information after removing it from the row
953 pBar->mpRow = NULL;
954 pBar->mHasLeftHandle = FALSE;
955 pBar->mHasRightHandle = FALSE;
8e08b761 956
11a68fa3 957 mpPane->InitLinksForRow( pRow ); // relink "mpNext/mpPrev"s
8e08b761 958
11a68fa3
GT
959 if ( pRow->mBars.Count() == 0 )
960 {
961 // empty rows should not exist
8e08b761 962
11a68fa3 963 event.mpPane->GetRowList().Remove( pRow );
8e08b761 964
11a68fa3 965 delete pRow;
8e08b761 966
11a68fa3
GT
967 mpPane->InitLinksForRows();
968 }
969 else
970 {
971 // force repainting of bars, in the row, from which the bar was removed
8e08b761 972
11a68fa3
GT
973 // FIXME:: really needed?
974 pRow->mBars[0]->mUMgrData.SetDirty(TRUE);
8e08b761 975
11a68fa3
GT
976 // re-setup mHasOnlyFixedBars flag for the row information
977 event.mpPane->SyncRowFlags( pRow );
8e08b761 978
11a68fa3 979 DetectBarHandles( pRow );
8e08b761 980
11a68fa3 981 if ( !pRow->mHasOnlyFixedBars )
8e08b761 982
11a68fa3
GT
983 ExpandNotFixedBars( pRow );
984 }
8e08b761
JS
985}
986
987void cbRowLayoutPlugin::OnLayoutRow( cbLayoutRowEvent& event )
988{
11a68fa3
GT
989 cbRowInfo* pRow = event.mpRow;
990 mpPane = event.mpPane;
8e08b761 991
11a68fa3 992 MinimzeNotFixedBars( pRow, NULL );
8e08b761 993
11a68fa3
GT
994 if ( !pRow->mHasOnlyFixedBars )
995 {
996 // do proportional resizing of not-fixed bars
997 ApplyLengthRatios( pRow );
998 }
8e08b761 999
11a68fa3
GT
1000 cbBarInfo& lastBar = *pRow->mBars[ pRow->mBars.Count() - 1 ];
1001 cbBarInfo& firstBar = *pRow->mBars[ 0 ];
8e08b761 1002
11a68fa3 1003 // FIXME:: Next line not used
8e08b761
JS
1004 // wxRect& bounds = lastBar.mBounds;
1005
11a68fa3
GT
1006 if ( lastBar.mBounds.x + lastBar.mBounds.width > mpPane->mPaneWidth )
1007 {
1008 lastBar.mBounds.x = mpPane->mPaneWidth - lastBar.mBounds.width;
8e08b761 1009
11a68fa3 1010 // first simulate left-row-edge friction
8e08b761 1011
11a68fa3 1012 SlideLeftSideBars( &lastBar );
8e08b761 1013
11a68fa3 1014 if ( firstBar.mBounds.x < 0 )
8e08b761
JS
1015 firstBar.mBounds.x = 0;
1016
11a68fa3
GT
1017 // then left-row-edge function, though this
1018 // may cause some of the right-side bars going
1019 // out of row bounds, but left-side always
1020 // has the highest "priority"
8e08b761 1021
11a68fa3
GT
1022 SlideRightSideBars( &firstBar );
1023 }
8e08b761 1024
11a68fa3 1025 event.Skip(); // pass event to the next handler
8e08b761
JS
1026}
1027
1028void cbRowLayoutPlugin::OnLayoutRows( cbLayoutRowsEvent& event )
1029{
11a68fa3 1030 mpPane = event.mpPane;
8e08b761 1031
11a68fa3 1032 int curY = 0;
8e08b761
JS
1033
1034 // FIXME:: Next line not used.
11a68fa3 1035 // RowArrayT& arr = mpPane->GetRowList();
8e08b761
JS
1036
1037 size_t i;
11a68fa3
GT
1038 for ( i = 0; i != mpPane->GetRowList().Count(); ++i )
1039 {
1040 cbRowInfo& row = *mpPane->GetRowList()[ i ];
a570d5b3 1041 //mpPane->CalcLengthRatios(& row);
11a68fa3
GT
1042
1043 // setup "has-handle" flags for rows, which depend on the existance
1044 // of not-fixed bars in the row
1045
1046 if ( !row.mHasOnlyFixedBars )
1047 {
1048 if ( mpPane->mAlignment == FL_ALIGN_TOP ||
1049 mpPane->mAlignment == FL_ALIGN_LEFT )
1050 {
1051 row.mHasLowerHandle = TRUE;
1052
1053 row.mHasUpperHandle = FALSE;
1054 }
1055 else
1056 {
1057 row.mHasUpperHandle = TRUE;
1058
1059 row.mHasLowerHandle = FALSE;
1060 }
1061 }
1062 else
1063 {
1064 // otherwise, rows with fixed-bars only, have no height-resizing handles
1065 row.mHasUpperHandle = FALSE;
1066 row.mHasLowerHandle = FALSE;
1067 }
1068
1069 // setup vertical positions for items in the row
1070
1071 row.mRowY = curY;
1072
1073 row.mRowWidth = mpPane->mPaneWidth;
1074 row.mRowHeight = CalcRowHeight( row );
1075
1076 LayoutItemsVertically( row );
1077
1078 if ( row.mHasUpperHandle )
8e08b761 1079 row.mRowHeight += mpPane->mProps.mResizeHandleSize;
11a68fa3 1080 if ( row.mHasLowerHandle )
8e08b761
JS
1081 row.mRowHeight += mpPane->mProps.mResizeHandleSize;
1082
11a68fa3
GT
1083 curY += row.mRowHeight;
1084 }
8e08b761 1085
11a68fa3
GT
1086 event.Skip(); // pass event to the next handler - other hookeds plugin
1087 // may also add some "refinements" to the layout now
8e08b761
JS
1088}
1089
1090void cbRowLayoutPlugin::OnResizeRow( cbResizeRowEvent& event )
1091{
11a68fa3
GT
1092 // extract resize-event info
1093 int ofs = event.mHandleOfs;
1094 bool forUpperHandle = event.mForUpperHandle;
1095 cbRowInfo* pTheRow = event.mpRow;
1096 mpPane = event.mpPane;
8e08b761
JS
1097
1098 // FIXME:: Next line not used.
11a68fa3 1099 //int newHeight = pTheRow->mRowHeight;
8e08b761 1100
11a68fa3 1101 int freeSpc = 0;
8e08b761 1102
11a68fa3
GT
1103 if ( forUpperHandle )
1104 {
1105 // calculate available free space from above,
1106 // which can be obtained by squeezing not-fixed height rows
8e08b761 1107
11a68fa3 1108 cbRowInfo* pRow = pTheRow->mpPrev;
8e08b761 1109
11a68fa3
GT
1110 while( pRow )
1111 {
1112 freeSpc += pRow->mRowHeight - event.mpPane->GetMinimalRowHeight( pRow );
8e08b761 1113
11a68fa3
GT
1114 pRow = pRow->mpPrev;
1115 }
1116 }
1117 else
1118 {
1119 // calculate available free space from below,
1120 // which can be obtained by squeezing not-fixed height rows
8e08b761 1121
11a68fa3 1122 cbRowInfo* pRow = pTheRow->mpNext;
8e08b761 1123
11a68fa3
GT
1124 while( pRow )
1125 {
1126 freeSpc += pRow->mRowHeight - mpPane->GetMinimalRowHeight( pRow );
8e08b761 1127
11a68fa3
GT
1128 pRow = pRow->mpNext;
1129 }
1130 }
8e08b761 1131
11a68fa3 1132 mpLayout->GetUpdatesManager().OnStartChanges();
8e08b761 1133
11a68fa3 1134 int clientSize;
8e08b761 1135
11a68fa3 1136 // allow user adjusting pane vs. client-area space, for upper-handle
8e08b761 1137
11a68fa3 1138 if ( mpPane->IsHorizontal() )
8e08b761 1139
11a68fa3
GT
1140 clientSize = mpLayout->GetClientHeight();
1141 else
1142 clientSize = mpLayout->GetClientWidth();
8e08b761 1143
11a68fa3
GT
1144 if ( forUpperHandle && ofs < -clientSize )
1145 {
1146 int needed = -(ofs + clientSize);
8e08b761 1147
11a68fa3 1148 cbRowInfo* pRow = mpPane->GetRowList()[ 0 ];
8e08b761 1149
11a68fa3 1150 // start squeezing rows from the top row towards bottom
8e08b761 1151
11a68fa3
GT
1152 while( pRow != pTheRow && needed )
1153 {
1154 // only not-fixed rows can be squeezed
8e08b761 1155
11a68fa3
GT
1156 if ( !pRow->mHasOnlyFixedBars )
1157 {
1158 int prevHeight = pRow->mRowHeight;
8e08b761 1159
11a68fa3
GT
1160 int newHeight = wxMax( event.mpPane->GetMinimalRowHeight( pRow ),
1161 prevHeight - needed );
8e08b761 1162
11a68fa3
GT
1163 if ( newHeight != prevHeight )
1164 {
1165 event.mpPane->SetRowHeight( pRow, newHeight );
8e08b761 1166
11a68fa3
GT
1167 needed -= prevHeight - pRow->mRowHeight;
1168 }
1169 }
8e08b761 1170
11a68fa3
GT
1171 pRow = pRow->mpNext;
1172 }
1173 }
8e08b761 1174
11a68fa3 1175 // allow user adjusting pane vs. client-area space, for lower-handle
8e08b761 1176
11a68fa3
GT
1177 if ( !forUpperHandle && ofs > clientSize )
1178 {
1179 int needed = ofs - clientSize;
8e08b761 1180
11a68fa3 1181 cbRowInfo* pRow = mpPane->GetRowList()[ mpPane->GetRowList().Count() - 1 ];
8e08b761 1182
11a68fa3 1183 // start squeezing rows from the bottom towards the top row
8e08b761 1184
11a68fa3
GT
1185 while( pRow && needed )
1186 {
1187 // only not-fixed rows can be squeezed
8e08b761 1188
11a68fa3
GT
1189 if ( !pRow->mHasOnlyFixedBars )
1190 {
1191 int prevHeight = pRow->mRowHeight;
8e08b761 1192
11a68fa3
GT
1193 int newHeight = wxMax( event.mpPane->GetMinimalRowHeight( pRow ),
1194 prevHeight - needed );
8e08b761 1195
11a68fa3
GT
1196 if ( newHeight != prevHeight )
1197 {
1198 event.mpPane->SetRowHeight( pRow, newHeight );
8e08b761 1199
11a68fa3
GT
1200 needed -= prevHeight - pRow->mRowHeight;
1201 }
1202 }
8e08b761 1203
11a68fa3
GT
1204 pRow = pRow->mpPrev;
1205 }
1206 }
8e08b761 1207
11a68fa3
GT
1208 if ( forUpperHandle )
1209
1210 event.mpPane->SetRowHeight( pTheRow, pTheRow->mRowHeight + (-ofs) );
1211 else
1212 event.mpPane->SetRowHeight( pTheRow, pTheRow->mRowHeight + ofs );
8e08b761 1213
11a68fa3 1214 mpLayout->RecalcLayout(FALSE);
8e08b761 1215
11a68fa3
GT
1216 mpLayout->GetUpdatesManager().OnFinishChanges();
1217 mpLayout->GetUpdatesManager().UpdateNow();
8e08b761
JS
1218}
1219