Skip to content

Commit

Permalink
Adjust the arrow points to fit inside the specified bounding
Browse files Browse the repository at this point in the history
 box, as opposed to adjusting the bounding box for the arrow points (except
 when bounding box is too small)
  • Loading branch information
manisandro committed Apr 8, 2014
1 parent e71930f commit e214741
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 e214741

Please sign in to comment.