curve-drag-point.cpp revision 0d68d82e47abab250c99dd534da2e2d26b697b2d
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Control point that is dragged during path drag
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Krzysztof KosiĆski <tweenk.pl@gmail.com>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Copyright (C) 2009 Authors
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Released under GNU GPL, read the file 'COPYING' for more information
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include "ui/tool/control-point-selection.h"
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include "ui/tool/multi-path-manipulator.h"
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * @class CurveDragPoint
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * An invisible point used to drag curves. This point is used by PathManipulator to allow editing
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * of path segments by dragging them. It is defined in a separate file so that the node tool
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * can check if the mouseovered control point is a curve drag point and update the cursor
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * accordingly, without the need to drag in the full PathManipulator header.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis// This point should be invisible to the user - use the invisible_cset from control-point.h
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis// TODO make some methods from path-manipulator.cpp public so that this point doesn't have
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis// to be declared as a friend
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisbool CurveDragPoint::_drags_stroke = false;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisbool CurveDragPoint::_segment_was_degenerate = false;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr JasiukajtisCurveDragPoint::CurveDragPoint(PathManipulator &pm)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis : ControlPoint(pm._multi_path_manipulator._path_data.node_data.desktop, Geom::Point(),
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis Gtk::ANCHOR_CENTER, SP_CTRL_SHAPE_CIRCLE, 1.0, &invisible_cset,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis pm._multi_path_manipulator._path_data.dragpoint_group)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisbool CurveDragPoint::_eventHandler(SPEventContext *event_context, GdkEvent *event)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis // do not process any events when the manipulator is empty
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return ControlPoint::_eventHandler(event_context, event);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisbool CurveDragPoint::grabbed(GdkEventMotion */*event*/)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis // move the handles to 1/3 the length of the segment for line segments
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (first->front()->isDegenerate() && second->back()->isDegenerate()) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis // delta is a vector equal 1/3 of distance from first to second
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis Geom::Point delta = (second->position() - first->position()) / 3.0;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis first->front()->move(first->front()->position() + delta);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis second->back()->move(second->back()->position() - delta);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisvoid CurveDragPoint::dragged(Geom::Point &new_pos, GdkEventMotion *event)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis // special cancel handling - retract handles when if the segment was degenerate
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (_is_drag_cancelled(event) && _segment_was_degenerate) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis // Magic Bezier Drag Equations follow!
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis // "weight" describes how the influence of the drag should be distributed
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis // among the handles; 0 = front handle only, 1 = back handle only.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis else if (t <= 0.5) weight = (pow((6 * t - 1) / 2.0, 3)) / 2;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis else if (t <= 5.0 / 6.0) weight = (1 - pow((6 * (1-t) - 1) / 2.0, 3)) / 2 + 0.5;
if (!second) return false;
_insertNode(false);
_insertNode(true);
setVisible(false);
if (take_selection) {
if (linear) {