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)
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.