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 a673fa8393146d9a8cd1a3bf6f0444bfa23352d7
Showing with 9 additions and 17 deletions.
  1. +9 −17 src/core/qgslegendrenderer.cpp
@@ -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

This comment has been minimized.

Copy link
Contributor

@nirvn nirvn commented on a673fa8 Sep 11, 2016

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.
You can’t perform that action at this time.