[qet] [2058] Element editor: changed the way scaling operations get rounded.

[ Thread Index | Date Index | More lists.tuxfamily.org/qet Archives ]


Revision: 2058
Author:   xavier
Date:     2013-03-06 19:51:29 +0100 (Wed, 06 Mar 2013)
Log Message:
-----------
Element editor: changed the way scaling operations get rounded.

Modified Paths:
--------------
    trunk/sources/editor/customelementpart.cpp
    trunk/sources/editor/customelementpart.h
    trunk/sources/editor/elementprimitivedecorator.cpp
    trunk/sources/editor/elementprimitivedecorator.h
    trunk/sources/editor/partpolygon.cpp
    trunk/sources/editor/partpolygon.h
    trunk/sources/qet.h

Modified: trunk/sources/editor/customelementpart.cpp
===================================================================
--- trunk/sources/editor/customelementpart.cpp	2013-03-06 18:50:46 UTC (rev 2057)
+++ trunk/sources/editor/customelementpart.cpp	2013-03-06 18:51:29 UTC (rev 2058)
@@ -60,6 +60,17 @@
 }
 
 /**
+	This method is called by the decorator when it needs to determine the best
+	way to interactively scale a primitive. It is typically called when only a
+	single primitive is being scaled.
+	The default implementation systematically returns
+	QET::SnapScalingPointToGrid
+*/
+QET::ScalingMethod CustomElementPart::preferredScalingMethod() const {
+	return(QET::SnapScalingPointToGrid);
+}
+
+/**
 	This method is called by the decorator when it manages only a single
 	primitive and it received a mouse press event.
 	The implementation should return true if the primitive accepts the event, false otherwise.

Modified: trunk/sources/editor/customelementpart.h
===================================================================
--- trunk/sources/editor/customelementpart.h	2013-03-06 18:50:46 UTC (rev 2057)
+++ trunk/sources/editor/customelementpart.h	2013-03-06 18:51:29 UTC (rev 2058)
@@ -20,6 +20,7 @@
 #include <QtGui>
 #include <QtXml>
 #include <QImage>
+#include "qet.h"
 class CustomElement;
 class ElementPrimitiveDecorator;
 class ElementScene;
@@ -101,6 +102,7 @@
 	virtual QGraphicsItem *toItem();
 	
 	virtual void setDecorator(ElementPrimitiveDecorator *);
+	virtual QET::ScalingMethod preferredScalingMethod() const;
 	virtual bool singleItemPressEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *);
 	virtual bool singleItemMoveEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *);
 	virtual bool singleItemReleaseEvent(ElementPrimitiveDecorator *, QGraphicsSceneMouseEvent *);

Modified: trunk/sources/editor/elementprimitivedecorator.cpp
===================================================================
--- trunk/sources/editor/elementprimitivedecorator.cpp	2013-03-06 18:50:46 UTC (rev 2057)
+++ trunk/sources/editor/elementprimitivedecorator.cpp	2013-03-06 18:51:29 UTC (rev 2058)
@@ -245,15 +245,30 @@
 	QPointF scene_pos = event -> scenePos();
 	QPointF movement = scene_pos - latest_pos_;
 	
-	// snap the movement to a non-visible grid when scaling selection
-	if (mustSnapToGrid(event)) {
-		// We now want some point belonging to the selection to be snapped to this rounded position
-		if (current_operation_square_ > QET::NoOperation) {
+	if (current_operation_square_ > QET::NoOperation) {
+		// This is a scaling operation.
+		
+		// For convenience purposes, we may need to adjust mouse movements.
+		QET::ScalingMethod scaling_method = scalingMethod(event);
+		if (scaling_method > QET::FreeScaling) {
 			// real, non-rounded movement from the mouse press event
 			QPointF global_movement = scene_pos - first_pos_;
 			
-			// real, rounded movement from the mouse press event
-			QPointF rounded_global_movement = snapConstPointToGrid(global_movement);
+			QPointF rounded_global_movement;
+			if (scaling_method == QET::SnapScalingPointToGrid) {
+				// real, rounded movement from the mouse press event
+				rounded_global_movement = snapConstPointToGrid(global_movement);
+			}
+			else {
+				QRectF new_bounding_rect = original_bounding_rect_;
+				applyMovementToRect(current_operation_square_, global_movement, new_bounding_rect);
+				
+				const qreal scale_epsilon = 20.0; // rounds to 0.05
+				QPointF delta = deltaForRoundScaling(original_bounding_rect_, new_bounding_rect, scale_epsilon);
+				
+				// real, rounded movement from the mouse press event
+				rounded_global_movement = global_movement + delta;
+			}
 			
 			// rounded position of the current mouse move event
 			QPointF rounded_scene_pos = first_pos_ + rounded_global_movement;
@@ -262,18 +277,22 @@
 			QPointF current_position = mapToScene(rects.at(current_operation_square_).center());
 			// determine the final, effective movement
 			movement = rounded_scene_pos - current_position;
-		} else if (current_operation_square_ == QET::MoveArea) {
-			// when moving the selection, consider the position of the first selected item
-			QPointF current_position = scene_pos - mouse_offset_;
-			QPointF rounded_current_position = snapConstPointToGrid(current_position);
-			movement = rounded_current_position - decorated_items_.at(0) -> toItem() -> scenePos();
-		} else {
-			if (CustomElementPart *single_item = singleItem()) {
-				bool event_accepted = single_item -> singleItemMoveEvent(this, event);
-				if (event_accepted) {
-					event -> ignore();
-					return;
-				}
+		}
+	}
+	else if (current_operation_square_ == QET::MoveArea) {
+		// When moving the selection, consider the position of the first selected item
+		QPointF current_position = scene_pos - mouse_offset_;
+		QPointF rounded_current_position = snapConstPointToGrid(current_position);
+		movement = rounded_current_position - decorated_items_.at(0) -> toItem() -> scenePos();
+	}
+	else {
+		// Neither a movement nor a scaling operation -- perhaps the underlying item
+		// is interested in the mouse event for custom operations?
+		if (CustomElementPart *single_item = singleItem()) {
+			bool event_accepted = single_item -> singleItemMoveEvent(this, event);
+			if (event_accepted) {
+				event -> ignore();
+				return;
 			}
 		}
 	}
@@ -628,6 +647,30 @@
 }
 
 /**
+	Receive two rects, assuming they share a common corner and current is a \a
+	scaled version of \a original.
+	Calculate the scale ratios implied by this assumption, round them to the
+	nearest multiple of \a epsilon, then return the horizontal and vertical
+	offsets to be applied in order to pass from \a current to \a original scaled
+	by the rounded factors.
+	This method can be used to adjust a mouse movement so that it inputs a
+	round scaling operation.
+*/
+QPointF ElementPrimitiveDecorator::deltaForRoundScaling(const QRectF &original, const QRectF &current, qreal epsilon) {
+	qreal sx = current.width()  / original.width();
+	qreal sy = current.height() / original.height();
+	
+	qreal sx_rounded = QET::round(sx, epsilon);
+	qreal sy_rounded = QET::round(sy, epsilon);
+	
+	QPointF delta(
+		original.width()  * (sx_rounded - sx),
+		original.height() * (sy_rounded - sy)
+	);
+	return(delta);
+}
+
+/**
 	Round the coordinates of \a point so it is snapped to the grid defined by the
 	grid_step_x_ and grid_step_y_ attributes.
 */
