29 #define YUILogComponent "ui-layout" 32 #include "YLayoutBox.h" 33 #include "YAlignment.h" 36 #include "YApplication.h" 46 , secondary( prim == YD_HORIZ ? YD_VERT : YD_HORIZ )
47 , debugLayout( false )
55 YUIDimension secondary;
66 YUI_CHECK_NEW( priv );
87 return priv->secondary;
94 return priv->debugLayout;
100 priv->debugLayout = deb;
102 yuiDebug() <<
"YLayoutBox: Layout debugging: " << std::boolalpha << deb << endl;
132 if ( dominatingChild )
184 double dominatingRatio = 0.0;
198 if ( ratio > dominatingRatio )
200 dominatingChild = child;
201 dominatingRatio = ratio;
209 if ( dominatingChild )
211 yuiDebug() <<
"Found dominating child: " << dominatingChild
218 yuiDebug() <<
"This layout doesn't have a dominating child." << endl;
222 return dominatingChild;
229 int maxPreferredSize = 0L;
235 maxPreferredSize = std::max( (*it)->preferredSize( dimension ), maxPreferredSize );
238 return maxPreferredSize;
245 int totalWeight = 0L;
251 totalWeight += (*it)->weight( dimension );
267 if ( ! (*it)->hasWeight( dimension ) )
268 size += (*it)->preferredSize( dimension );
284 if ( ! (*it)->hasWeight( dimension ) )
301 if ( ! (*it)->hasWeight( dimension ) &&
302 (*it)->stretchable( dimension ) )
319 if ( ! (*it)->hasWeight( dimension ) &&
336 if ( spacing && spacing->
stretchable( dimension ) )
351 if ( (*it)->stretchable( dimension ) ||
352 (*it)->hasWeight( dimension ) )
364 sizeVector widths ( count );
365 sizeVector heights ( count );
366 posVector x_pos ( count );
367 posVector y_pos ( count );
386 x_pos[i] = newWidth - x_pos[i] - widths[i];
389 doResize( widths, heights, x_pos, y_pos );
395 sizeVector & childSize,
396 posVector & childPos )
401 if ( distributableSize >= 0L )
408 int nonWeightedExtra = 0L;
411 int rubberBandExtra = 0L;
413 if ( totalWeight <= 0 )
421 if ( stretchableChildren > 0 )
422 nonWeightedExtra = distributableSize / stretchableChildren;
437 if ( surplusSize > 0L )
441 if ( rubberBands > 0 )
443 rubberBandExtra = surplusSize / rubberBands;
444 distributableSize -= rubberBandExtra * rubberBands;
451 yuiDebug() <<
"Distributing extra space" << endl;
452 yuiDebug() <<
"\tnew size: " << newSize << endl;
453 yuiDebug() <<
"\tdistributable size: " << distributableSize << endl;
454 yuiDebug() <<
"\trubber band extra: " << rubberBandExtra << endl;
455 yuiDebug() <<
"\trubber bands: " << rubberBands << endl;
456 yuiDebug() <<
"\ttotal weight: " << totalWeight << endl;
457 yuiDebug() <<
"\tnon weighted extra: " << nonWeightedExtra << endl;
471 childSize[i] = distributableSize * child->
weight(
primary() ) / totalWeight;
475 yuiDebug() <<
"Layout running out of space: " 476 <<
"Resizing child widget #" << i <<
" ("<< child
478 <<
" to " << childSize[i]
495 childSize[i] += nonWeightedExtra;
504 childSize[i] += rubberBandExtra;
523 int tooSmall = -distributableSize;
525 int totalMargins = 0L;
526 int remainingMargins = 0L;
527 double marginScale = 0.0;
529 yuiDebug() <<
"Not enough space: " << tooSmall <<
" too small - check the layout!" << endl;
538 if ( ! (*it)->hasWeight(
primary() ) )
545 yuiDebug() <<
"Found alignment with margins" << endl;
551 if ( totalMargins > tooSmall )
553 remainingMargins = totalMargins - tooSmall;
555 marginScale = ( (double) remainingMargins ) / totalMargins;
557 yuiDebug() <<
"Making up for insufficient space by reducing margins to " 558 << 100.0 * marginScale <<
"% - " 559 << remainingMargins <<
" left for margins" 564 tooSmall -= totalMargins;
566 yuiDebug() <<
"Reducing all margins to 0, but still " << tooSmall <<
" too small" << endl;
577 if ( ! (*it)->hasWeight(
primary() ) )
580 childSize[i] = (*it)->preferredSize(
primary() );
587 childSize[i] -= margins;
589 if ( remainingMargins > 0 )
591 margins = (int) marginScale * margins;
592 childSize[i] += margins;
593 remainingMargins -= margins;
609 int oldTooSmall = tooSmall;
610 int oldLoserCount = loserCount;
611 while ( tooSmall > 0 && loserCount > 0 )
615 yuiWarning() <<
"Distributing insufficient space of " << tooSmall
616 <<
" among " << loserCount <<
" losers" 620 int dividedLoss = std::max( tooSmall / loserCount, 1 );
627 if ( childSize[i] < dividedLoss )
633 if ( childSize[i] > 0L )
635 tooSmall -= childSize[i];
639 if ( loserCount > 0 )
640 dividedLoss = std::max( tooSmall / loserCount, 1 );
645 childSize[i] -= dividedLoss;
646 tooSmall -= dividedLoss;
653 yuiWarning() <<
"child #" << i <<
" ( " << child
654 <<
" ) will get " << childSize[i]
659 <<
"), pos: " << childPos[i]
664 if ( oldTooSmall == tooSmall &&
665 oldLoserCount == loserCount )
667 yuiWarning() <<
"Preventing endless loop while layout space distribution. Break." << endl;
671 oldTooSmall = tooSmall;
672 oldLoserCount = loserCount;
691 sizeVector & childSize,
692 posVector & childPos )
706 childSize[i] = newSize;
711 childSize[i] = preferred;
712 childPos [i] = ( newSize - preferred ) / 2;
715 if ( childSize[i] < preferred )
717 yuiDebug() <<
"Layout running out of space: " 718 <<
"Resizing child widget #" << i
720 <<
") below its preferred size of " << preferred
721 <<
" to " << childSize[i]
727 ( childSize[i] < preferred ? yuiWarning() : yuiDebug() )
730 <<
") will get " << childSize[i]
731 <<
" (preferred size: " << preferred
734 <<
"), pos: " << childPos[i]
754 child->
setSize( width[i], height[i] );
759 yuiMilestone() <<
" x: " << std::setw( 3 ) << x_pos[i]
760 <<
" y: " << std::setw( 3 ) << y_pos[i]
761 <<
" w: " << std::setw( 3 ) << width[i]
762 <<
" h: " << std::setw( 3 ) << height[i]
773 return primary() == YD_VERT ?
"YVBox" :
"YHBox";
int childrenTotalWeight(YUIDimension dimension)
Add up all the children's weights.
virtual void moveChild(YWidget *child, int newX, int newY)=0
Move a child to a new position.
virtual bool stretchable(YUIDimension dimension) const
Returns the stretchability of the layout box: The layout box is stretchable if one of the children is...
static bool isLayoutStretch(YWidget *child, YUIDimension dimension)
Check if this is a layout stretch widget in the specfied dimension, i.e.
bool debugLayout() const
Returns 'true' if layout debugging (verbose logging during layout) is on.
virtual int preferredWidth()
Preferred width of the widget.
YUIDimension secondary() const
Return the secondary dimension.
void calcPrimaryGeometry(int newSize, sizeVector &childSize, posVector &childPos)
Calculate the sizes and positions of all children in the primary dimension and store them in "childSi...
void calcSecondaryGeometry(int newSize, sizeVector &childSize, posVector &childPos)
Calculate the sizes and positions of all children in the secondary dimension and store them in "child...
void setDebugLayout(bool deb=true)
Enable or disable layout debugging.
virtual void setSize(int newWidth, int newHeight)
Sets the size of the layout box.
void doResize(sizeVector &width, sizeVector &height, posVector &x_pos, posVector &y_pos)
Actually perform resizing and moving the child widgets to the appropriate position.
int countNonWeightedChildren(YUIDimension dimension)
Count the number of non-weighted children.
int totalNonWeightedChildrenPreferredSize(YUIDimension dimension)
Add up all the non-weighted children's preferred sizes in the specified dimension.
virtual int preferredSize(YUIDimension dim)
Preferred size of the widget in the specified dimension.
Abstract base template class for children management, such as child widgets.
Implementation of all the alignment widgets:
virtual int preferredHeight()
Preferred height of the widget.
YLayoutBox(YWidget *parent, YUIDimension dim)
Constructor.
HSpacing, VSpacing, HStretch, VStretch.
int totalMargins(YUIDimension dim) const
Return the sum of all margins in the specified dimension.
int countStretchableChildren(YUIDimension dimension)
Count the number of stretchable ( non-weighted ) children.
static YApplication * app()
Return the global YApplication object.
YWidget * findDominatingChild()
Determine the number of the "dominating child" - the child widget that determines the overall size wi...
YLayoutBoxPrivate(YUIDimension prim)
Constructor.
virtual const char * widgetClass() const
Returns a descriptive name of this widget class for logging, debugging etc.
int childrenMaxPreferredSize(YUIDimension dimension)
Return the maximum preferred size of all children in the specified dimension.
int countLayoutStretchChildren(YUIDimension dimension)
Count the number of "rubber bands", i.e.
YUIDimension primary() const
Return the primary dimension, i.e., the dimension this LayoutBox lays out its children in: YD_VERT fo...
virtual ~YLayoutBox()
Destructor.