mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2025-12-20 16:20:52 +01:00
Element primitive decorator : the handlers keep the same size at screen, no matter the zoom
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@4052 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
@@ -32,7 +32,8 @@
|
|||||||
@param parent Parent QGraphicsItem
|
@param parent Parent QGraphicsItem
|
||||||
*/
|
*/
|
||||||
ElementPrimitiveDecorator::ElementPrimitiveDecorator(QGraphicsItem *parent):
|
ElementPrimitiveDecorator::ElementPrimitiveDecorator(QGraphicsItem *parent):
|
||||||
QGraphicsObject(parent)
|
QGraphicsObject(parent),
|
||||||
|
m_handler(10)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@@ -66,11 +67,13 @@ QRectF ElementPrimitiveDecorator::internalBoundingRect() const {
|
|||||||
/**
|
/**
|
||||||
@return the outer bounds of the decorator as a rectangle.
|
@return the outer bounds of the decorator as a rectangle.
|
||||||
*/
|
*/
|
||||||
QRectF ElementPrimitiveDecorator::boundingRect() const {
|
QRectF ElementPrimitiveDecorator::boundingRect() const
|
||||||
const qreal additional_margin = 2.5;
|
{
|
||||||
|
QVector<QRectF> rect_vector = m_handler.handlerRect(getResizingsPoints());
|
||||||
|
|
||||||
QRectF rect = effective_bounding_rect_;
|
QRectF rect = effective_bounding_rect_;
|
||||||
rect.adjust(-additional_margin, -additional_margin, additional_margin, additional_margin);
|
rect |= rect_vector.first();
|
||||||
|
rect |= rect_vector.last();
|
||||||
return(rect);
|
return(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +86,8 @@ QRectF ElementPrimitiveDecorator::boundingRect() const {
|
|||||||
widget that is being painted on; otherwise, it is 0. For cached painting,
|
widget that is being painted on; otherwise, it is 0. For cached painting,
|
||||||
widget is always 0.
|
widget is always 0.
|
||||||
*/
|
*/
|
||||||
void ElementPrimitiveDecorator::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
|
void ElementPrimitiveDecorator::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
|
{
|
||||||
Q_UNUSED(option)
|
Q_UNUSED(option)
|
||||||
Q_UNUSED(widget)
|
Q_UNUSED(widget)
|
||||||
painter -> save();
|
painter -> save();
|
||||||
@@ -92,9 +96,10 @@ void ElementPrimitiveDecorator::paint(QPainter *painter, const QStyleOptionGraph
|
|||||||
QPen pen(Qt::DashLine);
|
QPen pen(Qt::DashLine);
|
||||||
pen.setCosmetic(true);
|
pen.setCosmetic(true);
|
||||||
painter -> setPen(pen);
|
painter -> setPen(pen);
|
||||||
//QGraphicsItemGroup::paint(painter, option, widget);
|
|
||||||
painter -> drawRect(modified_bounding_rect_);
|
painter -> drawRect(modified_bounding_rect_);
|
||||||
drawSquares(painter, option, widget);
|
//Draw the handler
|
||||||
|
foreach (QPointF point, getResizingsPoints())
|
||||||
|
m_handler.DrawHandler(painter, point, decorated_items_.size()-1);
|
||||||
|
|
||||||
// uncomment to draw the real bouding rect (=adjusted internal bounding rect)
|
// uncomment to draw the real bouding rect (=adjusted internal bounding rect)
|
||||||
// painter -> setBrush(QBrush(QColor(240, 0, 0, 127)));
|
// painter -> setBrush(QBrush(QColor(240, 0, 0, 127)));
|
||||||
@@ -184,42 +189,47 @@ void ElementPrimitiveDecorator::adjust() {
|
|||||||
Handle events generated when the mouse hovers over the decorator.
|
Handle events generated when the mouse hovers over the decorator.
|
||||||
@param event Object describing the hover event.
|
@param event Object describing the hover event.
|
||||||
*/
|
*/
|
||||||
void ElementPrimitiveDecorator::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
void ElementPrimitiveDecorator::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
|
||||||
QList<QRectF> rects = getResizingSquares();
|
{
|
||||||
QPointF pos = event -> pos();
|
int p = m_handler.pointIsHoverHandler(event->pos(), getResizingsPoints());
|
||||||
|
|
||||||
if (rects.at(QET::ResizeFromTopLeftCorner).contains(pos) || rects.at(QET::ResizeFromBottomRightCorner).contains(pos)) {
|
if (p == 0 || p == 7)
|
||||||
setCursor(Qt::SizeFDiagCursor);
|
setCursor(Qt::SizeFDiagCursor);
|
||||||
} else if (rects.at(QET::ResizeFromTopRightCorner).contains(pos) || rects.at(QET::ResizeFromBottomLeftCorner).contains(pos)) {
|
else if (p == 2 || p == 5)
|
||||||
setCursor(Qt::SizeBDiagCursor);
|
setCursor(Qt::SizeBDiagCursor);
|
||||||
} else if (rects.at(QET::ResizeFromTopCenterCorner).contains(pos) || rects.at(QET::ResizeFromBottomCenterCorner).contains(pos)) {
|
else if (p == 1 || p ==6)
|
||||||
setCursor(Qt::SizeVerCursor);
|
setCursor(Qt::SizeVerCursor);
|
||||||
} else if (rects.at(QET::ResizeFromMiddleLeftCorner).contains(pos) || rects.at(QET::ResizeFromMiddleRightCorner).contains(pos)) {
|
else if (p == 3 || p == 4)
|
||||||
setCursor(Qt::SizeHorCursor);
|
setCursor(Qt::SizeHorCursor);
|
||||||
} else if (internalBoundingRect().contains(pos)) {
|
else if (p == -1 && modified_bounding_rect_.normalized().contains(event->pos()))
|
||||||
setCursor(Qt::SizeAllCursor);
|
setCursor(Qt::SizeAllCursor);
|
||||||
} else {
|
else
|
||||||
setCursor(Qt::ArrowCursor);
|
setCursor(Qt::ArrowCursor);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Handle event generated when mouse buttons are pressed.
|
Handle event generated when mouse buttons are pressed.
|
||||||
@param event Object describing the mouse event
|
@param event Object describing the mouse event
|
||||||
*/
|
*/
|
||||||
void ElementPrimitiveDecorator::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
void ElementPrimitiveDecorator::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
QList<QRectF> rects = getResizingSquares();
|
{
|
||||||
QPointF pos = event -> pos();
|
QPointF pos = event -> pos();
|
||||||
|
QVector <QPointF> points = getResizingsPoints();
|
||||||
|
|
||||||
current_operation_square_ = resizingSquareAtPos(pos);
|
current_operation_square_ = m_handler.pointIsHoverHandler(pos, points);
|
||||||
bool accept = false;
|
bool accept = false;
|
||||||
if (current_operation_square_ != QET::NoOperation) {
|
|
||||||
|
if (current_operation_square_ != QET::NoOperation)
|
||||||
accept = true;
|
accept = true;
|
||||||
} else {
|
else
|
||||||
if (internalBoundingRect().contains(pos)) {
|
{
|
||||||
if (CustomElementPart *single_item = singleItem()) {
|
if (internalBoundingRect().contains(pos))
|
||||||
|
{
|
||||||
|
if (CustomElementPart *single_item = singleItem())
|
||||||
|
{
|
||||||
bool event_accepted = single_item -> singleItemPressEvent(this, event);
|
bool event_accepted = single_item -> singleItemPressEvent(this, event);
|
||||||
if (event_accepted) {
|
if (event_accepted)
|
||||||
|
{
|
||||||
event -> ignore();
|
event -> ignore();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -229,19 +239,21 @@ void ElementPrimitiveDecorator::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accept) {
|
if (accept)
|
||||||
if (current_operation_square_ > QET::NoOperation) {
|
{
|
||||||
first_pos_ = latest_pos_ = mapToScene(rects.at(current_operation_square_).center());
|
if (current_operation_square_ > QET::NoOperation)
|
||||||
} else {
|
first_pos_ = latest_pos_ = mapToScene(points.at(current_operation_square_));
|
||||||
|
else
|
||||||
|
{
|
||||||
first_pos_ = decorated_items_.at(0) -> toItem() -> scenePos();
|
first_pos_ = decorated_items_.at(0) -> toItem() -> scenePos();
|
||||||
latest_pos_ = event -> scenePos();
|
latest_pos_ = event -> scenePos();
|
||||||
mouse_offset_ = event -> scenePos() - first_pos_;
|
mouse_offset_ = event -> scenePos() - first_pos_;
|
||||||
}
|
}
|
||||||
startMovement();
|
startMovement();
|
||||||
event -> accept();
|
event -> accept();
|
||||||
} else {
|
|
||||||
event -> ignore();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
event -> ignore();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -264,9 +276,8 @@ void ElementPrimitiveDecorator::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *
|
|||||||
@param event Object describing the mouse event
|
@param event Object describing the mouse event
|
||||||
@see QGraphicsScene::mouseGrabberItem()
|
@see QGraphicsScene::mouseGrabberItem()
|
||||||
*/
|
*/
|
||||||
void ElementPrimitiveDecorator::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
void ElementPrimitiveDecorator::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||||
QList<QRectF> rects = getResizingSquares();
|
{
|
||||||
|
|
||||||
QPointF scene_pos = event -> scenePos();
|
QPointF scene_pos = event -> scenePos();
|
||||||
QPointF movement = scene_pos - latest_pos_;
|
QPointF movement = scene_pos - latest_pos_;
|
||||||
|
|
||||||
@@ -299,7 +310,7 @@ void ElementPrimitiveDecorator::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
QPointF rounded_scene_pos = first_pos_ + rounded_global_movement;
|
QPointF rounded_scene_pos = first_pos_ + rounded_global_movement;
|
||||||
|
|
||||||
// when scaling the selection, consider the center of the currently dragged resizing rectangle
|
// when scaling the selection, consider the center of the currently dragged resizing rectangle
|
||||||
QPointF current_position = mapToScene(rects.at(current_operation_square_).center());
|
QPointF current_position = mapToScene(getResizingsPoints().at(current_operation_square_));
|
||||||
// determine the final, effective movement
|
// determine the final, effective movement
|
||||||
movement = rounded_scene_pos - current_position;
|
movement = rounded_scene_pos - current_position;
|
||||||
}
|
}
|
||||||
@@ -556,119 +567,30 @@ QRectF ElementPrimitiveDecorator::getSceneBoundingRect(QGraphicsItem *item) cons
|
|||||||
return(item -> mapRectToScene(item -> boundingRect()));
|
return(item -> mapRectToScene(item -> boundingRect()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
QVector<QPointF> ElementPrimitiveDecorator::getResizingsPoints() const
|
||||||
Draw all known resizing squares using \a painter.
|
{
|
||||||
@param option The option parameter provides style options for the item, such
|
|
||||||
as its state, exposed area and its level-of-detail hints.
|
|
||||||
@param The widget argument is optional. If provided, it points to the
|
|
||||||
widget that is being painted on; otherwise, it is 0. For cached painting,
|
|
||||||
widget is always 0.
|
|
||||||
*/
|
|
||||||
void ElementPrimitiveDecorator::drawSquares(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
|
|
||||||
foreach (QRectF rect, getResizingSquares()) {
|
|
||||||
drawResizeSquare(painter, option, widget, rect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Draw the provided resizing square \a rect using \a painter.
|
|
||||||
@param option The option parameter provides style options for the item, such
|
|
||||||
as its state, exposed area and its level-of-detail hints.
|
|
||||||
@param The widget argument is optional. If provided, it points to the
|
|
||||||
widget that is being painted on; otherwise, it is 0. For cached painting,
|
|
||||||
widget is always 0.
|
|
||||||
*/
|
|
||||||
void ElementPrimitiveDecorator::drawResizeSquare(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, const QRectF &rect) {
|
|
||||||
QColor inner(0xFF, 0xFF, 0xFF);
|
|
||||||
QColor outer(0x00, 0x61, 0xFF);
|
|
||||||
if (decorated_items_.count() > 1) {
|
|
||||||
outer = QColor(0x1A, 0x5C, 0x14);
|
|
||||||
}
|
|
||||||
drawGenericSquare(painter, option, widget, rect, inner, outer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Draw a generic square \a rect using \a painter.
|
|
||||||
@param inner Color used to fill the square
|
|
||||||
@param outer Color usd to draw the outline
|
|
||||||
@param option The option parameter provides style options for the item, such
|
|
||||||
as its state, exposed area and its level-of-detail hints.
|
|
||||||
@param The widget argument is optional. If provided, it points to the
|
|
||||||
widget that is being painted on; otherwise, it is 0. For cached painting,
|
|
||||||
widget is always 0.
|
|
||||||
*/
|
|
||||||
void ElementPrimitiveDecorator::drawGenericSquare(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, const QRectF &rect, const QColor &inner, const QColor &outer) {
|
|
||||||
Q_UNUSED(option)
|
|
||||||
Q_UNUSED(widget)
|
|
||||||
// 1.0px will end up to level_of_details px once rendered
|
|
||||||
// qreal level_of_details = option->levelOfDetailFromTransform(painter -> transform());
|
|
||||||
|
|
||||||
painter -> save();
|
|
||||||
painter -> setBrush(QBrush(inner));
|
|
||||||
QPen square_pen(QBrush(outer), 2.0, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin);
|
|
||||||
square_pen.setCosmetic(true);
|
|
||||||
painter -> setPen(square_pen);
|
|
||||||
painter -> drawRect(rect);
|
|
||||||
painter -> restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@return A list containing all known resizing squares, based on the
|
|
||||||
modified_bounding_rect_ attribute. They are ordered following
|
|
||||||
QET::OperationAreas, so it is possible to use positive values from this enum
|
|
||||||
to fetch the corresponding square in the list.
|
|
||||||
@see QET::OperationAreas
|
|
||||||
*/
|
|
||||||
QList<QRectF> ElementPrimitiveDecorator::getResizingSquares() {
|
|
||||||
QRectF primitive_rect = modified_bounding_rect_;
|
QRectF primitive_rect = modified_bounding_rect_;
|
||||||
QRectF half_primitive_rect1 = primitive_rect;
|
QVector <QPointF> vector;
|
||||||
half_primitive_rect1.setHeight(half_primitive_rect1.height() / 2.0);
|
QPointF half;
|
||||||
QRectF half_primitive_rect2 = primitive_rect;
|
|
||||||
half_primitive_rect2.setWidth(half_primitive_rect2.width() / 2.0);
|
|
||||||
|
|
||||||
QList<QRectF> rects;
|
vector << primitive_rect.topLeft(); //top left
|
||||||
|
half = primitive_rect.center();
|
||||||
|
half.setY(primitive_rect.top());
|
||||||
|
vector << half; //middle top
|
||||||
|
vector << primitive_rect.topRight(); //top right
|
||||||
|
half = primitive_rect.center();
|
||||||
|
half.setX(primitive_rect.left());
|
||||||
|
vector << half; //middle left
|
||||||
|
half = primitive_rect.center();
|
||||||
|
half.setX(primitive_rect.right());
|
||||||
|
vector << half; //middle right
|
||||||
|
vector << primitive_rect.bottomLeft(); //bottom left
|
||||||
|
half = primitive_rect.center();
|
||||||
|
half.setY(primitive_rect.bottom());
|
||||||
|
vector << half; //middle bottom
|
||||||
|
vector << primitive_rect.bottomRight(); //bottom right
|
||||||
|
|
||||||
rects << getGenericSquare(primitive_rect.topLeft());
|
return vector;
|
||||||
rects << getGenericSquare(half_primitive_rect2.topRight());
|
|
||||||
rects << getGenericSquare(primitive_rect.topRight());
|
|
||||||
rects << getGenericSquare(half_primitive_rect1.bottomLeft());
|
|
||||||
rects << getGenericSquare(half_primitive_rect1.bottomRight());
|
|
||||||
rects << getGenericSquare(primitive_rect.bottomLeft());
|
|
||||||
rects << getGenericSquare(half_primitive_rect2.bottomRight());
|
|
||||||
rects << getGenericSquare(primitive_rect.bottomRight());
|
|
||||||
|
|
||||||
/// TODO cache the rects instead of calculating them again and again?
|
|
||||||
return(rects);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@return the square to be drawn to represent \a position
|
|
||||||
*/
|
|
||||||
QRectF ElementPrimitiveDecorator::getGenericSquare(const QPointF &position) {
|
|
||||||
const qreal square_half_size = 0.5;
|
|
||||||
return(
|
|
||||||
QRectF(
|
|
||||||
position.x() - square_half_size,
|
|
||||||
position.y() - square_half_size,
|
|
||||||
square_half_size * 2.0,
|
|
||||||
square_half_size * 2.0
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@return the index of the square containing the \a position point or -1 if
|
|
||||||
none matches.
|
|
||||||
*/
|
|
||||||
int ElementPrimitiveDecorator::resizingSquareAtPos(const QPointF &position) {
|
|
||||||
QList<QRectF> rects = getResizingSquares();
|
|
||||||
int current_square = QET::NoOperation;
|
|
||||||
for (int i = 0 ; i < rects.count() ; ++ i) {
|
|
||||||
if (rects.at(i).contains(position)) {
|
|
||||||
current_square = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(current_square);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,8 +17,11 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef ELEMENTPRIMITIVEDECORATOR_H
|
#ifndef ELEMENTPRIMITIVEDECORATOR_H
|
||||||
#define ELEMENTPRIMITIVEDECORATOR_H
|
#define ELEMENTPRIMITIVEDECORATOR_H
|
||||||
|
|
||||||
#include <QGraphicsObject>
|
#include <QGraphicsObject>
|
||||||
#include "qet.h"
|
#include "qet.h"
|
||||||
|
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
|
||||||
|
|
||||||
class ElementEditionCommand;
|
class ElementEditionCommand;
|
||||||
class ElementScene;
|
class ElementScene;
|
||||||
class CustomElementPart;
|
class CustomElementPart;
|
||||||
@@ -34,7 +37,8 @@ class CustomElementPart;
|
|||||||
- the new bounding rect, after the user moved or resized items
|
- the new bounding rect, after the user moved or resized items
|
||||||
- the former bounding rect, due to implementation details
|
- the former bounding rect, due to implementation details
|
||||||
*/
|
*/
|
||||||
class ElementPrimitiveDecorator : public QGraphicsObject {
|
class ElementPrimitiveDecorator : public QGraphicsObject
|
||||||
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -83,12 +87,7 @@ class ElementPrimitiveDecorator : public QGraphicsObject {
|
|||||||
void translateItems(const QPointF &);
|
void translateItems(const QPointF &);
|
||||||
void scaleItems(const QRectF &, const QRectF &);
|
void scaleItems(const QRectF &, const QRectF &);
|
||||||
QRectF getSceneBoundingRect(QGraphicsItem *) const;
|
QRectF getSceneBoundingRect(QGraphicsItem *) const;
|
||||||
void drawSquares(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
|
QVector <QPointF> getResizingsPoints() const;
|
||||||
void drawResizeSquare(QPainter *, const QStyleOptionGraphicsItem *, QWidget *, const QRectF &);
|
|
||||||
void drawGenericSquare(QPainter *, const QStyleOptionGraphicsItem *, QWidget *, const QRectF &, const QColor &, const QColor &);
|
|
||||||
QList<QRectF> getResizingSquares();
|
|
||||||
QRectF getGenericSquare(const QPointF &);
|
|
||||||
int resizingSquareAtPos(const QPointF &);
|
|
||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
private:
|
private:
|
||||||
@@ -109,6 +108,7 @@ class ElementPrimitiveDecorator : public QGraphicsObject {
|
|||||||
QPointF mouse_offset_; ///< Offset between the mouse position and the point to be snapped to grid when moving selection
|
QPointF mouse_offset_; ///< Offset between the mouse position and the point to be snapped to grid when moving selection
|
||||||
bool moving_by_keys_; ///< Whether we are currently moving our decorated items using the arrow keys
|
bool moving_by_keys_; ///< Whether we are currently moving our decorated items using the arrow keys
|
||||||
QPointF keys_movement_; ///< Movement applied to our decorated items using the arrow keys
|
QPointF keys_movement_; ///< Movement applied to our decorated items using the arrow keys
|
||||||
|
QetGraphicsHandlerUtility m_handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user