@@ -656,3 +699,19 @@
 bool ElementPrimitiveDecorator::mustSnapToGrid(QGraphicsSceneMouseEvent *event) {
 	return(!(event -> modifiers() & Qt::ControlModifier));
 }
+
+/**
+	@param event Mouse event during the scale operations -- simply passed to mustSnapToGrid()
+	@return the scaling method to be used for the currently decorated items.
+	@see QET::ScalingMethod
+	@see mustSnapToGrid()
+*/
+QET::ScalingMethod ElementPrimitiveDecorator::scalingMethod(QGraphicsSceneMouseEvent *event) {
+	if (event && !mustSnapToGrid(event)) {
+		return(QET::FreeScaling);
+	}
+	if (CustomElementPart *single_item = singleItem()) {
+		return single_item -> preferredScalingMethod();
+	}
+	return QET::RoundScaleRatios;
+}

Modified: trunk/sources/editor/elementprimitivedecorator.h
===================================================================
--- trunk/sources/editor/elementprimitivedecorator.h	2013-03-06 18:50:46 UTC (rev 2057)
+++ trunk/sources/editor/elementprimitivedecorator.h	2013-03-06 18:51:29 UTC (rev 2058)
@@ -1,6 +1,7 @@
 #ifndef ELEMENTPRIMITIVEDECORATOR_H
 #define ELEMENTPRIMITIVEDECORATOR_H
 #include <QGraphicsObject>
