29 #define YUILogComponent "ui-layout"
32 #include "YLayoutBox.h"
33 #include "YAlignment.h"
36 #include "YApplication.h"
50 , secondary( prim == YD_HORIZ ? YD_VERT : YD_HORIZ )
51 , debugLayout( false )
59 YUIDimension secondary;
70 YUI_CHECK_NEW( priv );
91 return priv->secondary;
98 return priv->debugLayout;
104 priv->debugLayout = deb;
106 yuiDebug() <<
"YLayoutBox: Layout debugging: " << boolalpha << deb << endl;
136 if ( dominatingChild )
188 double dominatingRatio = 0.0;
202 if ( ratio > dominatingRatio )
204 dominatingChild = child;
205 dominatingRatio = ratio;
213 if ( dominatingChild )
215 yuiDebug() <<
"Found dominating child: " << dominatingChild
222 yuiDebug() <<
"This layout doesn't have a dominating child." << endl;
226 return dominatingChild;
233 int maxPreferredSize = 0L;
239 maxPreferredSize = std::max( (*it)->preferredSize( dimension ), maxPreferredSize );
242 return maxPreferredSize;
249 int totalWeight = 0L;
255 totalWeight += (*it)->weight( dimension );
271 if ( ! (*it)->hasWeight( dimension ) )
272 size += (*it)->preferredSize( dimension );
288 if ( ! (*it)->hasWeight( dimension ) )
305 if ( ! (*it)->hasWeight( dimension ) &&
306 (*it)->stretchable( dimension ) )
323 if ( ! (*it)->hasWeight( dimension ) &&
340 if ( spacing && spacing->
stretchable( dimension ) )
355 if ( (*it)->stretchable( dimension ) ||
356 (*it)->hasWeight( dimension ) )
368 sizeVector widths ( count );
369 sizeVector heights ( count );
370 posVector x_pos ( count );
371 posVector y_pos ( count );
390 x_pos[i] = newWidth - x_pos[i] - widths[i];
393 doResize( widths, heights, x_pos, y_pos );
399 sizeVector & childSize,
400 posVector & childPos )
405 if ( distributableSize >= 0L )
412 int nonWeightedExtra = 0L;
415 int rubberBandExtra = 0L;
417 if ( totalWeight <= 0 )
425 if ( stretchableChildren > 0 )
426 nonWeightedExtra = distributableSize / stretchableChildren;
441 if ( surplusSize > 0L )
445 if ( rubberBands > 0 )
447 rubberBandExtra = surplusSize / rubberBands;
448 distributableSize -= rubberBandExtra * rubberBands;
455 yuiDebug() <<
"Distributing extra space" << endl;
456 yuiDebug() <<
"\tnew size: " << newSize << endl;
457 yuiDebug() <<
"\tdistributable size: " << distributableSize << endl;
458 yuiDebug() <<
"\trubber band extra: " << rubberBandExtra << endl;
459 yuiDebug() <<
"\trubber bands: " << rubberBands << endl;
460 yuiDebug() <<
"\ttotal weight: " << totalWeight << endl;
461 yuiDebug() <<
"\tnon weighted extra: " << nonWeightedExtra << endl;
475 childSize[i] = distributableSize * child->
weight(
primary() ) / totalWeight;
479 yuiDebug() <<
"Layout running out of space: "
480 <<
"Resizing child widget #" << i <<
" ("<< child
482 <<
" to " << childSize[i]
499 childSize[i] += nonWeightedExtra;
508 childSize[i] += rubberBandExtra;
527 int tooSmall = -distributableSize;
529 int totalMargins = 0L;
530 int remainingMargins = 0L;
531 double marginScale = 0.0;
533 yuiDebug() <<
"Not enough space: " << tooSmall <<
" too small - check the layout!" << endl;
542 if ( ! (*it)->hasWeight(
primary() ) )
549 yuiDebug() <<
"Found alignment with margins" << endl;
555 if ( totalMargins > tooSmall )
557 remainingMargins = totalMargins - tooSmall;
559 marginScale = ( (double) remainingMargins ) / totalMargins;
561 yuiDebug() <<
"Making up for insufficient space by reducing margins to "
562 << 100.0 * marginScale <<
"% - "
563 << remainingMargins <<
" left for margins"
568 tooSmall -= totalMargins;
570 yuiDebug() <<
"Reducing all margins to 0, but still " << tooSmall <<
" too small" << endl;
581 if ( ! (*it)->hasWeight(
primary() ) )
584 childSize[i] = (*it)->preferredSize(
primary() );
591 childSize[i] -= margins;
593 if ( remainingMargins > 0 )
595 margins = (int) marginScale * margins;
596 childSize[i] += margins;
597 remainingMargins -= margins;
613 int oldTooSmall = tooSmall;
614 int oldLoserCount = loserCount;
615 while ( tooSmall > 0 && loserCount > 0 )
619 yuiWarning() <<
"Distributing insufficient space of " << tooSmall
620 <<
" among " << loserCount <<
" losers"
624 int dividedLoss = std::max( tooSmall / loserCount, 1 );
631 if ( childSize[i] < dividedLoss )
637 if ( childSize[i] > 0L )
639 tooSmall -= childSize[i];
643 if ( loserCount > 0 )
644 dividedLoss = std::max( tooSmall / loserCount, 1 );
649 childSize[i] -= dividedLoss;
650 tooSmall -= dividedLoss;
657 yuiWarning() <<
"child #" << i <<
" ( " << child
658 <<
" ) will get " << childSize[i]
663 <<
"), pos: " << childPos[i]
668 if ( oldTooSmall == tooSmall &&
669 oldLoserCount == loserCount )
671 yuiWarning() <<
"Preventing endless loop while layout space distribution. Break." << endl;
675 oldTooSmall = tooSmall;
676 oldLoserCount = loserCount;
695 sizeVector & childSize,
696 posVector & childPos )
710 childSize[i] = newSize;
715 childSize[i] = preferred;
716 childPos [i] = ( newSize - preferred ) / 2;
719 if ( childSize[i] < preferred )
721 yuiDebug() <<
"Layout running out of space: "
722 <<
"Resizing child widget #" << i
724 <<
") below its preferred size of " << preferred
725 <<
" to " << childSize[i]
731 ( childSize[i] < preferred ? yuiWarning() : yuiDebug() )
734 <<
") will get " << childSize[i]
735 <<
" (preferred size: " << preferred
738 <<
"), pos: " << childPos[i]
758 child->
setSize( width[i], height[i] );
763 yuiMilestone() <<
" x: " << setw( 3 ) << x_pos[i]
764 <<
" y: " << setw( 3 ) << y_pos[i]
765 <<
" w: " << setw( 3 ) << width[i]
766 <<
" h: " << setw( 3 ) << height[i]
777 return primary() == YD_VERT ?
"YVBox" :
"YHBox";
int childrenTotalWeight(YUIDimension dimension)
virtual void moveChild(YWidget *child, int newX, int newY)=0
static bool isLayoutStretch(YWidget *child, YUIDimension dimension)
virtual int preferredWidth()
void calcPrimaryGeometry(int newSize, sizeVector &childSize, posVector &childPos)
void calcSecondaryGeometry(int newSize, sizeVector &childSize, posVector &childPos)
void setDebugLayout(bool deb=true)
virtual void setSize(int newWidth, int newHeight)
void doResize(sizeVector &width, sizeVector &height, posVector &x_pos, posVector &y_pos)
virtual const char * widgetClass() const
YUIDimension secondary() const
int countNonWeightedChildren(YUIDimension dimension)
int totalNonWeightedChildrenPreferredSize(YUIDimension dimension)
virtual int preferredSize(YUIDimension dim)
virtual int preferredHeight()
YLayoutBox(YWidget *parent, YUIDimension dim)
virtual bool stretchable(YUIDimension dimension) const
int countStretchableChildren(YUIDimension dimension)
static YApplication * app()
YUIDimension primary() const
YWidget * findDominatingChild()
YLayoutBoxPrivate(YUIDimension prim)
int childrenMaxPreferredSize(YUIDimension dimension)
int countLayoutStretchChildren(YUIDimension dimension)
int totalMargins(YUIDimension dim) const