mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
[composer] Draw mouse handles and item bounds outside of item's frames, so that snapping occurs to edge of item frame (fix #8943)
This commit is contained in:
parent
0fc0ffbb8d
commit
78ecef6f2a
@ -183,8 +183,9 @@ class QgsComposerItem : QObject, QGraphicsRectItem
|
||||
void setItemPosition( double x, double y, ItemPositionMode itemPoint = UpperLeft );
|
||||
|
||||
/**Sets item position and width / height in one go
|
||||
* @param posIncludesFrame set to true if the position and size arguments include the item's frame border
|
||||
@note: this method was added in version 1.6*/
|
||||
void setItemPosition( double x, double y, double width, double height, ItemPositionMode itemPoint = UpperLeft );
|
||||
void setItemPosition( double x, double y, double width, double height, ItemPositionMode itemPoint = UpperLeft, bool posIncludesFrame = false );
|
||||
|
||||
/**Returns item's last used position mode.
|
||||
@note: This property has no effect on actual's item position, which is always the top-left corner.
|
||||
@ -228,6 +229,31 @@ class QgsComposerItem : QObject, QGraphicsRectItem
|
||||
*/
|
||||
void setFrameEnabled( bool drawFrame );
|
||||
|
||||
/** Sets frame outline width
|
||||
* @param outlineWidth new width for outline frame
|
||||
* @returns nothing
|
||||
* @note introduced in 2.2
|
||||
* @see setFrameEnabled
|
||||
*/
|
||||
virtual void setFrameOutlineWidth( double outlineWidth );
|
||||
|
||||
/** Returns the estimated amount the item's frame bleeds outside the item's
|
||||
* actual rectangle. For instance, if the item has a 2mm frame outline, then
|
||||
* 1mm of this frame is drawn outside the item's rect. In this case the
|
||||
* return value will be 1.0
|
||||
* @note introduced in 2.2
|
||||
*/
|
||||
virtual double estimatedFrameBleed() const;
|
||||
|
||||
/** Returns the item's rectangular bounds, including any bleed caused by the item's frame.
|
||||
* The bounds are returned in the item's coordinate system (see Qt's QGraphicsItem docs for
|
||||
* more details about QGraphicsItem coordinate systems). The results differ from Qt's rect()
|
||||
* function, as rect() makes no allowances for the portion of outlines which are drawn
|
||||
* outside of the item.
|
||||
* @note introduced in 2.2
|
||||
* @see estimatedFrameBleed
|
||||
*/
|
||||
virtual QRectF rectWithFrame() const;
|
||||
|
||||
/** Whether this item has a Background or not.
|
||||
* @returns true if there is a Background around this item, otherwise false.
|
||||
@ -466,4 +492,9 @@ class QgsComposerItem : QObject, QGraphicsRectItem
|
||||
void itemChanged();
|
||||
/**Emitted if the rectangle changes*/
|
||||
void sizeChanged();
|
||||
/**Emitted if the item's frame style changes
|
||||
* @note: this function was introduced in version 2.2
|
||||
*/
|
||||
void frameChanged();
|
||||
|
||||
};
|
||||
|
@ -61,4 +61,12 @@ class QgsComposerShape: QgsComposerItem
|
||||
virtual void drawFrame( QPainter* p );
|
||||
/* reimplement drawBackground, since it's not a rect, but a custom shape */
|
||||
virtual void drawBackground( QPainter* p );
|
||||
/**reimplement estimatedFrameBleed, since frames on shapes are drawn using symbology
|
||||
* rather than the item's pen */
|
||||
virtual double estimatedFrameBleed() const;
|
||||
public slots:
|
||||
/**Should be called after the shape's symbol is changed. Redraws the shape and recalculates
|
||||
* its selection bounds.
|
||||
* Note: added in version 2.1*/
|
||||
void refreshSymbol();
|
||||
};
|
||||
|
@ -196,9 +196,7 @@ void QgsComposerItemWidget::on_mOutlineWidthSpinBox_valueChanged( double d )
|
||||
}
|
||||
|
||||
mItem->beginCommand( tr( "Item outline width" ), QgsComposerMergeCommand::ItemOutlineWidth );
|
||||
QPen itemPen = mItem->pen();
|
||||
itemPen.setWidthF( d );
|
||||
mItem->setPen( itemPen );
|
||||
mItem->setFrameOutlineWidth( d );
|
||||
mItem->endCommand();
|
||||
}
|
||||
|
||||
|
@ -206,9 +206,7 @@ void QgsComposerScaleBarWidget::on_mLineWidthSpinBox_valueChanged( double d )
|
||||
|
||||
mComposerScaleBar->beginCommand( tr( "Scalebar line width" ), QgsComposerMergeCommand::ScaleBarLineWidth );
|
||||
disconnectUpdateSignal();
|
||||
QPen newPen( mComposerScaleBar->pen().color() );
|
||||
newPen.setWidthF( d );
|
||||
mComposerScaleBar->setPen( newPen );
|
||||
mComposerScaleBar->setFrameOutlineWidth( d );
|
||||
mComposerScaleBar->update();
|
||||
connectUpdateSignal();
|
||||
mComposerScaleBar->endCommand();
|
||||
|
@ -123,6 +123,7 @@ void QgsComposerShapeWidget::updateShapeStyle()
|
||||
{
|
||||
if ( mComposerShape )
|
||||
{
|
||||
mComposerShape->refreshSymbol();
|
||||
QIcon icon = QgsSymbolLayerV2Utils::symbolPreviewIcon( mComposerShape->shapeStyleSymbol(), mShapeStyleButton->iconSize() );
|
||||
mShapeStyleButton->setIcon( icon );
|
||||
}
|
||||
|
@ -349,6 +349,41 @@ bool QgsComposerItem::_readXML( const QDomElement& itemElem, const QDomDocument&
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgsComposerItem::setFrameEnabled( bool drawFrame )
|
||||
{
|
||||
mFrame = drawFrame;
|
||||
emit frameChanged();
|
||||
}
|
||||
|
||||
void QgsComposerItem::setFrameOutlineWidth( double outlineWidth )
|
||||
{
|
||||
QPen itemPen = pen();
|
||||
if ( itemPen.widthF() == outlineWidth )
|
||||
{
|
||||
//no change
|
||||
return;
|
||||
}
|
||||
itemPen.setWidthF( outlineWidth );
|
||||
setPen( itemPen );
|
||||
emit frameChanged();
|
||||
}
|
||||
|
||||
double QgsComposerItem::estimatedFrameBleed() const
|
||||
{
|
||||
if ( !hasFrame() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pen().widthF() / 2.0;
|
||||
}
|
||||
|
||||
QRectF QgsComposerItem::rectWithFrame() const
|
||||
{
|
||||
double frameBleed = estimatedFrameBleed();
|
||||
return rect().adjusted( -frameBleed, -frameBleed, frameBleed, frameBleed );
|
||||
}
|
||||
|
||||
void QgsComposerItem::beginCommand( const QString& commandText, QgsComposerMergeCommand::Context c )
|
||||
{
|
||||
if ( mComposition )
|
||||
@ -432,7 +467,7 @@ void QgsComposerItem::setItemPosition( double x, double y, ItemPositionMode item
|
||||
setItemPosition( x, y, width, height, itemPoint );
|
||||
}
|
||||
|
||||
void QgsComposerItem::setItemPosition( double x, double y, double width, double height, ItemPositionMode itemPoint )
|
||||
void QgsComposerItem::setItemPosition( double x, double y, double width, double height, ItemPositionMode itemPoint, bool posIncludesFrame )
|
||||
{
|
||||
double upperLeftX = x;
|
||||
double upperLeftY = y;
|
||||
@ -460,6 +495,28 @@ void QgsComposerItem::setItemPosition( double x, double y, double width, double
|
||||
upperLeftY -= height;
|
||||
}
|
||||
|
||||
if ( posIncludesFrame )
|
||||
{
|
||||
//adjust position to account for frame size
|
||||
|
||||
if ( mItemRotation == 0 )
|
||||
{
|
||||
upperLeftX += estimatedFrameBleed();
|
||||
upperLeftY += estimatedFrameBleed();
|
||||
}
|
||||
else
|
||||
{
|
||||
//adjust position for item rotation
|
||||
QLineF lineToItemOrigin = QLineF( 0, 0, estimatedFrameBleed(), estimatedFrameBleed() );
|
||||
lineToItemOrigin.setAngle( -45 - mItemRotation );
|
||||
upperLeftX += lineToItemOrigin.x2();
|
||||
upperLeftY += lineToItemOrigin.y2();
|
||||
}
|
||||
|
||||
width -= 2 * estimatedFrameBleed();
|
||||
height -= 2 * estimatedFrameBleed();
|
||||
}
|
||||
|
||||
setSceneRect( QRectF( upperLeftX, upperLeftY, width, height ) );
|
||||
}
|
||||
|
||||
|
@ -137,8 +137,9 @@ class CORE_EXPORT QgsComposerItem: public QObject, public QGraphicsRectItem
|
||||
void setItemPosition( double x, double y, ItemPositionMode itemPoint = UpperLeft );
|
||||
|
||||
/**Sets item position and width / height in one go
|
||||
*@param posIncludesFrame set to true if the position and size arguments include the item's frame border
|
||||
@note: this method was added in version 1.6*/
|
||||
void setItemPosition( double x, double y, double width, double height, ItemPositionMode itemPoint = UpperLeft );
|
||||
void setItemPosition( double x, double y, double width, double height, ItemPositionMode itemPoint = UpperLeft, bool posIncludesFrame = false );
|
||||
|
||||
/**Returns item's last used position mode.
|
||||
@note: This property has no effect on actual's item position, which is always the top-left corner.
|
||||
@ -180,8 +181,33 @@ class CORE_EXPORT QgsComposerItem: public QObject, public QGraphicsRectItem
|
||||
* @note introduced in 1.8
|
||||
* @see hasFrame
|
||||
*/
|
||||
void setFrameEnabled( bool drawFrame ) {mFrame = drawFrame;}
|
||||
void setFrameEnabled( bool drawFrame );
|
||||
|
||||
/** Sets frame outline width
|
||||
* @param outlineWidth new width for outline frame
|
||||
* @returns nothing
|
||||
* @note introduced in 2.2
|
||||
* @see setFrameEnabled
|
||||
*/
|
||||
virtual void setFrameOutlineWidth( double outlineWidth );
|
||||
|
||||
/** Returns the estimated amount the item's frame bleeds outside the item's
|
||||
* actual rectangle. For instance, if the item has a 2mm frame outline, then
|
||||
* 1mm of this frame is drawn outside the item's rect. In this case the
|
||||
* return value will be 1.0
|
||||
* @note introduced in 2.2
|
||||
*/
|
||||
virtual double estimatedFrameBleed() const;
|
||||
|
||||
/** Returns the item's rectangular bounds, including any bleed caused by the item's frame.
|
||||
* The bounds are returned in the item's coordinate system (see Qt's QGraphicsItem docs for
|
||||
* more details about QGraphicsItem coordinate systems). The results differ from Qt's rect()
|
||||
* function, as rect() makes no allowances for the portion of outlines which are drawn
|
||||
* outside of the item.
|
||||
* @note introduced in 2.2
|
||||
* @see estimatedFrameBleed
|
||||
*/
|
||||
virtual QRectF rectWithFrame() const;
|
||||
|
||||
/** Whether this item has a Background or not.
|
||||
* @returns true if there is a Background around this item, otherwise false.
|
||||
@ -456,6 +482,10 @@ class CORE_EXPORT QgsComposerItem: public QObject, public QGraphicsRectItem
|
||||
void itemChanged();
|
||||
/**Emitted if the rectangle changes*/
|
||||
void sizeChanged();
|
||||
/**Emitted if the item's frame style changes
|
||||
* @note: this function was introduced in version 2.2
|
||||
*/
|
||||
void frameChanged();
|
||||
private:
|
||||
// id (not unique)
|
||||
QString mId;
|
||||
|
@ -153,7 +153,7 @@ void QgsComposerMouseHandles::drawSelectedItemBounds( QPainter* painter )
|
||||
{
|
||||
//if currently dragging, draw selected item bounds relative to current mouse position
|
||||
//first, get bounds of current item in scene coordinates
|
||||
QPolygonF itemSceneBounds = ( *itemIter )->mapToScene(( *itemIter )->rect() );
|
||||
QPolygonF itemSceneBounds = ( *itemIter )->mapToScene(( *itemIter )->rectWithFrame() );
|
||||
//now, translate it by the current movement amount
|
||||
//IMPORTANT - this is done in scene coordinates, since we don't want any rotation/non-translation transforms to affect the movement
|
||||
itemSceneBounds.translate( transform().dx(), transform().dy() );
|
||||
@ -166,7 +166,7 @@ void QgsComposerMouseHandles::drawSelectedItemBounds( QPainter* painter )
|
||||
if ( selectedItems.size() > 1 )
|
||||
{
|
||||
//get item bounds in mouse handle item's coordinate system
|
||||
QRectF itemRect = mapRectFromItem(( *itemIter ), ( *itemIter )->rect() );
|
||||
QRectF itemRect = mapRectFromItem(( *itemIter ), ( *itemIter )->rectWithFrame() );
|
||||
//now, resize it relative to the current resized dimensions of the mouse handles
|
||||
QgsComposition::relativeResizeRect( itemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
|
||||
itemBounds = QPolygonF( itemRect );
|
||||
@ -180,7 +180,7 @@ void QgsComposerMouseHandles::drawSelectedItemBounds( QPainter* painter )
|
||||
else
|
||||
{
|
||||
//not resizing or moving, so just map from scene bounds
|
||||
itemBounds = mapRectFromItem(( *itemIter ), ( *itemIter )->rect() );
|
||||
itemBounds = mapRectFromItem(( *itemIter ), ( *itemIter )->rectWithFrame() );
|
||||
}
|
||||
painter->drawPolygon( itemBounds );
|
||||
}
|
||||
@ -189,7 +189,7 @@ void QgsComposerMouseHandles::drawSelectedItemBounds( QPainter* painter )
|
||||
|
||||
void QgsComposerMouseHandles::selectionChanged()
|
||||
{
|
||||
//listen out for selected items' sizeChanged signal
|
||||
//listen out for selected items' size and rotation changed signals
|
||||
QList<QGraphicsItem *> itemList = composition()->items();
|
||||
QList<QGraphicsItem *>::iterator itemIt = itemList.begin();
|
||||
for ( ; itemIt != itemList.end(); ++itemIt )
|
||||
@ -201,10 +201,13 @@ void QgsComposerMouseHandles::selectionChanged()
|
||||
{
|
||||
QObject::connect( item, SIGNAL( sizeChanged() ), this, SLOT( selectedItemSizeChanged() ) );
|
||||
QObject::connect( item, SIGNAL( itemRotationChanged( double ) ), this, SLOT( selectedItemRotationChanged() ) );
|
||||
QObject::connect( item, SIGNAL( frameChanged( ) ), this, SLOT( selectedItemSizeChanged() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
QObject::disconnect( item, SIGNAL( sizeChanged() ), this, 0 );
|
||||
QObject::disconnect( item, SIGNAL( itemRotationChanged( double ) ), this, 0 );
|
||||
QObject::disconnect( item, SIGNAL( frameChanged( ) ), this, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -279,12 +282,12 @@ QRectF QgsComposerMouseHandles::selectionBounds() const
|
||||
QList<QgsComposerItem*>::iterator itemIter = selectedItems.begin();
|
||||
|
||||
//start with handle bounds of first selected item
|
||||
QRectF bounds = mapFromItem(( *itemIter ), ( *itemIter )->rect() ).boundingRect();
|
||||
QRectF bounds = mapFromItem(( *itemIter ), ( *itemIter )->rectWithFrame() ).boundingRect();
|
||||
|
||||
//iterate through remaining items, expanding the bounds as required
|
||||
for ( ++itemIter; itemIter != selectedItems.end(); ++itemIter )
|
||||
{
|
||||
bounds = bounds.united( mapFromItem(( *itemIter ), ( *itemIter )->rect() ).boundingRect() );
|
||||
bounds = bounds.united( mapFromItem(( *itemIter ), ( *itemIter )->rectWithFrame() ).boundingRect() );
|
||||
}
|
||||
|
||||
return bounds;
|
||||
@ -627,19 +630,19 @@ void QgsComposerMouseHandles::mouseReleaseEvent( QGraphicsSceneMouseEvent* event
|
||||
QRectF itemRect;
|
||||
if ( selectedItems.size() == 1 )
|
||||
{
|
||||
//only a single item is selected, so set it's size to the final resized mouse handle size
|
||||
//only a single item is selected, so set its size to the final resized mouse handle size
|
||||
itemRect = mResizeRect;
|
||||
}
|
||||
else
|
||||
{
|
||||
//multiple items selected, so each needs to be scaled relatively to the final size of the mouse handles
|
||||
itemRect = mapRectFromItem(( *itemIter ), ( *itemIter )->rect() );
|
||||
itemRect = mapRectFromItem(( *itemIter ), ( *itemIter )->rectWithFrame() );
|
||||
QgsComposition::relativeResizeRect( itemRect, QRectF( -mResizeMoveX, -mResizeMoveY, mBeginHandleWidth, mBeginHandleHeight ), mResizeRect );
|
||||
}
|
||||
|
||||
itemRect = itemRect.normalized();
|
||||
QPointF newPos = mapToScene( itemRect.topLeft() );
|
||||
( *itemIter )->setItemPosition( newPos.x(), newPos.y(), itemRect.width(), itemRect.height() );
|
||||
( *itemIter )->setItemPosition( newPos.x(), newPos.y(), itemRect.width(), itemRect.height(), QgsComposerItem::UpperLeft, true );
|
||||
|
||||
subcommand->saveAfterState();
|
||||
}
|
||||
@ -1255,7 +1258,7 @@ void QgsComposerMouseHandles::collectAlignCoordinates( QMap< double, const QgsCo
|
||||
}
|
||||
else
|
||||
{
|
||||
itemRect = currentItem->sceneBoundingRect();
|
||||
itemRect = currentItem->mapRectToScene( currentItem->rectWithFrame() );
|
||||
}
|
||||
alignCoordsX.insert( itemRect.left(), currentItem );
|
||||
alignCoordsX.insert( itemRect.right(), currentItem );
|
||||
|
@ -59,6 +59,13 @@ void QgsComposerShape::setShapeStyleSymbol( QgsFillSymbolV2* symbol )
|
||||
delete mShapeStyleSymbol;
|
||||
mShapeStyleSymbol = symbol;
|
||||
update();
|
||||
emit frameChanged();
|
||||
}
|
||||
|
||||
void QgsComposerShape::refreshSymbol()
|
||||
{
|
||||
update();
|
||||
emit frameChanged();
|
||||
}
|
||||
|
||||
void QgsComposerShape::createDefaultShapeStyleSymbol()
|
||||
@ -242,6 +249,10 @@ void QgsComposerShape::drawBackground( QPainter* p )
|
||||
}
|
||||
}
|
||||
|
||||
double QgsComposerShape::estimatedFrameBleed() const
|
||||
{
|
||||
return QgsSymbolLayerV2Utils::estimateMaxSymbolBleed( mShapeStyleSymbol );
|
||||
}
|
||||
|
||||
bool QgsComposerShape::writeXML( QDomElement& elem, QDomDocument & doc ) const
|
||||
{
|
||||
|
@ -85,6 +85,15 @@ class CORE_EXPORT QgsComposerShape: public QgsComposerItem
|
||||
virtual void drawFrame( QPainter* p );
|
||||
/* reimplement drawBackground, since it's not a rect, but a custom shape */
|
||||
virtual void drawBackground( QPainter* p );
|
||||
/**reimplement estimatedFrameBleed, since frames on shapes are drawn using symbology
|
||||
* rather than the item's pen */
|
||||
virtual double estimatedFrameBleed() const;
|
||||
|
||||
public slots:
|
||||
/**Should be called after the shape's symbol is changed. Redraws the shape and recalculates
|
||||
* its selection bounds.
|
||||
* Note: added in version 2.1*/
|
||||
void refreshSymbol();
|
||||
|
||||
private:
|
||||
/**Ellipse, rectangle or triangle*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user