+#include "qet.h"
 class ElementEditionCommand;
 class ElementScene;
 class CustomElementPart;
@@ -49,9 +50,11 @@
 	void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
 	void keyPressEvent(QKeyEvent *);
 	void keyReleaseEvent(QKeyEvent *);
+	QPointF deltaForRoundScaling(const QRectF &, const QRectF &, qreal);
 	QPointF snapConstPointToGrid(const QPointF &) const;
 	void snapPointToGrid(QPointF &) const;
 	bool mustSnapToGrid(QGraphicsSceneMouseEvent *);
+	QET::ScalingMethod scalingMethod(QGraphicsSceneMouseEvent *);
 	
 	private:
 	void init();

Modified: trunk/sources/editor/partpolygon.cpp
===================================================================
--- trunk/sources/editor/partpolygon.cpp	2013-03-06 18:50:46 UTC (rev 2057)
+++ trunk/sources/editor/partpolygon.cpp	2013-03-06 18:51:29 UTC (rev 2058)
@@ -191,6 +191,17 @@
 }
 
 /**
+	@reimp CustomElementPart::preferredScalingMethod
+	This method is called by the decorator when it needs to determine the best
+	way to interactively scale a primitive. It is typically called when only a
+	single primitive is being scaled.
+	This reimplementation systematically returns QET::RoundScaleRatios.
+*/
+QET::ScalingMethod PartPolygon::preferredScalingMethod() const {
+	return(QET::RoundScaleRatios);
+}
+
+/**
 	@return le rectangle delimitant cette partie.
 */
 QRectF PartPolygon::boundingRect() const {

Modified: trunk/sources/editor/partpolygon.h
===================================================================
--- trunk/sources/editor/partpolygon.h	2013-03-06 18:50:46 UTC (rev 2057)
+++ trunk/sources/editor/partpolygon.h	2013-03-06 18:51:29 UTC (rev 2058)
@@ -59,6 +59,7 @@
 	virtual QRectF sceneGeometricRect() const;
 	virtual void startUserTransformation(const QRectF &);
 	virtual void handleUserTransformation(const QRectF &, const QRectF &);
+	virtual QET::ScalingMethod preferredScalingMethod() const;
 	
 	protected:
 	QVariant itemChange(GraphicsItemChange, const QVariant &);

Modified: trunk/sources/qet.h
===================================================================
--- trunk/sources/qet.h	2013-03-06 18:50:46 UTC (rev 2057)
+++ trunk/sources/qet.h	2013-03-06 18:51:29 UTC (rev 2058)
@@ -59,6 +59,13 @@
 		ResizeFromBottomRightCorner = 7
 	};
 	
+	/// Supported types of interactive scaling, typically for a single element primitive
+	enum ScalingMethod {
+		FreeScaling,              ///< do not interfer with the default scaling process
+		SnapScalingPointToGrid,   ///< snap the point used to define the new bounding rectangle to the grid
+		RoundScaleRatios          ///< adjust the scaling movement so that the induced scaling ratios are rounded
+	};
+	
 	/// Known kinds of conductor segments
 	enum ConductorSegmentType {
 		Horizontal = 1, ///< Horizontal segment 


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/