Skip to content

Commit

Permalink
Merge pull request #1300 from manisandro/fix_composer_arrow_bbox
Browse files Browse the repository at this point in the history
Improve print composer arrow bounding box logic
  • Loading branch information
nyalldawson committed Apr 13, 2014
2 parents e87a7b8 + e214741 commit 241e2f7
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 19 deletions.
69 changes: 51 additions & 18 deletions src/core/composer/qgscomposerarrow.cpp
Expand Up @@ -26,6 +26,8 @@ QgsComposerArrow::QgsComposerArrow( QgsComposition* c )
: QgsComposerItem( c )
, mStartPoint( 0, 0 )
, mStopPoint( 0, 0 )
, mStartXIdx( 0 )
, mStartYIdx( 0 )
, mMarkerMode( DefaultMarker )
, mArrowColor( QColor( 0, 0, 0 ) )
{
Expand All @@ -39,6 +41,8 @@ QgsComposerArrow::QgsComposerArrow( const QPointF& startPoint, const QPointF& st
, mMarkerMode( DefaultMarker )
, mArrowColor( QColor( 0, 0, 0 ) )
{
mStartXIdx = mStopPoint.x() < mStartPoint.x();
mStartYIdx = mStopPoint.y() < mStartPoint.y();
initGraphicsSettings();
adaptItemSceneRect();
}
Expand Down Expand Up @@ -97,18 +101,31 @@ void QgsComposerArrow::paint( QPainter* painter, const QStyleOptionGraphicsItem

void QgsComposerArrow::setSceneRect( const QRectF& rectangle )
{
//maintain the relative position of start and stop point in the rectangle
double startPointXPos = ( mStartPoint.x() - pos().x() ) / rect().width();
double startPointYPos = ( mStartPoint.y() - pos().y() ) / rect().height();
double stopPointXPos = ( mStopPoint.x() - pos().x() ) / rect().width();
double stopPointYPos = ( mStopPoint.y() - pos().y() ) / rect().height();
if ( rectangle.width() < 0 )
{
mStartXIdx = 1 - mStartXIdx;
}
if ( rectangle.height() < 0 )
{
mStartYIdx = 1 - mStartYIdx;
}

mStartPoint.setX( rectangle.left() + startPointXPos * rectangle.width() );
mStartPoint.setY( rectangle.top() + startPointYPos * rectangle.height() );
mStopPoint.setX( rectangle.left() + stopPointXPos * rectangle.width() );
mStopPoint.setY( rectangle.top() + stopPointYPos * rectangle.height() );
double margin = computeMarkerMargin();

adaptItemSceneRect();
// Ensure the rectangle is at least as large as needed to include the markers
QRectF rect = rectangle.unite( QRectF( rectangle.x(), rectangle.y(), 2. * margin, 2. * margin ) );

// Compute new start and stop positions
double x[2] = {rect.x(), rect.x() + rect.width()};
double y[2] = {rect.y(), rect.y() + rect.height()};

double xsign = x[mStartXIdx] < x[1 - mStartXIdx] ? 1.0 : -1.0;
double ysign = y[mStartYIdx] < y[1 - mStartYIdx] ? 1.0 : -1.0;

mStartPoint = QPointF( x[mStartXIdx] + xsign * margin, y[mStartYIdx] + ysign * margin );
mStopPoint = QPointF( x[1 - mStartXIdx] - xsign * margin, y[1 - mStartYIdx] - ysign * margin );

QgsComposerItem::setSceneRect( rect );
}

void QgsComposerArrow::drawHardcodedMarker( QPainter *p, MarkerType type )
Expand Down Expand Up @@ -258,30 +275,41 @@ void QgsComposerArrow::setArrowHeadWidth( double width )
adaptItemSceneRect();
}

void QgsComposerArrow::adaptItemSceneRect()
double QgsComposerArrow::computeMarkerMargin() const
{
//rectangle containing start and end point
QRectF rect = QRectF( qMin( mStartPoint.x(), mStopPoint.x() ), qMin( mStartPoint.y(), mStopPoint.y() ),
qAbs( mStopPoint.x() - mStartPoint.x() ), qAbs( mStopPoint.y() - mStartPoint.y() ) );
double enlarge = 0;
double margin = 0;
if ( mMarkerMode == DefaultMarker )
{
enlarge = mPen.widthF() / 2.0 + mArrowHeadWidth / 2.0;
margin = mPen.widthF() / 2.0 + mArrowHeadWidth / 2.0;
}
else if ( mMarkerMode == NoMarker )
{
enlarge = mPen.widthF() / 2.0;
margin = mPen.widthF() / 2.0;
}
else if ( mMarkerMode == SVGMarker )
{
double maxArrowHeight = qMax( mStartArrowHeadHeight, mStopArrowHeadHeight );
enlarge = mPen.widthF() / 2 + qMax( mArrowHeadWidth / 2.0, maxArrowHeight / 2.0 );
margin = mPen.widthF() / 2 + qMax( mArrowHeadWidth / 2.0, maxArrowHeight / 2.0 );
}
return margin;
}

void QgsComposerArrow::adaptItemSceneRect()
{
//rectangle containing start and end point
QRectF rect = QRectF( qMin( mStartPoint.x(), mStopPoint.x() ), qMin( mStartPoint.y(), mStopPoint.y() ),
qAbs( mStopPoint.x() - mStartPoint.x() ), qAbs( mStopPoint.y() - mStartPoint.y() ) );
double enlarge = computeMarkerMargin();
rect.adjust( -enlarge, -enlarge, enlarge, enlarge );
QgsComposerItem::setSceneRect( rect );
}

void QgsComposerArrow::setMarkerMode( MarkerMode mode )
{
mMarkerMode = mode;
adaptItemSceneRect();
}

bool QgsComposerArrow::writeXML( QDomElement& elem, QDomDocument & doc ) const
{
QDomElement composerArrowElem = doc.createElement( "ComposerArrow" );
Expand Down Expand Up @@ -362,7 +390,12 @@ bool QgsComposerArrow::readXML( const QDomElement& itemElem, const QDomDocument&
mStopPoint.setY( stopPointElem.attribute( "y", "0.0" ).toDouble() );
}

mStartXIdx = mStopPoint.x() < mStartPoint.x();
mStartYIdx = mStopPoint.y() < mStartPoint.y();

adaptItemSceneRect();
emit itemChanged();
return true;
}


12 changes: 11 additions & 1 deletion src/core/composer/qgscomposerarrow.h
Expand Up @@ -63,7 +63,7 @@ class CORE_EXPORT QgsComposerArrow: public QgsComposerItem
void setArrowColor( const QColor& c ) { mArrowColor = c; }

MarkerMode markerMode() const { return mMarkerMode;}
void setMarkerMode( MarkerMode mode ) {mMarkerMode = mode;}
void setMarkerMode( MarkerMode mode );

/** stores state in Dom element
* @param elem is Dom element corresponding to 'Composer' tag
Expand All @@ -88,6 +88,12 @@ class CORE_EXPORT QgsComposerArrow: public QgsComposerItem
QPointF mStartPoint;
QPointF mStopPoint;

/**Considering the rectangle as spanning [x[0], x[1]] x [y[0], y[1]], these
* indices specify which index {0, 1} corresponds to the start point
* coordinate of the respective dimension*/
int mStartXIdx;
int mStartYIdx;

QPen mPen;
QBrush mBrush;

Expand All @@ -110,6 +116,8 @@ class CORE_EXPORT QgsComposerArrow: public QgsComposerItem
/**Adapts the item scene rect to contain the start point, the stop point including the arrow marker and the outline.
Needs to be called whenever the arrow width/height, the outline with or the endpoints are changed*/
void adaptItemSceneRect();
/**Computes the margin around the line necessary to include the markers */
double computeMarkerMargin() const;
/**Draws the default marker at the line end*/
void drawHardcodedMarker( QPainter* p, MarkerType type );
/**Draws a user-defined marker (must be an svg file)*/
Expand All @@ -119,3 +127,5 @@ class CORE_EXPORT QgsComposerArrow: public QgsComposerItem
};

#endif // QGSCOMPOSERARROW_H


0 comments on commit 241e2f7

Please sign in to comment.