seltrans.cpp revision 070093a95d1f92b43b8bdbbff68d1515205349f3
280N/A#define __SELTRANS_C__
919N/A#ifdef HAVE_CONFIG_H
280N/A#include "document.h"
280N/A#include "sp-namedview.h"
280N/A#include "desktop-handles.h"
970N/A#include "desktop-style.h"
970N/A#include "selection.h"
1356N/A#include "select-context.h"
1356N/A#include "sp-item-transform.h"
280N/A#include "seltrans-handles.h"
1366N/A#include "seltrans.h"
280N/A#include "selection-chemistry.h"
911N/A#include "sp-metrics.h"
911N/A#include "display/sp-ctrlline.h"
280N/A#include "prefs-utils.h"
493N/Astatic void sp_sel_trans_handle_new_event(SPKnot *knot, NR::Point *position, guint32 state, gpointer data);
280N/Astatic gboolean sp_sel_trans_handle_request(SPKnot *knot, NR::Point *p, guint state, gboolean *data);
case GDK_MOTION_NOTIFY:
case GDK_KEY_PRESS:
return FALSE;
return TRUE;
return FALSE;
_grabbed(false),
_show_handles(true),
//_snap_bbox_type = SPItem::GEOMETRIC_BBOX; //TODO: Get this parameter from UI; hardcoded for the time being
NULL);
NULL);
if (_shandle[i]) {
if (_rhandle[i]) {
if (_chandle) {
if (_norm) {
if (_grip) {
if (_l[i]) {
_center = p;
_center_is_set = true;
_grabbed = true;
_changed = false;
if (_empty) {
_items_centers.push_back(std::pair<SPItem *, NR::Point>(it, it->getCenter())); // for content-dragging, we need to remember original centers
_point = p;
std::vector<NR::Point> snap_points_hull = selection->getSnapPointsConvexHull(); // Includes path nodes
_approximate_bbox = selection->bounds(SPItem::APPROXIMATE_BBOX); // Used for correctly scaling the strokewidth
if (_bbox) {
// There are two separate "opposites" (i.e. opposite w.r.t. the handle being dragged):
// The "opposite" in case of a geometric boundingbox always coincides with the "opposite" for the special points
// These distinct "opposites" are needed in the snapmanager to avoid bugs such as #1540195 (in which
_opposite_for_specpoints = (snap_points_bbox.min() + (snap_points_bbox.dimensions() * NR::scale(1-x, 1-y) ) );
/*std::cout << "Number of snap points: " << _snap_points.size() << std::endl;
std::cout << "Number of bbox points: " << _bbox_points.size() << std::endl;
if (_bbox) {
_changed = true;
_grabbed = false;
_show_handles = true;
if (_stamp_cache) {
if (_center) {
_center_is_set = true;
if (_center_is_set) {
if (!_empty) {
GSList *l;
if (_stamp_cache) {
l = _stamp_cache;
_stamp_cache = l;
l = l->next;
_chandle = sp_knot_new(_desktop, _("<b>Center</b> of rotation and skewing: drag to reposition; scaling with Shift also uses this center"));
_("<b>Squeeze or stretch</b> selection; with <b>Ctrl</b> to scale uniformly; with <b>Shift</b> to scale around rotation center"),
_("<b>Scale</b> selection; with <b>Ctrl</b> to scale uniformly; with <b>Shift</b> to scale around rotation center"));
_("<b>Skew</b> selection; with <b>Ctrl</b> to snap angle; with <b>Shift</b> to skew around the opposite side"),
_("<b>Rotate</b> selection; with <b>Ctrl</b> to snap angle; with <b>Shift</b> to rotate around the opposite corner"));
if (!_center_is_set) {
_center_is_set = true;
if (_empty) {
std::vector<NR::Point> snap_points_hull = selection->getSnapPointsConvexHull(); // Includes path nodes
/*std::cout << "Approximate BBox: " << _approximate_bbox->min() << " - " << _approximate_bbox->max() << std::endl;
std::cout << "Geometric BBox: " << selection->bounds(SPItem::GEOMETRIC_BBOX)->min() << " - " << selection->bounds(SPItem::GEOMETRIC_BBOX)->max() << std::endl;
if (!_bbox) {
_empty = true;
for (int i = 0; i < num; i++) {
for (int i = 0; i < num; i++) {
g_signal_connect(G_OBJECT(knot[i]), "event", G_CALLBACK(sp_seltrans_handle_event), (gpointer) &handle[i]);
static void sp_sel_trans_handle_new_event(SPKnot *knot, NR::Point *position, guint state, gpointer data)
static gboolean sp_sel_trans_handle_request(SPKnot *knot, NR::Point *position, guint state, gboolean *data)
case GTK_ANCHOR_CENTER:
case GTK_ANCHOR_CENTER:
NULL);
NULL);
void Inkscape::SelTrans::handleNewEvent(SPKnot *knot, NR::Point *position, guint state, SPSelTransHandle const &handle)
gboolean Inkscape::SelTrans::handleRequest(SPKnot *knot, NR::Point *position, guint state, SPSelTransHandle const &handle)
return TRUE;
} else if (_center) {
return TRUE;
return TRUE;
if (!_grabbed) {
if (!_grabbed) {
_changed = false;
static double sign(double const x)
using NR::X;
using NR::Y;
it,
it,
it,
it,
: NR_HUGE;
: NR_HUGE;
return TRUE;
gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, NR::Point &pt, guint state)
using NR::X;
using NR::Y;
case GDK_TOP_SIDE:
case GDK_BOTTOM_SIDE:
case GDK_LEFT_SIDE:
case GDK_RIGHT_SIDE:
return TRUE;
return FALSE;
it,
s[axis],
axis,
it,
s[axis],
axis,
it,
s[axis],
axis,
it,
s[axis],
axis,
return TRUE;
gboolean Inkscape::SelTrans::skewRequest(SPSelTransHandle const &handle, NR::Point &pt, guint state)
using NR::X;
using NR::Y;
return FALSE;
dim_a = X;
dim_b = Y;
dim_a = Y;
dim_b = X;
return FALSE;
if (snaps) {
dim_b);
dim_b);
degrees);
return TRUE;
double radians;
if (snaps) {
return TRUE;
using NR::X;
using NR::Y;
_message_context.setF(Inkscape::NORMAL_MESSAGE, _("Move <b>center</b> to %s, %s"), xs->str, ys->str);
return TRUE;
void sp_sel_trans_stretch(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, NR::Point &pt, guint state)
void sp_sel_trans_scale(Inkscape::SelTrans *seltrans, SPSelTransHandle const &, NR::Point &pt, guint state)
void sp_sel_trans_skew(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, NR::Point &pt, guint state)
void sp_sel_trans_rotate(Inkscape::SelTrans *seltrans, SPSelTransHandle const &, NR::Point &pt, guint state)
using NR::X;
using NR::Y;
case GDK_LEFT_SIDE:
case GDK_RIGHT_SIDE:
dim = X;
case GDK_TOP_SIDE:
case GDK_BOTTOM_SIDE:
dim = Y;
abort();
if (!_bbox) {
NR::Point p1 = _approximate_bbox->min() * (NR::translate(-scale_origin) * NR::Matrix(s) * NR::translate(scale_origin));
NR::Point p2 = _approximate_bbox->max() * (NR::translate(-scale_origin) * NR::Matrix(s) * NR::translate(scale_origin));
int transform_stroke = false;
NR::Matrix scaler = get_scale_transform_with_stroke (*_approximate_bbox, strokewidth, transform_stroke,
if (!_bbox) {
NR::Point p1 = _approximate_bbox->min() * (NR::translate(-_origin) * NR::Matrix(s) * NR::translate(_origin));
NR::Point p2 = _approximate_bbox->max() * (NR::translate(-_origin) * NR::Matrix(s) * NR::translate(_origin));
int transform_stroke = false;
NR::Matrix scaler = get_scale_transform_with_stroke (*_approximate_bbox, strokewidth, transform_stroke,
unsigned dim;
case GDK_SB_H_DOUBLE_ARROW:
case GDK_SB_V_DOUBLE_ARROW:
abort();
void sp_sel_trans_center(Inkscape::SelTrans *seltrans, SPSelTransHandle const &, NR::Point &pt, guint state)
if (alt) {
} else if (!shift) {
if (control) {
it,
dxy));
it,
dxy));
if (i->second) {
if (m < best) {
best = m;
if (control) {
_message_context.setF(Inkscape::NORMAL_MESSAGE, _("<b>Move</b> by %s, %s; with <b>Ctrl</b> to restrict to horizontal/vertical; with <b>Shift</b> to disable snapping"), xs->str, ys->str);