Skip to content
Permalink
Browse files
Fix multi column legends with odd number of items would place
more items in rightmost columns instead of leftmost columns

Eg a 2 column legend with 3 items would put 1 item in
the first column and 2 in the second. This was ugly, and now
it places 2 in the first column and 1 in the second.

The legend column assigner was incorrectly adding padding above
the first item in a column during column size calculation
(padding which is not present when actually rendering the column)
  • Loading branch information
nyalldawson committed Sep 10, 2016
1 parent 570e693 commit a673fa8
Showing 1 changed file with 9 additions and 17 deletions.
@@ -265,40 +265,34 @@ void QgsLegendRenderer::setColumns( QList<Atom>& atomList )

// Divide atoms to columns
double totalHeight = 0;
// bool first = true;
qreal maxAtomHeight = 0;
Q_FOREACH ( const Atom& atom, atomList )
{
//if ( !first )
//{
totalHeight += spaceAboveAtom( atom );
//}
totalHeight += atom.size.height();
maxAtomHeight = qMax( atom.size.height(), maxAtomHeight );
// first = false;
}

// We know height of each atom and we have to split them into columns
// minimizing max column height. It is sort of bin packing problem, NP-hard.
// We are using simple heuristic, brute fore appeared to be to slow,
// the number of combinations is N = n!/(k!*(n-k)!) where n = atomsCount-1
// and k = columnsCount-1

double avgColumnHeight = totalHeight / mSettings.columnCount();
double maxColumnHeight = 0;
int currentColumn = 0;
int currentColumnAtomCount = 0; // number of atoms in current column
double currentColumnHeight = 0;
double maxColumnHeight = 0;
double closedColumnsHeight = 0;
// first = true; // first in column

for ( int i = 0; i < atomList.size(); i++ )
{
Atom atom = atomList[i];
// Recalc average height for remaining columns including current
double avgColumnHeight = ( totalHeight - closedColumnsHeight ) / ( mSettings.columnCount() - currentColumn );

Atom atom = atomList.at( i );
double currentHeight = currentColumnHeight;
//if ( !first )
//{
currentHeight += spaceAboveAtom( atom );
//}
if ( currentColumnAtomCount > 0 )
currentHeight += spaceAboveAtom( atom );
currentHeight += atom.size.height();

// Recalc average height for remaining columns including current
@@ -322,11 +316,9 @@ void QgsLegendRenderer::setColumns( QList<Atom>& atomList )
atomList[i].column = currentColumn;
currentColumnAtomCount++;
maxColumnHeight = qMax( currentColumnHeight, maxColumnHeight );

// first = false;
}

// Alling labels of symbols for each layr/column to the same labelXOffset
// Align labels of symbols for each layr/column to the same labelXOffset
QMap<QString, qreal> maxSymbolWidth;
for ( int i = 0; i < atomList.size(); i++ )
{

1 comment on commit a673fa8

@nirvn
Copy link
Contributor

@nirvn nirvn commented on a673fa8 Sep 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, gone are the days of having to rely on an invisible symbology layer with no labels to properly balance the columns. Thanks.

Please sign in to comment.