Skip to content

Commit

Permalink
[composer] Respect reference point when resizing scalebar and legend
Browse files Browse the repository at this point in the history
Previously, the reference point (and data defined position/size) were
ignored when scalebars or legends resized themselves.

Fix #11321, #11380
  • Loading branch information
nyalldawson committed Oct 21, 2014
1 parent ba8a60f commit 5b9210b
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 22 deletions.
13 changes: 11 additions & 2 deletions python/core/composer/qgscomposeritem.sip
Expand Up @@ -761,8 +761,17 @@ class QgsComposerItem : QgsComposerObject, QGraphicsRectItem
void deleteVAlignSnapItem();
void deleteAlignItems();

/**Update an item rect to consider data defined position and size of item*/
QRectF evalItemRect( const QRectF &newRect );
/**Evaluates an item's bounding rect to consider data defined position and size of item
* and reference point
* @param newRect target bouding rect for item
* @param resizeOnly set to true if the item is only being resized. If true then
* the position of the returned rect will be adjusted to account for the item's
* position mode
* @returns bounding box rectangle for item after data defined size and position have been
* set and position mode has been accounted for
* @note added in QGIS 2.5
*/
QRectF evalItemRect( const QRectF &newRect, const bool resizeOnly = false );

/**Returns whether the item should be drawn in the current context
* @returns true if item should be drawn
Expand Down
53 changes: 41 additions & 12 deletions src/core/composer/qgscomposeritem.cpp
Expand Up @@ -708,7 +708,7 @@ void QgsComposerItem::setSceneRect( const QRectF& rectangle )
emit sizeChanged();
}

QRectF QgsComposerItem::evalItemRect( const QRectF &newRect )
QRectF QgsComposerItem::evalItemRect( const QRectF &newRect, const bool resizeOnly )
{
QRectF result = newRect;

Expand Down Expand Up @@ -737,14 +737,29 @@ QRectF QgsComposerItem::evalItemRect( const QRectF &newRect )
}

double x = result.left();
//initially adjust for position mode to get top-left coordinate
if ( mLastUsedPositionMode == UpperMiddle || mLastUsedPositionMode == Middle || mLastUsedPositionMode == LowerMiddle )
//initially adjust for position mode to get x coordinate
if ( !resizeOnly )
{
x += newRect.width() / 2.0;
//adjust x-coordinate if placement is not done to a left point
if ( mLastUsedPositionMode == UpperMiddle || mLastUsedPositionMode == Middle || mLastUsedPositionMode == LowerMiddle )
{
x += newRect.width() / 2.0;
}
else if ( mLastUsedPositionMode == UpperRight || mLastUsedPositionMode == MiddleRight || mLastUsedPositionMode == LowerRight )
{
x += newRect.width();
}
}
else if ( mLastUsedPositionMode == UpperRight || mLastUsedPositionMode == MiddleRight || mLastUsedPositionMode == LowerRight )
else
{
x += newRect.width();
if ( mLastUsedPositionMode == UpperMiddle || mLastUsedPositionMode == Middle || mLastUsedPositionMode == LowerMiddle )
{
x += rect().width() / 2.0;
}
else if ( mLastUsedPositionMode == UpperRight || mLastUsedPositionMode == MiddleRight || mLastUsedPositionMode == LowerRight )
{
x += rect().width();
}
}
if ( dataDefinedEvaluate( QgsComposerObject::PositionX, exprVal ) )
{
Expand All @@ -758,16 +773,30 @@ QRectF QgsComposerItem::evalItemRect( const QRectF &newRect )
}

double y = result.top();
//adjust y-coordinate if placement is not done to an upper point
if ( mLastUsedPositionMode == MiddleLeft || mLastUsedPositionMode == Middle || mLastUsedPositionMode == MiddleRight )
//initially adjust for position mode to get y coordinate
if ( !resizeOnly )
{
y += newRect.height() / 2.0;
//adjust y-coordinate if placement is not done to an upper point
if ( mLastUsedPositionMode == MiddleLeft || mLastUsedPositionMode == Middle || mLastUsedPositionMode == MiddleRight )
{
y += newRect.height() / 2.0;
}
else if ( mLastUsedPositionMode == LowerLeft || mLastUsedPositionMode == LowerMiddle || mLastUsedPositionMode == LowerRight )
{
y += newRect.height();
}
}
else if ( mLastUsedPositionMode == LowerLeft || mLastUsedPositionMode == LowerMiddle || mLastUsedPositionMode == LowerRight )
else
{
y += newRect.height();
if ( mLastUsedPositionMode == MiddleLeft || mLastUsedPositionMode == Middle || mLastUsedPositionMode == MiddleRight )
{
y += rect().height() / 2.0;
}
else if ( mLastUsedPositionMode == LowerLeft || mLastUsedPositionMode == LowerMiddle || mLastUsedPositionMode == LowerRight )
{
y += rect().height();
}
}

if ( dataDefinedEvaluate( QgsComposerObject::PositionY, exprVal ) )
{
bool ok;
Expand Down
13 changes: 11 additions & 2 deletions src/core/composer/qgscomposeritem.h 100755 → 100644
Expand Up @@ -774,8 +774,17 @@ class CORE_EXPORT QgsComposerItem: public QgsComposerObject, public QGraphicsRec
void deleteVAlignSnapItem();
void deleteAlignItems();

/**Update an item rect to consider data defined position and size of item*/
QRectF evalItemRect( const QRectF &newRect );
/**Evaluates an item's bounding rect to consider data defined position and size of item
* and reference point
* @param newRect target bouding rect for item
* @param resizeOnly set to true if the item is only being resized. If true then
* the position of the returned rect will be adjusted to account for the item's
* position mode
* @returns bounding box rectangle for item after data defined size and position have been
* set and position mode has been accounted for
* @note added in QGIS 2.5
*/
QRectF evalItemRect( const QRectF &newRect, const bool resizeOnly = false );

