summaryrefslogtreecommitdiffstats
path: root/src/measure-context.cpp
diff options
context:
space:
mode:
authorJon A. Cruz <jon@joncruz.org>2012-06-05 08:12:11 +0000
committerJon A. Cruz <jon@joncruz.org>2012-06-05 08:12:11 +0000
commite49f8336142eda7a88587b85b78f4cad175aef28 (patch)
tree1412a001baee9c1102d53eada14906899bdfb227 /src/measure-context.cpp
parentLimit angle label to show up within the desktop window. Also refactor arc dra... (diff)
downloadinkscape-e49f8336142eda7a88587b85b78f4cad175aef28.tar.gz
inkscape-e49f8336142eda7a88587b85b78f4cad175aef28.zip
Allow angle measurement base to be changed by tapping space.
(bzr r11459)
Diffstat (limited to 'src/measure-context.cpp')
-rw-r--r--src/measure-context.cpp55
1 files changed, 47 insertions, 8 deletions
diff --git a/src/measure-context.cpp b/src/measure-context.cpp
index b3ea82e3b..8dfcb1441 100644
--- a/src/measure-context.cpp
+++ b/src/measure-context.cpp
@@ -12,6 +12,7 @@
#include <gdk/gdkkeysyms.h>
+#include <boost/none_t.hpp>
#include "helper/units.h"
#include "macros.h"
#include "display/curve.h"
@@ -62,6 +63,8 @@ static gint tolerance = 0;
static bool within_tolerance = false;
Geom::Point start_point;
+boost::optional<Geom::Point> explicitBase;
+boost::optional<Geom::Point> lastEnd;
std::vector<Inkscape::Display::TemporaryItem*> measure_tmp_items;
@@ -158,20 +161,21 @@ void repositionOverlappingLabels(std::vector<LabelPlacement> &placements, SPDesk
*
* @param desktop the desktop that is being used.
* @param angle the angle to be displaying.
+ * @param baseAngle the angle of the initial baseline.
* @param startPoint the point that is the vertex of the selected angle.
* @param endPoint the point that is the end the user is manipulating for measurement.
* @param fontsize the size to display the text label at.
*/
-Geom::Point calcAngleDisplayAnchor(SPDesktop *desktop, double angle,
+Geom::Point calcAngleDisplayAnchor(SPDesktop *desktop, double angle, double baseAngle,
Geom::Point const &startPoint, Geom::Point const &endPoint,
double fontsize)
{
// Time for the trick work of figuring out where things should go, and how.
- Geom::Point where = endPoint;
- Geom::Affine adjust = Geom::Affine(Geom::Translate(-startPoint))
- * Geom::Affine(Geom::Rotate(-angle / 2))
- * Geom::Affine(Geom::Translate(startPoint));
- where *= adjust;
+ double lengthVal = (endPoint - startPoint).length();
+ double effective = baseAngle + (angle / 2);
+ Geom::Point where(lengthVal, 0);
+ where *= Geom::Affine(Geom::Rotate(effective)) * Geom::Affine(Geom::Translate(startPoint));
+
// We now have the ideal position, but need to see if it will fit/work.
Geom::Rect visibleArea = desktop->get_display_area();
@@ -354,6 +358,8 @@ static gint sp_measure_context_root_handler(SPEventContext *event_context, GdkEv
case GDK_BUTTON_PRESS:
{
Geom::Point const button_w(event->button.x, event->button.y);
+ explicitBase = boost::none;
+ lastEnd = boost::none;
start_point = desktop->w2d(button_w);
if (event->button.button == 1 && !event_context->space_panning) {
// save drag origin
@@ -376,6 +382,16 @@ static gint sp_measure_context_root_handler(SPEventContext *event_context, GdkEv
break;
}
+ case GDK_KEY_PRESS:
+ {
+ if ((event->key.keyval == GDK_KEY_Shift_L) || (event->key.keyval == GDK_KEY_Shift_R)) {
+ if (lastEnd) {
+ explicitBase = lastEnd;
+ }
+ }
+ break;
+ }
+
case GDK_MOTION_NOTIFY:
{
if (!((event->motion.state & GDK_BUTTON1_MASK) && !event_context->space_panning)) {
@@ -439,6 +455,20 @@ static gint sp_measure_context_root_handler(SPEventContext *event_context, GdkEv
double deltax = end_point[Geom::X] - start_point[Geom::X];
double deltay = end_point[Geom::Y] - start_point[Geom::Y];
double angle = atan2(deltay, deltax);
+ double baseAngle = 0;
+
+ if (explicitBase) {
+ double deltax2 = explicitBase.get()[Geom::X] - start_point[Geom::X];
+ double deltay2 = explicitBase.get()[Geom::Y] - start_point[Geom::Y];
+
+ baseAngle = atan2(deltay2, deltax2);
+ angle -= baseAngle;
+ if (angle < -M_PI) {
+ angle += 2 * M_PI;
+ } else if (angle > M_PI) {
+ angle -= 2 * M_PI;
+ }
+ }
//TODO: calculate NPOINTS
//800 seems to be a good value for 800x600 resolution
@@ -558,7 +588,7 @@ static gint sp_measure_context_root_handler(SPEventContext *event_context, GdkEv
g_free(measure_str);
}
- Geom::Point angleDisplayPt = calcAngleDisplayAnchor(desktop, angle,
+ Geom::Point angleDisplayPt = calcAngleDisplayAnchor(desktop, angle, baseAngle,
start_point, end_point,
fontsize);
@@ -651,9 +681,14 @@ static gint sp_measure_context_root_handler(SPEventContext *event_context, GdkEv
measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
if ((end_point[Geom::X] != start_point[Geom::X]) && (end_point[Geom::Y] != start_point[Geom::Y])) {
- Geom::Point anchorEnd = start_point;
double length = std::abs((end_point - start_point).length());
+ Geom::Point anchorEnd = start_point;
anchorEnd[Geom::X] += length;
+ if (explicitBase) {
+ anchorEnd *= (Geom::Affine(Geom::Translate(-start_point))
+ * Geom::Affine(Geom::Rotate(baseAngle))
+ * Geom::Affine(Geom::Translate(start_point)));
+ }
SPCtrlLine *control_line = ControlManager::getManager().createControlLine(sp_desktop_tempgroup(desktop),
start_point,
@@ -726,6 +761,8 @@ static gint sp_measure_context_root_handler(SPEventContext *event_context, GdkEv
measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvasitem, 0));
}
+ lastEnd = end_point; // track in case we get a anchoring key-press later
+
gobble_motion_events(GDK_BUTTON1_MASK);
}
break;
@@ -734,6 +771,8 @@ static gint sp_measure_context_root_handler(SPEventContext *event_context, GdkEv
case GDK_BUTTON_RELEASE:
{
sp_event_context_discard_delayed_snap_event(event_context);
+ explicitBase = boost::none;
+ lastEnd = boost::none;
//clear all temporary canvas items related to the measurement tool.
for (size_t idx = 0; idx < measure_tmp_items.size(); ++idx) {