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