/**Returns whether the item should be drawn in the current context
* @returns true if item should be drawn
Expand Down
20 changes: 15 additions & 5 deletions src/core/composer/qgscomposerlegend.cpp
Expand Up @@ -103,10 +103,18 @@ void QgsComposerLegend::paint( QPainter* painter, const QStyleOptionGraphicsItem

//adjust box if width or height is too small
QSizeF size = legendRenderer.minimumSize();
if ( size.height() > rect().height() )
setSceneRect( QRectF( pos().x(), pos().y(), rect().width(), size.height() ) );
if ( size.width() > rect().width() )
setSceneRect( QRectF( pos().x(), pos().y(), size.width(), rect().height() ) );
if ( size.height() > rect().height() || size.width() > rect().width() )
{
//need to resize box
QRectF targetRect = QRectF( pos().x(), pos().y(), rect().width(), rect().height() );
if ( size.height() > targetRect.height() )
targetRect.setHeight( size.height() );
if ( size.width() > rect().width() )
targetRect.setWidth( size.width() );

//set new rect, respecting position mode and data defined size/position
setSceneRect( evalItemRect( targetRect, true ) );
}

legendRenderer.drawLegend( painter );

Expand Down Expand Up @@ -137,7 +145,9 @@ void QgsComposerLegend::adjustBoxSize()
QgsDebugMsg( QString( "width = %1 height = %2" ).arg( size.width() ).arg( size.height() ) );
if ( size.isValid() )
{
setSceneRect( QRectF( pos().x(), pos().y(), size.width(), size.height() ) );
QRectF targetRect = QRectF( pos().x(), pos().y(), size.width(), size.height() );
//set new rect, respecting position mode and data defined size/position
setSceneRect( evalItemRect( targetRect, true ) );
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/composer/qgscomposerscalebar.cpp
Expand Up @@ -389,7 +389,7 @@ void QgsComposerScaleBar::adjustBoxSize()
QRectF box = mStyle->calculateBoxSize();

//update rect for data defined size and position
QRectF newRect = evalItemRect( box );
QRectF newRect = evalItemRect( box, true );

//scale bars have a minimum size, respect that regardless of data defined settings
if ( newRect.width() < box.width() )
Expand Down

2 comments on commit 5b9210b

@nirvn
Copy link
Contributor

@nirvn nirvn commented on 5b9210b Oct 21, 2014

Choose a reason for hiding this comment

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

Very, very good.

I assume it's already the case for other items, like labels, right?

@nyalldawson
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@nirvn that should already be the case. Can you please file issues if you run into any other circumstances where the reference point is not respected?

Please sign in to comment.