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