Skip to content

Commit e214741

Browse files
committed
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)
1 parent e71930f commit e214741

File tree

2 files changed

+62
-19
lines changed

2 files changed

+62
-19
lines changed

src/core/composer/qgscomposerarrow.cpp

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ QgsComposerArrow::QgsComposerArrow( QgsComposition* c )
2626
: QgsComposerItem( c )
2727
, mStartPoint( 0, 0 )
2828
, mStopPoint( 0, 0 )
29+
, mStartXIdx( 0 )
30+
, mStartYIdx( 0 )
2931
, mMarkerMode( DefaultMarker )
3032
, mArrowColor( QColor( 0, 0, 0 ) )
3133
{
@@ -39,6 +41,8 @@ QgsComposerArrow::QgsComposerArrow( const QPointF& startPoint, const QPointF& st
3941
, mMarkerMode( DefaultMarker )
4042
, mArrowColor( QColor( 0, 0, 0 ) )
4143
{
44+
mStartXIdx = mStopPoint.x() < mStartPoint.x();
45+
mStartYIdx = mStopPoint.y() < mStartPoint.y();
4246
initGraphicsSettings();
4347
adaptItemSceneRect();
4448
}
@@ -97,18 +101,31 @@ void QgsComposerArrow::paint( QPainter* painter, const QStyleOptionGraphicsItem
97101

98102
void QgsComposerArrow::setSceneRect( const QRectF& rectangle )
99103
{
100-
//maintain the relative position of start and stop point in the rectangle
101-
double startPointXPos = ( mStartPoint.x() - pos().x() ) / rect().width();
102-
double startPointYPos = ( mStartPoint.y() - pos().y() ) / rect().height();
103-
double stopPointXPos = ( mStopPoint.x() - pos().x() ) / rect().width();
104-
double stopPointYPos = ( mStopPoint.y() - pos().y() ) / rect().height();
104+
if ( rectangle.width() < 0 )
105+
{
106+
mStartXIdx = 1 - mStartXIdx;
107+
}
108+
if ( rectangle.height() < 0 )
109+
{
110+
mStartYIdx = 1 - mStartYIdx;
111+
}
105112

106-
mStartPoint.setX( rectangle.left() + startPointXPos * rectangle.width() );
107-
mStartPoint.setY( rectangle.top() + startPointYPos * rectangle.height() );
108-
mStopPoint.setX( rectangle.left() + stopPointXPos * rectangle.width() );
109-
mStopPoint.setY( rectangle.top() + stopPointYPos * rectangle.height() );
113+
double margin = computeMarkerMargin();
110114

111-
adaptItemSceneRect();
115+
// Ensure the rectangle is at least as large as needed to include the markers
116+
QRectF rect = rectangle.unite( QRectF( rectangle.x(), rectangle.y(), 2. * margin, 2. * margin ) );
117+
118+
// Compute new start and stop positions
119+
double x[2] = {rect.x(), rect.x() + rect.width()};
120+
double y[2] = {rect.y(), rect.y() + rect.height()};
121+
122+
double xsign = x[mStartXIdx] < x[1 - mStartXIdx] ? 1.0 : -1.0;
123+
double ysign = y[mStartYIdx] < y[1 - mStartYIdx] ? 1.0 : -1.0;
124+
125+
mStartPoint = QPointF( x[mStartXIdx] + xsign * margin, y[mStartYIdx] + ysign * margin );
126+
mStopPoint = QPointF( x[1 - mStartXIdx] - xsign * margin, y[1 - mStartYIdx] - ysign * margin );
127+
128+
QgsComposerItem::setSceneRect( rect );
112129
}
113130

114131
void QgsComposerArrow::drawHardcodedMarker( QPainter *p, MarkerType type )
@@ -258,30 +275,41 @@ void QgsComposerArrow::setArrowHeadWidth( double width )
258275
adaptItemSceneRect();
259276
}
260277

261-
void QgsComposerArrow::adaptItemSceneRect()
278+
double QgsComposerArrow::computeMarkerMargin() const
262279
{
263-
//rectangle containing start and end point
264-
QRectF rect = QRectF( qMin( mStartPoint.x(), mStopPoint.x() ), qMin( mStartPoint.y(), mStopPoint.y() ),
265-
qAbs( mStopPoint.x() - mStartPoint.x() ), qAbs( mStopPoint.y() - mStartPoint.y() ) );
266-
double enlarge = 0;
280+
double margin = 0;
267281
if ( mMarkerMode == DefaultMarker )
268282
{
269-
enlarge = mPen.widthF() / 2.0 + mArrowHeadWidth / 2.0;
283+
margin = mPen.widthF() / 2.0 + mArrowHeadWidth / 2.0;
270284
}
271285
else if ( mMarkerMode == NoMarker )
272286
{
273-
enlarge = mPen.widthF() / 2.0;
287+
margin = mPen.widthF() / 2.0;
274288
}
275289
else if ( mMarkerMode == SVGMarker )
276290
{
277291
double maxArrowHeight = qMax( mStartArrowHeadHeight, mStopArrowHeadHeight );
278-
enlarge = mPen.widthF() / 2 + qMax( mArrowHeadWidth / 2.0, maxArrowHeight / 2.0 );
292+
margin = mPen.widthF() / 2 + qMax( mArrowHeadWidth / 2.0, maxArrowHeight / 2.0 );
279293
}
294+
return margin;
295+
}
280296

297+
void QgsComposerArrow::adaptItemSceneRect()
298+
{
299+
//rectangle containing start and end point
300+
QRectF rect = QRectF( qMin( mStartPoint.x(), mStopPoint.x() ), qMin( mStartPoint.y(), mStopPoint.y() ),
301+
qAbs( mStopPoint.x() - mStartPoint.x() ), qAbs( mStopPoint.y() - mStartPoint.y() ) );
302+
double enlarge = computeMarkerMargin();
281303
rect.adjust( -enlarge, -enlarge, enlarge, enlarge );
282304
QgsComposerItem::setSceneRect( rect );
283305
}
284306

307+
void QgsComposerArrow::setMarkerMode( MarkerMode mode )
308+
{
309+
mMarkerMode = mode;
310+
adaptItemSceneRect();
311+
}
312+
285313
bool QgsComposerArrow::writeXML( QDomElement& elem, QDomDocument & doc ) const
286314
{
287315
QDomElement composerArrowElem = doc.createElement( "ComposerArrow" );
@@ -362,7 +390,12 @@ bool QgsComposerArrow::readXML( const QDomElement& itemElem, const QDomDocument&
362390
mStopPoint.setY( stopPointElem.attribute( "y", "0.0" ).toDouble() );
363391
}
364392

393+
mStartXIdx = mStopPoint.x() < mStartPoint.x();
394+
mStartYIdx = mStopPoint.y() < mStartPoint.y();
395+
365396
adaptItemSceneRect();
366397
emit itemChanged();
367398
return true;
368399
}
400+
401+

src/core/composer/qgscomposerarrow.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class CORE_EXPORT QgsComposerArrow: public QgsComposerItem
6363
void setArrowColor( const QColor& c ) { mArrowColor = c; }
6464

6565
MarkerMode markerMode() const { return mMarkerMode;}
66-
void setMarkerMode( MarkerMode mode ) {mMarkerMode = mode;}
66+
void setMarkerMode( MarkerMode mode );
6767

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

91+
/**Considering the rectangle as spanning [x[0], x[1]] x [y[0], y[1]], these
92+
* indices specify which index {0, 1} corresponds to the start point
93+
* coordinate of the respective dimension*/
94+
int mStartXIdx;
95+
int mStartYIdx;
96+
9197
QPen mPen;
9298
QBrush mBrush;
9399

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

121129
#endif // QGSCOMPOSERARROW_H
130+
131+

0 commit comments

Comments
 (0)