mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-27 00:33:48 -05:00
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)
This commit is contained in:
parent
e71930fd45
commit
e214741c62
@ -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();
|
||||
}
|
||||
|
||||
double QgsComposerArrow::computeMarkerMargin() const
|
||||
{
|
||||
double margin = 0;
|
||||
if ( mMarkerMode == DefaultMarker )
|
||||
{
|
||||
margin = mPen.widthF() / 2.0 + mArrowHeadWidth / 2.0;
|
||||
}
|
||||
else if ( mMarkerMode == NoMarker )
|
||||
{
|
||||
margin = mPen.widthF() / 2.0;
|
||||
}
|
||||
else if ( mMarkerMode == SVGMarker )
|
||||
{
|
||||
double maxArrowHeight = qMax( mStartArrowHeadHeight, mStopArrowHeadHeight );
|
||||
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 = 0;
|
||||
if ( mMarkerMode == DefaultMarker )
|
||||
{
|
||||
enlarge = mPen.widthF() / 2.0 + mArrowHeadWidth / 2.0;
|
||||
}
|
||||
else if ( mMarkerMode == NoMarker )
|
||||
{
|
||||
enlarge = mPen.widthF() / 2.0;
|
||||
}
|
||||
else if ( mMarkerMode == SVGMarker )
|
||||
{
|
||||
double maxArrowHeight = qMax( mStartArrowHeadHeight, mStopArrowHeadHeight );
|
||||
enlarge = mPen.widthF() / 2 + qMax( mArrowHeadWidth / 2.0, maxArrowHeight / 2.0 );
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user