15#include <glib/gi18n.h>
101 group->set_name(
"CanvasItemGroup:NodeTool");
122 data.node_data.handle_line_group->set_name(
"CanvasItemGroup:NodeTool:handle_line_group");
163 if (prefs->getBool(
"/tools/nodes/selcue")) {
167 if (prefs->getBool(
"/tools/nodes/gradientdrag")) {
231 for (
auto hp : nt->_helperpath_tmpitem) {
234 nt->_helperpath_tmpitem.clear();
235 std::vector<SPItem *> vec(selection->
items().begin(), selection->
items().end());
236 std::vector<std::pair<Geom::PathVector, Geom::Affine>> cs;
237 for (
auto item : vec) {
238 auto lpeitem = cast<SPLPEItem>(
item);
239 if (lpeitem && lpeitem->hasPathEffectRecursive()) {
242 std::vector<Geom::Point> selectedNodesPositions;
243 if (nt->_selected_nodes) {
245 for (
auto selectionNode : *selectionNodes) {
247 selectedNodesPositions.push_back(n->position());
260 helperpath->set_stroke(0x0000ff9a);
272 if (entry_name ==
"show_handles") {
275 }
else if (entry_name ==
"show_outline") {
278 }
else if (entry_name ==
"live_outline") {
281 }
else if (entry_name ==
"live_objects") {
284 }
else if (entry_name ==
"show_path_direction") {
287 }
else if (entry_name ==
"show_transform_handles") {
291 }
else if (entry_name ==
"single_node_transform_handles") {
295 }
else if (entry_name ==
"edit_clipping_paths") {
298 }
else if (entry_name ==
"edit_masks") {
309 std::set<Inkscape::UI::ShapeRecord> &s)
322 }
else if (
auto item = cast<SPItem>(obj)) {
332 if (s.insert(r).second) {
347 std::set<ShapeRecord> shapes;
360 return !shapes.contains(s);
363 for (
auto const &r : shapes) {
364 auto item = cast<SPItem>(r.object);
367 auto si = std::make_unique<ShapeEditor>(
_desktop, r.edit_transform);
369 it->second = std::move(si);
373 std::vector<SPItem *> vec(sel->
items().begin(), sel->
items().end());
393 if (!rubberband->isStarted()) {
406 auto const motion_w =
event.pos;
409 if (event.
modifiers & GDK_BUTTON1_MASK) {
410 if (rubberband->isStarted()) {
411 rubberband->move(motion_dt);
418 _(
"<b>Draw over</b> lines to select their nodes; release <b>%s</b> to switch to rubberband selection"), touch_path.c_str());
421 _(
"<b>Drag around</b> nodes to select them; press <b>%s</b> to switch to box selection"), touch_path.c_str());
425 }
else if (rubberband->isMoved()) {
435 if (!(event.
modifiers & GDK_SHIFT_MASK)) {
438 m.preSnap(scp,
true);
449 if (prefs->getBool(
"/tools/nodes/pathflash_enabled")) {
454 if (!prefs->getBool(
"/tools/nodes/pathflash_selected") && over_item && selection->includes(over_item)) {
464 auto shape = cast<SPShape>(over_item);
470 if (!shape->curveForEdit()) {
474 auto c = *shape->curveForEdit() * over_item->
i2dt_affine();
477 flash->set_stroke(over_item->highlight_color().toRGBA());
516 prefs->setBool(
"/tools/nodes/show_handles", !
show_handles);
526 case GDK_KEY_ISO_Left_Tab:
544 if (event.button != 1) {
548 auto const event_pt =
event.pos;
551 if (event.num_press == 1) {
557 rubberband->start(
_desktop, desktop_pt,
true);
561 }
else if (event.num_press == 2) {
566 if (!(event.
modifiers & GDK_SHIFT_MASK)) {
584 if (event.button != 1) {
588 if (rubberband->isStarted() && rubberband->isMoved()) {
615 if (event.num_press != 1 || event.button != 1) {
620 if (
auto &knotholder = se.second->knotholder) {
621 auto const point =
event.pos;
641 auto modifiers_change =
event.modifiersChange();
643 if (modifiers_change == 0) {
647 auto modifiers_after =
event.modifiers ^ modifiers_change;
652 C_(
"Node tool tip",
"<b>Shift</b>: drag to add nodes to the selection, "
653 "click to toggle object selection"));
656 C_(
"Node tool tip",
"<b>Shift</b>: drag to add nodes to the selection"));
673 auto nodestring = Glib::ustring::compose(
674 ngettext(
"<b>%1 of %2</b> node selected.",
"<b>%1 of %2</b> nodes selected.", total),
681 std::vector<Geom::Point> positions;
682 for (
auto selection_node : selection_nodes) {
683 if (selection_node->selected()) {
685 positions.push_back(n->position());
688 g_assert(positions.size() == 2);
689 const double angle = Geom::deg_from_rad(
Geom::Line(positions[0], positions[1]).angle());
692 nodestring += Glib::ustring::compose(_(
"Angle: %1°."),
698 auto const dyntip = Glib::ustring::compose(C_(
"Node tool tip",
699 "%1 Drag to select nodes, click to edit only this object (more: Shift)"),
704 auto const dyntip = Glib::ustring::compose(C_(
"Node tool tip",
705 "%1 Drag to select nodes, click to clear the selection"),
712 "Drag to select nodes, click to edit only this object"));
715 "Drag to select nodes, click to clear the selection"));
720 "Drag to select objects to edit, click to edit this object (more: Shift)"));
723 "Drag to select objects to edit"));
735 selection->setList(
items);
782 selection->toggle(item_clicked);
783 }
else if (!selection->includes(item_clicked)) {
784 selection->set(item_clicked);
Infinite line on a plane.
Sequence of contiguous curves, aka spline.
OptRect boundsFast() const
Get the approximate bounding box.
std::vector< Geom::PathVector > getCanvasIndicators(SPLPEItem const *lpeitem)
Return a vector of PathVectors which contain all canvas indicators for this effect.
void setCurrentZoom(double cZ)
void setSelectedNodePoints(std::vector< Geom::Point > sNP)
void setF(MessageType type, char const *format,...) G_GNUC_PRINTF(3
pushes a message on the stack using prinf-style formatting, and replacing our old message
A class to represent ways functionality is driven by shift modifiers.
SPItemRange items()
Returns a range of selected SPItems.
boost::enable_if< boost::is_base_of< SPObject, T >, void >::type addList(const std::vector< T * > &objs)
Adds the specified objects to selection, without deselecting first.
bool isEmpty()
Returns true if no items are selected.
Data type representing a typeless value of a preference.
Glib::ustring getEntryName() const
Get the last component of the preference's path.
bool getBool(bool def=false) const
Interpret the preference as a Boolean value.
static Preferences * get()
Access the singleton Preferences object.
static Rubberband * get(SPDesktop *desktop)
The set of selected SPObjects for a given document and layer model.
sigc::connection connectChanged(sigc::slot< void(Selection *)> slot)
Connects a slot to be notified of selection changes.
Class to store data for points which are snap candidates, either as a source or as a target.
Group of selected control points.
void selectArea(Geom::Path const &, bool invert=false)
Select all points inside the given rectangle (in desktop coordinates).
sigc::signal< void(std::vector< SelectableControlPoint * >, bool)> signal_selection_changed
set_type const & allPoints() const
void invertSelection()
Unselect all selected points and select all unselected points.
bool event(Inkscape::UI::Tools::ToolBase *tool, CanvasEvent const &event) override
Handle input event. Returns true if handled.
void showTransformHandles(bool v, bool one_node)
void clear()
Remove all points from the selection, making it empty.
void selectAll()
Select all points that this selection can contain.
Draggable point, the workhorse of on-canvas editing.
static sigc::signal< void(ControlPoint *)> signal_mouseover_change
Emitted when the mouseovered point changes.
An invisible point used to drag curves.
Manipulator that manages multiple path manipulators active at the same time.
void setItems(std::set< ShapeRecord > const &)
Change the set of items to edit.
void showOutline(bool show)
void showPathDirection(bool show)
sigc::signal< void()> signal_coords_changed
Emitted whenever the coordinates shown in the status bar need updating.
void setLiveObjects(bool set)
Set live object update status.
void setLiveOutline(bool set)
Set live outline update status.
void shiftSelection(int dir)
void insertNode(Geom::Point pt)
bool event(Inkscape::UI::Tools::ToolBase *tool, CanvasEvent const &event) override
Handle input event. Returns true if handled.
void showHandles(bool show)
void deleteNodes()
Delete nodes, use the preference to decide which mode to use.
To do: update description of desktop.
double current_zoom() const
Inkscape::CanvasItemGroup * getCanvasControls() const
void emit_control_point_selected(Inkscape::UI::ControlPointSelection *selection)
SPDocument * getDocument() const
Inkscape::Display::TemporaryItem * add_temporary_canvasitem(Inkscape::CanvasItem *item, int lifetime_msecs, bool move_to_bottom=true)
One should not keep a reference to the SPCanvasItem, the temporary item code will delete the object f...
Inkscape::CanvasItemGroup * getCanvasTemp() const
Geom::Affine const & dt2doc() const
Geom::Point point() const
Returns the mouse point in desktop coordinates; if mouse is outside the canvas, returns the center of...
SPItem * getItemAtPoint(Geom::Point const &p, bool into_groups, SPItem *upto=nullptr) const
SPNamedView * getNamedView() const
Inkscape::Selection * getSelection() const
void remove_temporary_canvasitem(Inkscape::Display::TemporaryItem *tempitem)
It is perfectly safe to call this function while the object has already been deleted due to a timeout...
Inkscape::UI::Tools::ToolBase * getTool() const
Geom::Affine const & w2d() const
Transformation from window to desktop coordinates (zoom/rotate).
std::vector< SPItem * > getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_hidden=false, bool take_insensitive=false, bool take_groups=true, bool enter_groups=false, bool enter_layers=true) const
Return list of items, contained in box.
Base class for visual SVG elements.
Geom::Affine i2dt_affine() const
Returns the transformation from item to desktop coords.
SPMask * getMaskObject() const
Geom::Affine i2doc_affine() const
Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
SPClipPath * getClipObject() const
SPObject is an abstract base class of all of the document nodes at the SVG document level.
void setup(SPDesktop const *desktop, bool snapindicator=true, SPObject const *item_to_ignore=nullptr, std::vector< Inkscape::SnapCandidatePoint > *unselected_nodes=nullptr)
Convenience shortcut when there is only one item to ignore.
Control point selection - stores a set of control points and applies transformations to them.
void pathvector_append(Geom::PathVector &to, Geom::PathVector const &pathv, bool use_lineto)
Append pathv to to.
void shift(T &a, T &b, T const &c)
Multi path manipulator - a tool component that edits multiple paths at once.
void selectNone(SPDesktop *desktop)
ShapeRole
Role of the shape in the drawing - affects outline display and color.
@ SHAPE_ROLE_CLIPPING_PATH
Glib::ustring format_classic(T const &... args)
bool mod_alt(unsigned modifiers)
void inspect_event(E &&event, Fs... funcs)
Perform pattern-matching on a CanvasEvent.
@ SNAPSOURCE_OTHER_HANDLE
bool mod_ctrl_only(unsigned modifiers)
bool mod_ctrl(unsigned modifiers)
bool mod_shift(unsigned modifiers)
Inkscape::ShapeEditor This is a container class which contains a knotholder for shapes.
Abstract base class for events.
unsigned modifiers
The modifiers mask immediately before the event.
unsigned modifiersAfter() const
Get the modifiers mask immediately after the event. (Convenience function.)
virtual EventType type() const =0
Return the dynamic type of the CanvasEvent.
Movement of the mouse pointer.
Inkscape::CanvasItemGroup * node_group
Inkscape::CanvasItemGroup * handle_group
Inkscape::CanvasItemGroup * handle_line_group
ControlPointSelection * selection
Inkscape::CanvasItemGroup * outline_group
Inkscape::CanvasItemGroup * dragpoint_group
Geom::Affine edit_transform