mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-27 00:33:48 -05:00
Merge pull request #1300 from manisandro/fix_composer_arrow_bbox
Improve print composer arrow bounding box logic
This commit is contained in:
commit
241e2f7fbd
@ -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