Skip to content
Permalink
Browse files
Adjust the arrow points to fit inside the specified bounding
 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 e214741c623dd01afeddf73c4811dd5f05577fb4
Showing with 62 additions and 19 deletions.
  1. +51 −18 src/core/composer/qgscomposerarrow.cpp
  2. +11 −1 src/core/composer/qgscomposerarrow.h
@@ -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 ) )
{
@@ -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();
}
@@ -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 )
@@ -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" );
@@ -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;
}


@@ -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
@@ -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;

@@ -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)*/
@@ -119,3 +127,5 @@ class CORE_EXPORT QgsComposerArrow: public QgsComposerItem
};

#endif // QGSCOMPOSERARROW_H


0 comments on commit e214741

Please sign in to comment.